What is the URL of the page with the issue?
https://go.dev/ref/spec#Struct_types
What is your user agent?
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Screenshot
No response
What did you do?
Specification for the promoted methods of the embedded struct field states:
Given a struct type S and a named type T, promoted methods are included in the method set of the struct as follows: - If S contains an embedded field T, the method sets of S and S both include promoted methods with receiver T. The method set of S also includes promoted methods with receiver T. - If S contains an embedded field T, the method sets of S and S both include promoted methods with receiver T or T.
However, promoted methods won't be included in 2 cases: 1. if the method with the same name (identifier) is already defined for the struct type in which we embed 2. if two (or more) methods of the embedded fields that would be promoted have the same method name (identifier)
What did you see happen?
I created an example for each case. Note that only method names are the same, but the signatures are different.
First case:
type T struct{}
func (T) Method(int) string { return "" }
type S struct {
T
}
func (S) Method() {}
type I interface {
Method(int) string
}
func main() {
var _ I = S{} // InvalidIfaceAssign error
}
Second case:
type T1 struct{}
func (T1) Method(int) string { return "" }
type T2 struct{}
func (T2) Method(float32) string { return "" }
type S struct {
T1
T2
}
type I interface {
Method(int) string
}
func main() {
var _ I = S{} // InvalidIfaceAssign error
}
What did you expect to see?
I expect to see these two constrains for the promoted methods included in the specification.
Comment From: gabyhelp
Related Issues and Documentation
- spec: clarify rules for uniqueness of method names #14309 (closed)
- spec: Embedded fields don't need to be defined types #41687 (closed)
- The method set of S shouldn't include promoted methods with receiver *T when S contains an embedded field T #39255 (closed)
- spec: incorrect requirement for the embedded field #69460 (closed)
- spec: a possible inconsistency for promoted methods #34454 (closed)
- spec: Interface Types defines embedding as method enumeration, but private methods are treated differently #7886 (closed)
- spec: Promoted type T gives access to *T receiver. #10581 (closed)
- The Go Programming Language Specification > Types > Struct types
- spec: clarify method sets and recursive promotions #15708
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Comment From: TutiFrouti
In my opinion it is not duplicate of the #14309. Specification states that the method names must be unique in the method set. I agree with that. Since the methods won't even be promoted in either my or the #14309 example, these programs are valid and should compile (if I omit assigning).
I am talking here about adding note about cases when methods won't even be promoted and thus won't be part of the method set.
Comment From: adonovan
See the spec wording on Selectors and the concept of depth. I think the first rule below addresses both of your concerns:
A selector f may denote a field or method f of a type T, or it may refer to a field or method f of a nested embedded field of T. The number of embedded fields traversed to reach f is called its depth in T. The depth of a field or method f declared in T is zero. The depth of a field or method f declared in an embedded field A in T is the depth of f in A plus one. The following rules apply to selectors: For a value x of type T or *T where T is not a pointer or interface type, x.f denotes the field or method at the shallowest depth in T where there is such an f. If there is not exactly one f with shallowest depth, the selector expression is illegal.
Comment From: TutiFrouti
@adonovan I'm talking about the rules for adding methods of the embedded fields to the method set of the structure we're embedding into. It is not related to the selectors nor illegal selector expressions.
Comment From: adonovan
I'm talking about the rules for adding methods of the embedded fields to the method set of the structure we're embedding into.
The spec calls this process "promotion".
It is not related to the selectors nor illegal selector expressions.
In fact it is. The method set of the outer struct type is the set of method selectors x.f that are legal, and the rules for promotion determine what is legal. For example, "x.f denotes the field or method at the shallowest depth in T where there is such an f. If there is not exactly one f with shallowest depth, the selector expression is illegal."
Comment From: TutiFrouti
@adonovan Amazing explanation, thanks. Unfortunately, it is not explained in that way in the specification. Perhaps the following should be included in the specification, it's very clear and useful (I cite you):
The method set of the outer struct type is the set of method selectors x.f that are legal, and the rules for promotion determine what is legal.
EDIT: Nvm, I found something similar:
A field or method f of an embedded field in a struct x is called promoted if x.f is a legal selector that denotes that field or method f.