-
Notifications
You must be signed in to change notification settings - Fork 18k
spec: add example for method value in case of embedded method #47863
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 mean, immediately. An implementation might delay the expansion as needed. |
I think it must, according to following lines from the spec:
|
I agree the correct semantics are to print |
Change https://golang.org/cl/344209 mentions this issue: |
It is not very clear what the meaning of the "denote" words used in the two rules. Must expand to immediately or not? package main
type (
T int
S struct{ *T }
I interface { M() }
)
func (t T) M() { print(t) }
var (
t = new(T)
s = S{T: t}
i I = &s
)
func main() {
g := s.M // expand immediately
h := i.M // expand with a delay
*t = 5
g() // 0
h() // 5
} |
I personally recommend to define "denote" as "expand with a delay", to simplify many explanations. We can view the current gc implementation as a result of considering program performance. |
@go101 I dont see any inconsistent. "i.M" evaluated the value of "i", and expand to the interface method "I.M". The actual relevant part in spec is Method Values:
|
@cuonglm |
"Denote" in those paragraphs isn't explaining any dynamic behavior. It's just explaining what field/method is associated with a particular selector expression. In go/types terminology, it's explaining the relationship represented by Info.Selections. The section @cuonglm quotes is indeed the part that explains the dynamic behavior. Moreover, I believe the sentences:
are meant to describe the behavior in question (i.e., that the receiver argument is "expanded immediately" in your terminology). However, I think the examples could better demonstrate this. |
The dynamic value of an interface is often hard to determined at compile time. So it is hard to recored the dynamic type into in Info.Selections. So maybe the description of the rule 2 should be also tweaked, |
Another problem needs to be clarified is: does the type type T int
func (t T) M() { print(t) }
type S struct{ *T } @cuonglm's opinion is the type If |
@go101 To clarify, since when your opinion is about the spec, then
Quote from the embedded part:
I can't find any place in the spec can be interpreted that
I also show you a https://play.golang.org/p/5LdUMIoKaQd But you refused because:
and:
which I also don't agree. If we're talking about the gc implementation, then yes. The compiler does generate wrapper method |
The https://golang.org/ref/spec#Method_sets section says clearly:
So I think the spec admits that there is a method I don't care about whether or not |
@go101 seems you missed some sentences after that one:
It's not about expanding or not, it's about the receiver of the method must be evaluated. Thus receiver of "s.M" is "s.(*t)" must be evaluated. Adding implicit "M" for "S" actually make everything more complicated. |
OK. So a promoted method of I think then the following contents need to be tweaked:
It doesn't consider the case
Here, the "actual method" wording also doesn't consider promoted method cases. |
I don't follow this, the spec clearly state that
Same here, I don't follow. In your case,
The only place in the spec that mention
|
It is not the line, the inaccuracy is in this line
The spec says |
Do you mean the inaccuracy is the word
So it covers both T's own methods and promoted method.
Yes. but what's the problem? As @mdempsky explained above, that part does not explain the dynamic behavior, It's just explaining what field/method is associated with a particular selector expression. |
No, I mean this: "The expression x is evaluated and saved".
Here the "actual method" might be a "promoted method", and if the dynamic value is a |
Why is this inaccuracy?
I don't see the conflicts, either:
Is there a S's own method named So the actual method with name |
Okay, let's use the |
Okay, we use the |
Here's how I understand method values: If If Sorry, I'm too confused with all the back and forth to understand where exactly the confusion is. |
Yup, I have the same feel. @go101 since when this issue is now closed, would you mind opening other issue to discuss about places where you think are still confused in the spec. |
Personally, I still think the spec is not clear and even contains conflicts, as explained above. But okay. Something remaining to do:
|
The Selectors section in spec has an example to state that for
s
of typeS
, whereT
is an embedded field ofS
, andT
has methodM
, thens.M()
is a shorthand fors.T.M()
:But it lacks of the example where embedded field is use as method value, thus user can interpret that
f := p.M0
is not a shorthand off := ((*p).T0).M0
.I think we should add an example for method value to prevent that confusion.
I filed this issue after long discussion with @go101 about the behavior of this program:
I think any Go compiler implementation must ensure the output is
00
to conform with the spec, but @go101 disagree, becauses.M
is not guaranteed to expand tos.T.M
.Quote from @go101:
The text was updated successfully, but these errors were encountered: