-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
spec: document promotion of methods from embedded aliases of unnamed types #66540
Comments
Personally, I don't find the promotion to be surprising.
Which IMO does say that the method is promoted. OTOH it also says two paragraphs later
Which restricts promoted methods in the method set to those of named types. So, arguably, |
I was surprised to learn that embedding a non-named type was legal at all, so my intuition may not be a good guide here. The specified (as opposed to implemented) behavior of promotion makes more sense to me because I have always thought of aliases as being largely melted away. But surprising or not, the spec disallows it (see below).
That's the definition of promotion, not a description of when it applies. The paragraph that follows explains the mechanism:
and the definition of named types is:
So, an alias for (say) a slice type is not a named type, though it is a legal anonymous field, according to:
|
I believe "named type" should be "type name" here. The "named type` term returned back to spec at Go 1.18. |
Nope. Funnily enough, I proposed the "type name" phrasing. But @griesemer opted for "named type" instead. Maybe he has an opinion. IMO if the spec and implementation have been disagreeing for several Go versions, the spec is wrong. (I also completely forgot that I reported it and I used exactly @adonovan's example to argue for that change) |
The embedding-related wording is really subtle. I still think there are some inaccuracies there: #22005 |
Per this phrase, where we now use "named type" (formerly "defined type"), it seems to me that the implementation is not correct. Per the spec, an alias is only a named type type if it aliases a named type, such as a defined type:
But in this case Can we change (fix) this? Maybe. It seems that the chance that code such exists in the wild is pretty slim; at the very least it's not going to be a lot of code. But we'd need to do a little investigation first. |
@griesemer I'll point out again that in the issue I linked above I observed this behavior of promoted method and prompted that change. So IMO that change was made specifically to bring the spec in line with this behavior. I don't remember if I filed that issue based on a real world example. At the time, I suggested "type name", specifically because it includes aliases that are not named types (and thus to address my example). I'm not sure why you chose "named type" instead; neither the issue description, nor the commit message mention. |
Per the fact that an interface can embed any types, including struct literals, maybe the current implementation is preferred? |
I used this in a project for my job, no source available. It is convenient and makes sense. |
@Merovius I see. The commit message says "The types of embedded fields must be named, but they don't need to be defined types" which implies that I meant any type with a name (i.e., with a type name). Yet, the change mentions named type, which excludes aliases denoting type literals, and - which I believe - was my intention as it simply used the more general term (named type) for the original term (defined type). Sigh. The implementation does something else, the spec says something else in most places, and so maybe this issue is fixed by simply changing "named type" to "type name" in "Given a struct type S and a name type T, ...". (It's really unfortunate, and a mistake in my mind, that we allowed aliases for type literals. There was no need for it, and it needlessly complicates/confuses things.) |
That would solve the inconsistency, but it seems like a pragmatic admission of defeat relative to your original intent, which makes more sense to me.
Inessential they may be, but type aliases for unnamed types are quite useful as documentable abbreviations for verbose types that have no need for declared methods, function types in particular. |
Too late for 1.23. Moving to 1.24. |
This issue is currently labeled as early-in-cycle for Go 1.24. |
Added to proposal process to decide what the right answer is. It may be that this has been this way for so long that the spec should be considered wrong. |
This proposal has been added to the active column of the proposals project |
FWIW to me, the behavior as implemented is still correct.
Personally, I find it honestly puzzling that this would seem the wrong behavior. I would find it a bit confusing to have a type embedded into a struct and not get its methods promoted - just because I happen to refer to it via an alias. Given that changing the implemented behavior is a breakage I'm wondering what the arguments in favor of doing so even are. ISTM the burden of evidence to break compatibility should be relatively high. Are there technical reasons to change the compiler here, beyond "I find the current behavior surprising" (and I'd claim that, if it took 14 Go versions to be surprised by that, it can't be that big of a problem)? |
It sounds like everyone agrees that we can't and shouldn't change the behavior. The spec needs to be updated, and @adonovan and @griesemer will work on the wording. |
No API changes here, so taking this out of the proposal process. |
Change https://go.dev/cl/603958 mentions this issue: |
No change in consensus, so accepted. 🎉 We ended up deciding this was a spec mistake and not a proposal change, but marking this accepted as the best approximation to the proposal outcome. |
@griesemer Do you think there's anything to be said in Go 1.24 release notes about this? Or is it fine not to mention it there since this a clarification only? Thanks. |
@dmitshur I don't think this warrants a release note. It's not something one would casually notice in the first place, nor is it a change in behavior. The spec change is really just about being more precise about a behavior that existed from the beginning when alias types were introduced. Thanks. |
I was surprised to learn yesterday that it is legal to embed an alias type whose underlying type is not a defined type.
This is legal according to the spec; there is supposed to be no promotion of methods from the alias's underlying type.
And yet promotion does occur:
https://go.dev/play/p/_bJZeiZW-cW
I expect go/types has the same issue.
The text was updated successfully, but these errors were encountered: