-
Notifications
You must be signed in to change notification settings - Fork 18.1k
proposal: Go 2: make := always shadow variables #65700
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
Comments
I hit enter for a line break on the "Performance Costs" part of the form while writing this and it submitted the incomplete form. |
We are extremely unlikely to adopt a language change that is not strictly backward compatible. The change to loop variable scope in 1.22 was an exception adopted only because a study of many examples showed that it fixed a lot of code while breaking almost none. I don't see how that kind of argument applies here. |
This is a very dangerous incompatible breaking change: there is probably a very large corpus out there that, for instance, uses |
FWIW, a transition could be made more safely across two releases by first removing the partially-declaring mode of Even without adding same-block shadowing, the partially-declaring mode sticks out to me as a bit of a complexity wart in the language. In my experience, it's almost exclusively used with one new variable and one reused |
But that would break an enormous amount of existing working code. That is a non-starter. We simply aren't going to adopt this proposal. I'm going to close it. Sorry. |
Damn, this is unfortunate. Shadow-chaining would be an awesome feature to have, it would make things not require explicit names, and would make it a fairly good emulation of a chain operator some languages have thing := 123 // type: int
thing := doSomething(thing) // type: string
thing := doAnotherOperation(thing) // type: SomeStruct
return thing It would be at least pretty cool for v2 of Go (if it ever comes). |
Uh oh!
There was an error while loading. Please reload this page.
Go Programming Experience
Experienced
Other Languages Experience
TypeScript, Java, Kotlin, Flow, Hack
Related Idea
Has this idea, or one like it, been proposed before?
There are other proposals that involve changing the behavior of
:=
, but I haven't found any that would make shadowing more permissive:Does this affect error handling?
Shadowing variables in the same block would make multiline err checks easier to add/remove/reorder.
Example:
Because
err
is shadowed, the statements don't need to be edited depending on whether they're the first to declareerr
.Is this about generics?
No
Proposal
When a variable that has already been declared is listed on the LHS of
:=
, always shadow it.There are two primary use cases that this would simplify. The first is multiline-form error checks (see the error handling section). The second (and much more compelling) use case is for handling type-changing transformations to collections. When using functional programming paradigms, composing operations is one of the biggest pain points with the current implementation of generics. Being able to repeatedly declare the same variable with different types would help alleviate that pain without adding new syntax to support composition.
The example is a little bit contrived, but it can be genuinely difficult to come up with succinct and descriptive names for the intermediate steps when composing several collection operations together. Shadowing the original variable name has a couple other advantages:
Language Spec Changes
Under "Declarations and scope"
this paragraph:
becomes
Under "Declarations and scope"
this paragraph:
becomes
Under "Short variable declarations"
this paragraph is removed:
Informal Change
No response
Is this change backward compatible?
No.
Because shadowing changes the variable type, this change could result in some variable types being downgraded from interfaces to concrete types:
Because shadowing would change access semantics, this change could also break some corner cases with pointers and goroutines:
It's fairly subtle and actual incompatibilities might be rare enough to justify adding it, similar to the 1.22 changes to
for
variables.Orthogonality: How does this change interact or overlap with existing features?
No response
Would this change make Go easier or harder to learn, and why?
In my opinion, this would make Go easier to learn because it would reduce the number of possible outcomes from using
:=
. After this change, you can say that variables on the LHS of:=
are always shadowed if they already exist in the current scope.With the current behavior, you have to find which block each variable on the LHS was originally declared in to determine whether
:=
will shadow or reuse.Cost Description
The biggest adoption cost would likely be in the changes that would need to be made to the
types
package. TheScope.Lookup
andScope.LookupParent
methods both assume that a variable can only be declared once per block, so they would need to be deprecated and redefined as returning either the first or last declaration of the named identifier.Changes to Go ToolChain
any tool that uses
types
would probably need to be updatedPerformance Costs
The run time cost should be fairly small since stack locations could still be reused if the shadowed variable doesn't escape and the new variable has the same size.
Depending on implementation details, compiler performance cost could go either way. There's potential for it to be a perf improvement since the logic of parsing
:=
statements wouldn't require doing a lookup against the set of declared variables any more.Prototype
No response
The text was updated successfully, but these errors were encountered: