summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2008-10-23 12:04:45 -0700
committerRobert Griesemer <gri@golang.org>2008-10-23 12:04:45 -0700
commit071c91bf48209cdad1a8099b82b2b3c867efe9d5 (patch)
treeff1a87feeba942f5b75e77e87cee35f086aea97f /doc
parent8d3a3dd9040fa3e5b881dd3f3b09172b1a03a4a9 (diff)
downloadgo-git-071c91bf48209cdad1a8099b82b2b3c867efe9d5.tar.gz
First cut at incorporating anonymous fields of pointer types into the
spec. I have deliberately removed the wording about receivers where it was before because I think it needs to be more precise. There is a TODO. DELTA=90 (54 added, 0 deleted, 36 changed) OCL=17597 CL=17716
Diffstat (limited to 'doc')
-rw-r--r--doc/go_spec.txt108
1 files changed, 81 insertions, 27 deletions
diff --git a/doc/go_spec.txt b/doc/go_spec.txt
index ed279ce7e2..585cfbf73a 100644
--- a/doc/go_spec.txt
+++ b/doc/go_spec.txt
@@ -4,7 +4,7 @@ The Go Programming Language Specification (DRAFT)
Robert Griesemer, Rob Pike, Ken Thompson
----
-(October 20, 2008)
+(October 23, 2008)
This document is a semi-formal specification of the Go systems
@@ -843,8 +843,8 @@ Types may be ``complete'' or ''incomplete''. Basic, pointer, function and
interface types are always complete (although their components, such
as the base type of a pointer type, may be incomplete). All other types are
complete when they are fully declared. Incomplete types are subject to
-usage restrictions; for instance a variable type cannot be an incomplete
-type.
+usage restrictions; for instance the type of a variable must be complete
+where the variable is declared.
CompleteType = Type .
@@ -1118,20 +1118,29 @@ types (§Types).
f *();
}
-A struct may contain ``anonymous fields'', which are declared with
-a type name but no explicit field identifier. Instead, the unqualified type
-name acts as the field identifier. Anonymous fields must not be interface types.
+A struct may contain ``anonymous fields'', which are declared with a type
+but no explicit field identifier. An anonymous field type must be specified as
+a type name "T", or as a pointer to a type name ``*T'', and T itself may not be
+a pointer or interface type. The unqualified type acts as the field identifier.
- // A struct with two anonymous fields of type T1 and P.T2
+ // A struct with four anonymous fields of type T1, *T2, P.T3 and *P.T4
struct {
T1; // the field name is T1
- P.T2; // the field name is the unqualified type name T2
+ *T2; // the field name is T2
+ P.T3; // the field name is the unqualified type name T3
+ *P.T4; // the field name is the unqualified type name T4
x, y int;
}
The unqualified type name of an anonymous field must not conflict with the
field identifier (or unqualified type name for an anonymous field) of any
-other field within the struct.
+other field within the struct. The following declaration is illegal:
+
+ struct {
+ T; // conflicts with anonymous field *T and *P.T
+ *T; // conflicts with anonymous field T and *P.T
+ *P.T; // conflicts with anonymous field T and *T
+ }
Fields and methods (§Method declarations) of an anonymous field become directly
accessible as fields and methods of the struct without the need to provide the
@@ -1570,32 +1579,77 @@ A primary expression of the form
x.f
denotes the field or method f of the value denoted by x (or of *x if
-x is of pointer type). The identifier f is called the ``selector''.
-The following rules apply:
+x is of pointer type). The identifier f is called the (field or method)
+``selector''.
+
+A selector f may denote a field f declared in a type T, or it may refer
+to a field f declared in a nested anonymous field of T. Analogously,
+f may denote a method f of T, or it may refer to a method f of the type
+of a nested anonymous field of T. The number of anonymous fields traversed
+to get to the field or method is called its ``depth'' in T.
+
+More precisely, the depth of a field or method f declared in T is zero.
+The depth of a field or method f declared anywhere inside
+an anonymous field A declared in T is the depth of f in A plus one.
+
+The following rules apply to selectors:
+
+1) For a value x of type T or *T where T is not an interface type,
+x.f denotes the field or method at the shallowest depth in T where there
+is such an f. The type of x.f is the type of the field or method f.
+If there is not exactly one f with shallowest depth, the selector
+expression is illegal.
+
+2) For a variable x of type I or *I where I is an interface type,
+x.f denotes the actual method with name f of the value assigned
+to x if there is such a method. The type of x.f is the type
+of the method f. If no value or nil was assigned to x, x.f is illegal.
+
+3) In all other cases, x.f is illegal.
-For x of type S or *S where S is a struct type (§Struct types):
+Thus, selectors automatically dereference pointers as necessary. For instance,
+for an x of type *T where T declares an f, x.f is a shortcut for (*x).f.
+Furthermore, for an x of type T containing an anonymous field A declared as *A
+inside T, and where A contains a field f, x.f is a shortcut for (*x.A).f
+(assuming that the selector is legal in the first place).
+
+The following examples illustrate selector use in more detail. Given the
+declarations:
+
+ type T0 struct {
+ x int;
+ }
+
+ func (recv *T0) M0()
+
+ type T1 struct {
+ y int;
+ }
+
+ func (recv T1) M1()
+
+ type T2 struct {
+ z int;
+ T1;
+ *T0;
+ }
- 1) If f is declared as a (named or anonymous) field of S then x.f denotes
- that field.
+ func (recv *T2) M2()
- 2) If f is declared (or forward-declared) as a method of S textually
- before x.f then x.f denotes that method and x becomes the receiver
- of f.
+ var p *T2; // with p != nil and p.T1 != nil
- 3) Otherwise, if there is single anononymous field A of S such that
- x.A.f denotes a valid field according to 1) or 2), then x.f is
- a shortcut for x.A.f, and x.A becomes the receiver of f.
- If there is none or more then one anonymous field of S satisfying
- this criterion, x.f is illegal.
+we can write:
+ p.z // (*p).z
+ p.y // ((*p).T1).y
+ p.x // (*(*p).T0).x
-For x of type I or *I where I is an interface type (§Interface types):
+ p.M2 // (*p).M2
+ p.M1 // ((*p).T1).M1
+ p.M0 // ((*p).T0).M0
- - If f is a method declared in I then x.f denotes the actual method with
- name f of the value assigned to the variable x and x becomes the receiver
- of f. If no value or nil was assigned to x, x.f is illegal.
-Otherwise, x.f is illegal.
+TODO: Specify what happens to receivers.
Indexes