diff options
author | Robert Griesemer <gri@golang.org> | 2014-11-11 13:19:47 -0800 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2014-11-11 13:19:47 -0800 |
commit | 40818cfe1c3601a8b88d6935e255064aab07679b (patch) | |
tree | a98a16e291fb14b4bab478601c22896548866d54 | |
parent | 0f8cd1438d46ecf7393305e8981857b940f50ef4 (diff) | |
download | go-40818cfe1c3601a8b88d6935e255064aab07679b.tar.gz go-40818cfe1c3601a8b88d6935e255064aab07679b.zip |
spec: method selectors don't auto-deref named pointer types
Language clarification.
The existing rules for selector expressions imply
automatic dereferencing of pointers to struct fields.
They also implied automatic dereferencing of selectors
denoting methods. In almost all cases, such automatic
dereferencing does indeed take place for methods but the
reason is not the selector rules but the fact that method
sets include both methods with T and *T receivers; so for
a *T actual receiver, a method expecting a formal T
receiver, also accepts a *T (and the invocation or method
value expression is the reason for the auto-derefering).
However, the rules as stated so far implied that even in
case of a variable p of named pointer type P, a selector
expression p.f would always be shorthand for (*p).f. This
is true for field selectors f, but cannot be true for
method selectors since a named pointer type always has an
empty method set.
Named pointer types may never appear as anonymous field
types (and method receivers, for that matter), so this
only applies to variables declared of a named pointer
type. This is exceedingly rare and perhaps shouldn't be
permitted in the first place (but we cannot change that).
Amended the selector rules to make auto-deref of values
of named pointer types an exception to the general rules
and added corresponding examples with explanations.
Both gc and gccgo have a bug where they do auto-deref
pointers of named types in method selectors where they
should not:
See http://play.golang.org/p/c6VhjcIVdM , line 45.
Fixes #5769.
Fixes #8989.
LGTM=r, rsc
R=r, rsc, iant, ken
CC=golang-codereviews
https://golang.org/cl/168790043
-rw-r--r-- | doc/go_spec.html | 68 |
1 files changed, 42 insertions, 26 deletions
diff --git a/doc/go_spec.html b/doc/go_spec.html index 050c06465d..ca0deb56a3 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ <!--{ "Title": "The Go Programming Language Specification", - "Subtitle": "Version of October 27, 2014", + "Subtitle": "Version of November 11, 2014", "Path": "/ref/spec" }--> @@ -2521,30 +2521,40 @@ The following rules apply to selectors: <ol> <li> For a value <code>x</code> of type <code>T</code> or <code>*T</code> -where <code>T</code> is not an interface type, +where <code>T</code> is not a pointer or interface type, <code>x.f</code> denotes the field or method at the shallowest depth in <code>T</code> where there is such an <code>f</code>. If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code></a> with shallowest depth, the selector expression is illegal. </li> + <li> -For a variable <code>x</code> of type <code>I</code> where <code>I</code> +For a value <code>x</code> of type <code>I</code> where <code>I</code> is an interface type, <code>x.f</code> denotes the actual method with name -<code>f</code> of the value assigned to <code>x</code>. +<code>f</code> of the dynamic value of <code>x</code>. If there is no method with name <code>f</code> in the <a href="#Method_sets">method set</a> of <code>I</code>, the selector expression is illegal. </li> + +<li> +As an exception, if the type of <code>x</code> is a named pointer type +and <code>(*x).f</code> is a valid selector expression denoting a field +(but not a method), <code>x.f</code> is shorthand for <code>(*x).f</code>. +</li> + <li> In all other cases, <code>x.f</code> is illegal. </li> + <li> If <code>x</code> is of pointer type and has the value <code>nil</code> and <code>x.f</code> denotes a struct field, assigning to or evaluating <code>x.f</code> causes a <a href="#Run_time_panics">run-time panic</a>. </li> + <li> If <code>x</code> is of interface type and has the value <code>nil</code>, <a href="#Calls">calling</a> or @@ -2554,18 +2564,6 @@ causes a <a href="#Run_time_panics">run-time panic</a>. </ol> <p> -Selectors automatically <a href="#Address_operators">dereference</a> -pointers to structs. -If <code>x</code> is a pointer to a struct, <code>x.y</code> -is shorthand for <code>(*x).y</code>; if the field <code>y</code> -is also a pointer to a struct, <code>x.y.z</code> is shorthand -for <code>(*(*x).y).z</code>, and so on. -If <code>x</code> contains an anonymous field of type <code>*A</code>, -where <code>A</code> is also a struct type, -<code>x.f</code> is shorthand for <code>(*x.A).f</code>. -</p> - -<p> For example, given the declarations: </p> @@ -2574,13 +2572,13 @@ type T0 struct { x int } -func (recv *T0) M0() +func (*T0) M0() type T1 struct { y int } -func (recv T1) M1() +func (T1) M1() type T2 struct { z int @@ -2588,9 +2586,13 @@ type T2 struct { *T0 } -func (recv *T2) M2() +func (*T2) M2() -var p *T2 // with p != nil and p.T0 != nil +type Q *T2 + +var t T2 // with t.T0 != nil +var p *T2 // with p != nil and (*p).T0 != nil +var q Q = p </pre> <p> @@ -2598,13 +2600,27 @@ one may write: </p> <pre> -p.z // (*p).z -p.y // ((*p).T1).y -p.x // (*(*p).T0).x +t.z // t.z +t.y // t.T1.y +t.x // (*t.TO).x + +p.z // (*p).z +p.y // (*p).T1.y +p.x // (*(*p).T0).x + +q.x // (*(*q).T0).x (*q).x is a valid field selector + +p.M2() // p.M2() M2 expects *T2 receiver +p.M1() // ((*p).T1).M1() M1 expects T1 receiver +p.M0() // ((&(*p).T0)).M0() M0 expects *T0 receiver, see section on Calls +</pre> -p.M2() // (*p).M2() -p.M1() // ((*p).T1).M1() -p.M0() // ((*p).T0).M0() +<p> +but the following is invalid: +</p> + +<pre> +q.M0() // (*q).M0 is valid but not a field selector </pre> |