mirror of https://github.com/golang/go.git
go/types: adopt spec terminology, use 'embedded' rather then 'anonyous' field
Commit f8b4123613 (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: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
b98ffdf859
commit
903f095c1a
|
|
@ -161,14 +161,14 @@ type Info struct {
|
|||
// in package clauses, or symbolic variables t in t := x.(type) of
|
||||
// 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()
|
||||
Defs map[*ast.Ident]Object
|
||||
|
||||
// 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()
|
||||
Uses map[*ast.Ident]Object
|
||||
|
|
@ -239,7 +239,7 @@ func (info *Info) TypeOf(e ast.Expr) Type {
|
|||
// ObjectOf returns the object denoted by the specified id,
|
||||
// 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.
|
||||
//
|
||||
// Precondition: the Uses and Defs maps are populated.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package types
|
|||
// 2) the list of all methods (method set) of an interface type; or
|
||||
// 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.
|
||||
//
|
||||
// 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
|
|||
// T is a type name. If e.typ appeared multiple times at
|
||||
// this depth, f.typ appears multiple times at the next
|
||||
// depth.
|
||||
if obj == nil && f.anonymous {
|
||||
if obj == nil && f.embedded {
|
||||
typ, isPtr := deref(f.typ)
|
||||
// TODO(gri) optimization: ignore types that can't
|
||||
// have fields or methods (only Named, Struct, and
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ func NewMethodSet(T Type) *MethodSet {
|
|||
// T is a type name. If typ appeared multiple times at
|
||||
// this depth, f.Type appears multiple times at the next
|
||||
// depth.
|
||||
if f.anonymous {
|
||||
if f.embedded {
|
||||
typ, isPtr := deref(f.typ)
|
||||
// TODO(gri) optimization: ignore types that can't
|
||||
// have fields or methods (only Named, Struct, and
|
||||
|
|
|
|||
|
|
@ -215,10 +215,10 @@ func (obj *TypeName) IsAlias() bool {
|
|||
// A Variable represents a declared variable (including function parameters and results, and struct fields).
|
||||
type Var struct {
|
||||
object
|
||||
anonymous bool // if set, the variable is an anonymous struct field, and name is the type name
|
||||
visited bool // for initialization cycle detection
|
||||
isField bool // var is struct field
|
||||
used bool // set if the variable was used
|
||||
embedded bool // if set, the variable is an embedded struct field, and name is the type name
|
||||
visited bool // for initialization cycle detection
|
||||
isField bool // var is struct field
|
||||
used bool // set if the variable was used
|
||||
}
|
||||
|
||||
// NewVar returns a new variable.
|
||||
|
|
@ -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.
|
||||
// For anonymous (embedded) fields, the name is the unqualified
|
||||
// type name under which the field is accessible.
|
||||
func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var {
|
||||
return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}, anonymous: anonymous, isField: true}
|
||||
// For embedded fields, the name is the unqualified type name
|
||||
/// under which the field is accessible.
|
||||
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}, embedded: embedded, isField: true}
|
||||
}
|
||||
|
||||
// Anonymous reports whether the variable is an anonymous field.
|
||||
func (obj *Var) Anonymous() bool { return obj.anonymous }
|
||||
// Anonymous reports whether the variable is an embedded field.
|
||||
// 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.
|
||||
func (obj *Var) IsField() bool { return obj.isField }
|
||||
|
|
|
|||
|
|
@ -164,13 +164,13 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
|
|||
case *Struct:
|
||||
// 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 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.
|
||||
if y, ok := y.(*Struct); ok {
|
||||
if x.NumFields() == y.NumFields() {
|
||||
for i, f := range x.fields {
|
||||
g := y.fields[i]
|
||||
if f.anonymous != g.anonymous ||
|
||||
if f.embedded != g.embedded ||
|
||||
cmpTags && x.Tag(i) != y.Tag(i) ||
|
||||
!f.sameId(g.pkg, g.name) ||
|
||||
!identical(f.typ, g.typ, cmpTags, p) {
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ type (
|
|||
u, v, a /* ERROR "redeclared" */ float32
|
||||
}
|
||||
S2 struct {
|
||||
S0 // anonymous field
|
||||
S0 // embedded field
|
||||
S0 /* ERROR "redeclared" */ int
|
||||
}
|
||||
S3 struct {
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ func NewStruct(fields []*Var, tags []string) *Struct {
|
|||
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) }
|
||||
|
||||
// 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) {
|
|||
if i > 0 {
|
||||
buf.WriteString("; ")
|
||||
}
|
||||
if !f.anonymous {
|
||||
if !f.embedded {
|
||||
buf.WriteString(f.name)
|
||||
buf.WriteByte(' ')
|
||||
}
|
||||
|
|
@ -146,7 +146,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
|
|||
case *Interface:
|
||||
// We write the source-level methods and embedded types rather
|
||||
// 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
|
||||
// current interface. For instance, consider the result type
|
||||
// of m:
|
||||
|
|
|
|||
|
|
@ -658,7 +658,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
|
|||
// current field typ and tag
|
||||
var typ Type
|
||||
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 {
|
||||
tags = make([]string, len(fields))
|
||||
}
|
||||
|
|
@ -667,7 +667,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
|
|||
}
|
||||
|
||||
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."
|
||||
if name == "_" || check.declareInSet(&fset, pos, fld) {
|
||||
fields = append(fields, fld)
|
||||
|
|
@ -684,13 +684,13 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
|
|||
add(name, false, name.Pos())
|
||||
}
|
||||
} else {
|
||||
// anonymous field
|
||||
// embedded field
|
||||
// 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."
|
||||
pos := f.Type.Pos()
|
||||
name := anonymousFieldIdent(f.Type)
|
||||
name := embeddedFieldIdent(f.Type)
|
||||
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
|
||||
}
|
||||
t, isPtr := deref(typ)
|
||||
|
|
@ -705,17 +705,17 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
|
|||
|
||||
// unsafe.Pointer is treated like a regular pointer
|
||||
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
|
||||
}
|
||||
|
||||
case *Pointer:
|
||||
check.errorf(pos, "anonymous field type cannot be a pointer")
|
||||
check.errorf(pos, "embedded field type cannot be a pointer")
|
||||
continue
|
||||
|
||||
case *Interface:
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -727,17 +727,17 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
|
|||
styp.tags = tags
|
||||
}
|
||||
|
||||
func anonymousFieldIdent(e ast.Expr) *ast.Ident {
|
||||
func embeddedFieldIdent(e ast.Expr) *ast.Ident {
|
||||
switch e := e.(type) {
|
||||
case *ast.Ident:
|
||||
return e
|
||||
case *ast.StarExpr:
|
||||
// *T is valid, but **T is not
|
||||
if _, ok := e.X.(*ast.StarExpr); !ok {
|
||||
return anonymousFieldIdent(e.X)
|
||||
return embeddedFieldIdent(e.X)
|
||||
}
|
||||
case *ast.SelectorExpr:
|
||||
return e.Sel
|
||||
}
|
||||
return nil // invalid anonymous field
|
||||
return nil // invalid embedded field
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue