golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.09k stars 17.68k forks source link

spec: clarify intended behaviour of method values using promoted methods #6475

Open stevenblenkinsop opened 11 years ago

stevenblenkinsop commented 11 years ago
What steps will reproduce the problem?

Run this program:
http://play.golang.org/p/pQb9VlrLkv

What is the expected output?

Based on the spec, it's not clear if this should print "1 1" or "1
2".

What do you see instead?

Running the program in the go playground prints "1 1".

Which compiler are you using (5g, 6g, 8g, gccgo)?
Go playground.

Which operating system are you using?
n/a

Which version are you using?  (run 'go version')
go1.1.2

Please provide any additional information below.

The spec mentions auto-referencing/dereferencing the x in method value expression x.M as
necessary so that it matches the kind of receiver M has, which is why the call to tFn is
expected to print 1. It doesn't mention resolving x to the value that will ultimately
used to initialize the receiver-parameter visible in the body of the method M. Instead,
it says that x is evaluated and saved to be used as the receiver. Note that receiver has
multiple meanings used in the spec, depending on whether you're talking about the
receiver-argument or the receiver-parameter.

Depending on the intended behaviour, this may also be a compiler bug.
adg commented 11 years ago

Comment 1:

This is definitely what I would expect to happen, and IMO the compiler is doing the
right thing.
Perhaps a small change to the spec is necessary, to mention the possibility of
dereferencing x in x.M.

Owner changed to @griesemer.

Status changed to Accepted.

stevenblenkinsop commented 11 years ago

Comment 2:

The behaviour of sFn seems consistent with the behaviour of iFn logically, I just wasn't
sure if it was expected based on the wording of the spec. I was checking through the
spec to see how the term "receiver" was used because of a topic I posted to the mailing
list, and happened upon this.
It already says that x in x.M will be dereferenced to match the receiver of the
function. Dereferencing just doesn't normally mean traversing anonymous fields. I
suppose the current behaviour could be justified using the "x.f is shorthand for
(*x.A).f" rule, but nowhere else is the literal expansion of this "shorthand"
semantically significant, that I can think of. If this is the basis for the current
behaviour, then it bears mentioning along with auto-reference/dereference, especially
since auto-dereference is just a special case of it.
I didn't think it was worth mentioning, but the other behaviour (observing the change to
*t rather than not) is observed when an interface is involved:
http://play.golang.org/p/993ZmY8324
But I was fairly certain this was expected based on both the language spec and how
interfaces normally behave as an opaque barrier between static and dynamic dispatch of
methods.
stevenblenkinsop commented 11 years ago

Comment 3:

The current behaviour is also consistent with the behaviour of defer:
http://play.golang.org/p/oOrplS9704
rsc commented 10 years ago

Comment 4:

Labels changed: added go1.3maybe.

rsc commented 10 years ago

Comment 5:

Labels changed: added release-none, removed go1.3maybe.

rsc commented 10 years ago

Comment 6:

Labels changed: added repo-main.

griesemer commented 10 years ago

Comment 7:

The implementation is correct. The spec sections on field/method selectors and method
values need to be cleaned up and be more precise.

Labels changed: added release-go1.4, documentation, removed release-none.

rsc commented 10 years ago

Comment 8:

Labels changed: added release-go1.4maybe, removed release-go1.4.

rsc commented 10 years ago

Comment 9:

Labels changed: added release-go1.5, removed release-go1.4maybe.