// 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
// 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.
// 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
// 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
// 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
// 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.
}
// 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 }
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) {
u, v, a /* ERROR "redeclared" */ float32
}
S2 struct {
- S0 // anonymous field
+ S0 // embedded field
S0 /* ERROR "redeclared" */ int
}
S3 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().
if i > 0 {
buf.WriteString("; ")
}
- if !f.anonymous {
+ if !f.embedded {
buf.WriteString(f.name)
buf.WriteByte(' ')
}
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:
// 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))
}
}
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)
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)
// 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
}
}
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
}