Commit 903f095c authored by Robert Griesemer's avatar Robert Griesemer

go/types: adopt spec terminology, use 'embedded' rather then 'anonyous' field

Commit f8b41236 (https://go-review.googlesource.com/35108) adjusted
the spec to uniformly use 'embedded' rather than 'anonymous' for struct
embedded fields. Adjust go/types' internal terminology.

Provide an additional accessor Var.IsEmbedded().

This is essentially a rename of an internal field and adjustments of
documentation.

Change-Id: Icd07aa192bc5df7a2ee103185fa7e9c55e8f1ac3
Reviewed-on: https://go-review.googlesource.com/112716
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: default avatarAlan Donovan <adonovan@google.com>
parent b98ffdf8
...@@ -161,14 +161,14 @@ type Info struct { ...@@ -161,14 +161,14 @@ type Info struct {
// in package clauses, or symbolic variables t in t := x.(type) of // in package clauses, or symbolic variables t in t := x.(type) of
// type switch headers), the corresponding objects are nil. // type switch headers), the corresponding objects are nil.
// //
// For an anonymous field, Defs returns the field *Var it defines. // For an embedded field, Defs returns the field *Var it defines.
// //
// Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos() // Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos()
Defs map[*ast.Ident]Object Defs map[*ast.Ident]Object
// Uses maps identifiers to the objects they denote. // Uses maps identifiers to the objects they denote.
// //
// For an anonymous field, Uses returns the *TypeName it denotes. // For an embedded field, Uses returns the *TypeName it denotes.
// //
// Invariant: Uses[id].Pos() != id.Pos() // Invariant: Uses[id].Pos() != id.Pos()
Uses map[*ast.Ident]Object Uses map[*ast.Ident]Object
...@@ -239,7 +239,7 @@ func (info *Info) TypeOf(e ast.Expr) Type { ...@@ -239,7 +239,7 @@ func (info *Info) TypeOf(e ast.Expr) Type {
// ObjectOf returns the object denoted by the specified id, // ObjectOf returns the object denoted by the specified id,
// or nil if not found. // or nil if not found.
// //
// If id is an anonymous struct field, ObjectOf returns the field (*Var) // If id is an embedded struct field, ObjectOf returns the field (*Var)
// it uses, not the type (*TypeName) it defines. // it uses, not the type (*TypeName) it defines.
// //
// Precondition: the Uses and Defs maps are populated. // Precondition: the Uses and Defs maps are populated.
......
...@@ -19,7 +19,7 @@ package types ...@@ -19,7 +19,7 @@ package types
// 2) the list of all methods (method set) of an interface type; or // 2) the list of all methods (method set) of an interface type; or
// 3) the list of fields of a struct type. // 3) the list of fields of a struct type.
// //
// The earlier index entries are the indices of the anonymous struct fields // The earlier index entries are the indices of the embedded struct fields
// traversed to get to the found entry, starting at depth 0. // traversed to get to the found entry, starting at depth 0.
// //
// If no entry is found, a nil object is returned. In this case, the returned // If no entry is found, a nil object is returned. In this case, the returned
...@@ -149,7 +149,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o ...@@ -149,7 +149,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
// T is a type name. If e.typ appeared multiple times at // T is a type name. If e.typ appeared multiple times at
// this depth, f.typ appears multiple times at the next // this depth, f.typ appears multiple times at the next
// depth. // depth.
if obj == nil && f.anonymous { if obj == nil && f.embedded {
typ, isPtr := deref(f.typ) typ, isPtr := deref(f.typ)
// TODO(gri) optimization: ignore types that can't // TODO(gri) optimization: ignore types that can't
// have fields or methods (only Named, Struct, and // have fields or methods (only Named, Struct, and
......
...@@ -132,7 +132,7 @@ func NewMethodSet(T Type) *MethodSet { ...@@ -132,7 +132,7 @@ func NewMethodSet(T Type) *MethodSet {
// T is a type name. If typ appeared multiple times at // T is a type name. If typ appeared multiple times at
// this depth, f.Type appears multiple times at the next // this depth, f.Type appears multiple times at the next
// depth. // depth.
if f.anonymous { if f.embedded {
typ, isPtr := deref(f.typ) typ, isPtr := deref(f.typ)
// TODO(gri) optimization: ignore types that can't // TODO(gri) optimization: ignore types that can't
// have fields or methods (only Named, Struct, and // have fields or methods (only Named, Struct, and
......
...@@ -215,7 +215,7 @@ func (obj *TypeName) IsAlias() bool { ...@@ -215,7 +215,7 @@ func (obj *TypeName) IsAlias() bool {
// A Variable represents a declared variable (including function parameters and results, and struct fields). // A Variable represents a declared variable (including function parameters and results, and struct fields).
type Var struct { type Var struct {
object object
anonymous bool // if set, the variable is an anonymous struct field, and name is the type name embedded bool // if set, the variable is an embedded struct field, and name is the type name
visited bool // for initialization cycle detection visited bool // for initialization cycle detection
isField bool // var is struct field isField bool // var is struct field
used bool // set if the variable was used used bool // set if the variable was used
...@@ -233,14 +233,18 @@ func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var { ...@@ -233,14 +233,18 @@ func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
} }
// NewField returns a new variable representing a struct field. // NewField returns a new variable representing a struct field.
// For anonymous (embedded) fields, the name is the unqualified // For embedded fields, the name is the unqualified type name
// type name under which the field is accessible. /// under which the field is accessible.
func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var { func NewField(pos token.Pos, pkg *Package, name string, typ Type, embedded bool) *Var {
return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}, anonymous: anonymous, isField: true} return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}, embedded: embedded, isField: true}
} }
// Anonymous reports whether the variable is an anonymous field. // Anonymous reports whether the variable is an embedded field.
func (obj *Var) Anonymous() bool { return obj.anonymous } // Same as Embedded; only present for backward-compatibility.
func (obj *Var) Anonymous() bool { return obj.embedded }
// Embedded reports whether the variable is an embedded field.
func (obj *Var) Embedded() bool { return obj.embedded }
// IsField reports whether the variable is a struct field. // IsField reports whether the variable is a struct field.
func (obj *Var) IsField() bool { return obj.isField } func (obj *Var) IsField() bool { return obj.isField }
......
...@@ -164,13 +164,13 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { ...@@ -164,13 +164,13 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
case *Struct: case *Struct:
// Two struct types are identical if they have the same sequence of fields, // Two struct types are identical if they have the same sequence of fields,
// and if corresponding fields have the same names, and identical types, // and if corresponding fields have the same names, and identical types,
// and identical tags. Two anonymous fields are considered to have the same // and identical tags. Two embedded fields are considered to have the same
// name. Lower-case field names from different packages are always different. // name. Lower-case field names from different packages are always different.
if y, ok := y.(*Struct); ok { if y, ok := y.(*Struct); ok {
if x.NumFields() == y.NumFields() { if x.NumFields() == y.NumFields() {
for i, f := range x.fields { for i, f := range x.fields {
g := y.fields[i] g := y.fields[i]
if f.anonymous != g.anonymous || if f.embedded != g.embedded ||
cmpTags && x.Tag(i) != y.Tag(i) || cmpTags && x.Tag(i) != y.Tag(i) ||
!f.sameId(g.pkg, g.name) || !f.sameId(g.pkg, g.name) ||
!identical(f.typ, g.typ, cmpTags, p) { !identical(f.typ, g.typ, cmpTags, p) {
......
...@@ -97,7 +97,7 @@ type ( ...@@ -97,7 +97,7 @@ type (
u, v, a /* ERROR "redeclared" */ float32 u, v, a /* ERROR "redeclared" */ float32
} }
S2 struct { S2 struct {
S0 // anonymous field S0 // embedded field
S0 /* ERROR "redeclared" */ int S0 /* ERROR "redeclared" */ int
} }
S3 struct { S3 struct {
......
...@@ -141,7 +141,7 @@ func NewStruct(fields []*Var, tags []string) *Struct { ...@@ -141,7 +141,7 @@ func NewStruct(fields []*Var, tags []string) *Struct {
return &Struct{fields: fields, tags: tags} return &Struct{fields: fields, tags: tags}
} }
// NumFields returns the number of fields in the struct (including blank and anonymous fields). // NumFields returns the number of fields in the struct (including blank and embedded fields).
func (s *Struct) NumFields() int { return len(s.fields) } func (s *Struct) NumFields() int { return len(s.fields) }
// Field returns the i'th field for 0 <= i < NumFields(). // Field returns the i'th field for 0 <= i < NumFields().
......
...@@ -121,7 +121,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { ...@@ -121,7 +121,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
if i > 0 { if i > 0 {
buf.WriteString("; ") buf.WriteString("; ")
} }
if !f.anonymous { if !f.embedded {
buf.WriteString(f.name) buf.WriteString(f.name)
buf.WriteByte(' ') buf.WriteByte(' ')
} }
...@@ -146,7 +146,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { ...@@ -146,7 +146,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
case *Interface: case *Interface:
// We write the source-level methods and embedded types rather // We write the source-level methods and embedded types rather
// than the actual method set since resolved method signatures // than the actual method set since resolved method signatures
// may have non-printable cycles if parameters have anonymous // may have non-printable cycles if parameters have embedded
// interface types that (directly or indirectly) embed the // interface types that (directly or indirectly) embed the
// current interface. For instance, consider the result type // current interface. For instance, consider the result type
// of m: // of m:
......
...@@ -658,7 +658,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa ...@@ -658,7 +658,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
// current field typ and tag // current field typ and tag
var typ Type var typ Type
var tag string var tag string
add := func(ident *ast.Ident, anonymous bool, pos token.Pos) { add := func(ident *ast.Ident, embedded bool, pos token.Pos) {
if tag != "" && tags == nil { if tag != "" && tags == nil {
tags = make([]string, len(fields)) tags = make([]string, len(fields))
} }
...@@ -667,7 +667,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa ...@@ -667,7 +667,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
} }
name := ident.Name name := ident.Name
fld := NewField(pos, check.pkg, name, typ, anonymous) fld := NewField(pos, check.pkg, name, typ, embedded)
// spec: "Within a struct, non-blank field names must be unique." // spec: "Within a struct, non-blank field names must be unique."
if name == "_" || check.declareInSet(&fset, pos, fld) { if name == "_" || check.declareInSet(&fset, pos, fld) {
fields = append(fields, fld) fields = append(fields, fld)
...@@ -684,13 +684,13 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa ...@@ -684,13 +684,13 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
add(name, false, name.Pos()) add(name, false, name.Pos())
} }
} else { } else {
// anonymous field // embedded field
// spec: "An embedded type must be specified as a type name T or as a pointer // spec: "An embedded type must be specified as a type name T or as a pointer
// to a non-interface type name *T, and T itself may not be a pointer type." // to a non-interface type name *T, and T itself may not be a pointer type."
pos := f.Type.Pos() pos := f.Type.Pos()
name := anonymousFieldIdent(f.Type) name := embeddedFieldIdent(f.Type)
if name == nil { if name == nil {
check.invalidAST(pos, "anonymous field type %s has no name", f.Type) check.invalidAST(pos, "embedded field type %s has no name", f.Type)
continue continue
} }
t, isPtr := deref(typ) t, isPtr := deref(typ)
...@@ -705,17 +705,17 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa ...@@ -705,17 +705,17 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
// unsafe.Pointer is treated like a regular pointer // unsafe.Pointer is treated like a regular pointer
if t.kind == UnsafePointer { if t.kind == UnsafePointer {
check.errorf(pos, "anonymous field type cannot be unsafe.Pointer") check.errorf(pos, "embedded field type cannot be unsafe.Pointer")
continue continue
} }
case *Pointer: case *Pointer:
check.errorf(pos, "anonymous field type cannot be a pointer") check.errorf(pos, "embedded field type cannot be a pointer")
continue continue
case *Interface: case *Interface:
if isPtr { if isPtr {
check.errorf(pos, "anonymous field type cannot be a pointer to an interface") check.errorf(pos, "embedded field type cannot be a pointer to an interface")
continue continue
} }
} }
...@@ -727,17 +727,17 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa ...@@ -727,17 +727,17 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
styp.tags = tags styp.tags = tags
} }
func anonymousFieldIdent(e ast.Expr) *ast.Ident { func embeddedFieldIdent(e ast.Expr) *ast.Ident {
switch e := e.(type) { switch e := e.(type) {
case *ast.Ident: case *ast.Ident:
return e return e
case *ast.StarExpr: case *ast.StarExpr:
// *T is valid, but **T is not // *T is valid, but **T is not
if _, ok := e.X.(*ast.StarExpr); !ok { if _, ok := e.X.(*ast.StarExpr); !ok {
return anonymousFieldIdent(e.X) return embeddedFieldIdent(e.X)
} }
case *ast.SelectorExpr: case *ast.SelectorExpr:
return e.Sel return e.Sel
} }
return nil // invalid anonymous field return nil // invalid embedded field
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment