-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
math/big: document that shallow copies of big.Int/Rat/Float are not supported #28423
Comments
You're depending on the behavior of shallow copies of
If instead you do:
It should work correctly. @griesemer : Is this documented anywhere? I didn't see it in the |
This is working as intended; and @randall77 's suggested change would be the correct approach here. The ModInverse implementation changed; in the past it created a new underlying slice to represent the result of ModInverse, and thus didn't change int32Prime's value (which shared the same underlying array). Now it does, and consequently, int32Prime changes as well. Shallow copies are definitively not supported. I'll add documentation. |
Thanks @griesemer @randall77. |
I don't think this warrants a note in the release notes - besides that we fixed a bug in ModInverse. None of the math/big code operates on big.Int values; all operations take pointers. The implementation of a big.Int is completely opaque, and nowhere does it say that one might safely shallow copy it: In general, making shallow copies of exported types is not a good idea unless explicitly permitted. This is true for every package, not just math/big. |
The problem is here:
https://golang.org/doc/go1compat#expectations also says nothing about the compatibility issue of shallow copy, which IMHO means that if making a shallow copy works, it should continue work in all future releases in Go 1. Anyway, I'll be more cautious when making shallow copies of exported types. |
@QuantumGhost You're right that the documentation probably should say how to properly make a copy of a big.Int - after all it's a (mostly) abstract data type and should support this operation. Which I believe this issue should be about. Shallow copy may have worked for the specific operation and arguments, but in general shallow copying won't work at all with big.Int (or any of big.Rat or big.Float). It's really a lucky coincidence that it did work. But as I said before, unless you know the exact details of an abstract data type, making a shallow copy is usually a bad idea. If we had a reliable mechanism to disallow copies, we'd be using it. |
Note that shallow copies have been broken forever, and in ways that have nothing to do with
This prints |
Thanks for mentioning this @randall77. |
Change https://golang.org/cl/145537 mentions this issue: |
Is this the sort of thing that |
@dgryski Yes. Or one could just embed a sync.Mutex into the Int/Rat/Float objects. I thought about it, but I'm not sure it's necessary. |
FYI adding |
What version of Go are you using (
go version
)?go version go1.11.1 darwin/amd64
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?What did you do?
go playground
Run this code under 1.10 and 1.11 respectively.
go 1.10 prints
Not Changed
go 1.11 prints
Changed!
What did you expect to see?
The value of
int32Prime
should not be changed.What did you see instead?
The value of
int32Prime
changed.The text was updated successfully, but these errors were encountered: