Commit 47be3d49 authored by Robert Griesemer's avatar Robert Griesemer

reflect: use 'defined' rather than 'named', use 'embedded' rather than 'anonymous'

On the API level this is just an update of the documentation to match
the current spec more closely.

On the implementation side, this is a rename of various unexported names.

For #22005.

Change-Id: Ie5ae32f3b10f003805240efcceab3d0fd373cd51
Reviewed-on: https://go-review.googlesource.com/112717
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 903f095c
...@@ -2535,7 +2535,7 @@ func TestFieldPkgPath(t *testing.T) { ...@@ -2535,7 +2535,7 @@ func TestFieldPkgPath(t *testing.T) {
type pkgpathTest struct { type pkgpathTest struct {
index []int index []int
pkgPath string pkgPath string
anonymous bool embedded bool
} }
checkPkgPath := func(name string, s []pkgpathTest) { checkPkgPath := func(name string, s []pkgpathTest) {
...@@ -2544,7 +2544,7 @@ func TestFieldPkgPath(t *testing.T) { ...@@ -2544,7 +2544,7 @@ func TestFieldPkgPath(t *testing.T) {
if got, want := f.PkgPath, test.pkgPath; got != want { if got, want := f.PkgPath, test.pkgPath; got != want {
t.Errorf("%s: Field(%d).PkgPath = %q, want %q", name, test.index, got, want) t.Errorf("%s: Field(%d).PkgPath = %q, want %q", name, test.index, got, want)
} }
if got, want := f.Anonymous, test.anonymous; got != want { if got, want := f.Anonymous, test.embedded; got != want {
t.Errorf("%s: Field(%d).Anonymous = %v, want %v", name, test.index, got, want) t.Errorf("%s: Field(%d).Anonymous = %v, want %v", name, test.index, got, want)
} }
} }
...@@ -4874,7 +4874,7 @@ func TestStructOfWithInterface(t *testing.T) { ...@@ -4874,7 +4874,7 @@ func TestStructOfWithInterface(t *testing.T) {
}) })
// We currently do not correctly implement methods // We currently do not correctly implement methods
// for anonymous fields other than the first. // for embedded fields other than the first.
// Therefore, for now, we expect those methods // Therefore, for now, we expect those methods
// to not exist. See issues 15924 and 20824. // to not exist. See issues 15924 and 20824.
// When those issues are fixed, this test of panic // When those issues are fixed, this test of panic
......
...@@ -69,14 +69,15 @@ type Type interface { ...@@ -69,14 +69,15 @@ type Type interface {
// NumMethod returns the number of exported methods in the type's method set. // NumMethod returns the number of exported methods in the type's method set.
NumMethod() int NumMethod() int
// Name returns the type's name within its package. // Name returns the type's name within its package for a defined type.
// It returns an empty string for unnamed types. // For other (non-defined) types it returns the empty string.
Name() string Name() string
// PkgPath returns a named type's package path, that is, the import path // PkgPath returns a defined type's package path, that is, the import path
// that uniquely identifies the package, such as "encoding/base64". // that uniquely identifies the package, such as "encoding/base64".
// If the type was predeclared (string, error) or unnamed (*T, struct{}, []int), // If the type was predeclared (string, error) or not defined (*T, struct{},
// the package path will be the empty string. // []int, or A where A is an alias for a non-defined type), the package path
// will be the empty string.
PkgPath() string PkgPath() string
// Size returns the number of bytes needed to store // Size returns the number of bytes needed to store
...@@ -164,13 +165,13 @@ type Type interface { ...@@ -164,13 +165,13 @@ type Type interface {
// the field was found. // the field was found.
// //
// FieldByNameFunc considers the fields in the struct itself // FieldByNameFunc considers the fields in the struct itself
// and then the fields in any anonymous structs, in breadth first order, // and then the fields in any embedded structs, in breadth first order,
// stopping at the shallowest nesting depth containing one or more // stopping at the shallowest nesting depth containing one or more
// fields satisfying the match function. If multiple fields at that depth // fields satisfying the match function. If multiple fields at that depth
// satisfy the match function, they cancel each other // satisfy the match function, they cancel each other
// and FieldByNameFunc returns no match. // and FieldByNameFunc returns no match.
// This behavior mirrors Go's handling of name lookup in // This behavior mirrors Go's handling of name lookup in
// structs containing anonymous fields. // structs containing embedded fields.
FieldByNameFunc(match func(string) bool) (StructField, bool) FieldByNameFunc(match func(string) bool) (StructField, bool)
// In returns the type of a function type's i'th input parameter. // In returns the type of a function type's i'th input parameter.
...@@ -326,10 +327,10 @@ type method struct { ...@@ -326,10 +327,10 @@ type method struct {
tfn textOff // fn used for normal method call tfn textOff // fn used for normal method call
} }
// uncommonType is present only for types with names or methods // uncommonType is present only for defined types or types with methods
// (if T is a named type, the uncommonTypes for T and *T have methods). // (if T is a defined type, the uncommonTypes for T and *T have methods).
// Using a pointer to this struct reduces the overall size required // Using a pointer to this struct reduces the overall size required
// to describe an unnamed type with no methods. // to describe a non-defined type with no methods.
type uncommonType struct { type uncommonType struct {
pkgPath nameOff // import path; empty for built-in types like int, string pkgPath nameOff // import path; empty for built-in types like int, string
mcount uint16 // number of methods mcount uint16 // number of methods
...@@ -423,15 +424,15 @@ type sliceType struct { ...@@ -423,15 +424,15 @@ type sliceType struct {
type structField struct { type structField struct {
name name // name is always non-empty name name // name is always non-empty
typ *rtype // type of field typ *rtype // type of field
offsetAnon uintptr // byte offset of field<<1 | isAnonymous offsetEmbed uintptr // byte offset of field<<1 | isEmbedded
} }
func (f *structField) offset() uintptr { func (f *structField) offset() uintptr {
return f.offsetAnon >> 1 return f.offsetEmbed >> 1
} }
func (f *structField) anon() bool { func (f *structField) embedded() bool {
return f.offsetAnon&1 != 0 return f.offsetEmbed&1 != 0
} }
// structType represents a struct type. // structType represents a struct type.
...@@ -1199,7 +1200,7 @@ func (t *structType) Field(i int) (f StructField) { ...@@ -1199,7 +1200,7 @@ func (t *structType) Field(i int) (f StructField) {
p := &t.fields[i] p := &t.fields[i]
f.Type = toType(p.typ) f.Type = toType(p.typ)
f.Name = p.name.name() f.Name = p.name.name()
f.Anonymous = p.anon() f.Anonymous = p.embedded()
if !p.name.isExported() { if !p.name.isExported() {
f.PkgPath = t.pkgPath.name() f.PkgPath = t.pkgPath.name()
} }
...@@ -1293,11 +1294,11 @@ func (t *structType) FieldByNameFunc(match func(string) bool) (result StructFiel ...@@ -1293,11 +1294,11 @@ func (t *structType) FieldByNameFunc(match func(string) bool) (result StructFiel
visited[t] = true visited[t] = true
for i := range t.fields { for i := range t.fields {
f := &t.fields[i] f := &t.fields[i]
// Find name and (for anonymous field) type for field f. // Find name and (for embedded field) type for field f.
fname := f.name.name() fname := f.name.name()
var ntyp *rtype var ntyp *rtype
if f.anon() { if f.embedded() {
// Anonymous field of type T or *T. // Embedded field of type T or *T.
ntyp = f.typ ntyp = f.typ
if ntyp.Kind() == Ptr { if ntyp.Kind() == Ptr {
ntyp = ntyp.Elem().common() ntyp = ntyp.Elem().common()
...@@ -1353,20 +1354,20 @@ func (t *structType) FieldByNameFunc(match func(string) bool) (result StructFiel ...@@ -1353,20 +1354,20 @@ func (t *structType) FieldByNameFunc(match func(string) bool) (result StructFiel
// FieldByName returns the struct field with the given name // FieldByName returns the struct field with the given name
// and a boolean to indicate if the field was found. // and a boolean to indicate if the field was found.
func (t *structType) FieldByName(name string) (f StructField, present bool) { func (t *structType) FieldByName(name string) (f StructField, present bool) {
// Quick check for top-level name, or struct without anonymous fields. // Quick check for top-level name, or struct without embedded fields.
hasAnon := false hasEmbeds := false
if name != "" { if name != "" {
for i := range t.fields { for i := range t.fields {
tf := &t.fields[i] tf := &t.fields[i]
if tf.name.name() == name { if tf.name.name() == name {
return t.Field(i), true return t.Field(i), true
} }
if tf.anon() { if tf.embedded() {
hasAnon = true hasEmbeds = true
} }
} }
} }
if !hasAnon { if !hasEmbeds {
return return
} }
return t.FieldByNameFunc(func(s string) bool { return s == name }) return t.FieldByNameFunc(func(s string) bool { return s == name })
...@@ -1565,7 +1566,7 @@ func directlyAssignable(T, V *rtype) bool { ...@@ -1565,7 +1566,7 @@ func directlyAssignable(T, V *rtype) bool {
return true return true
} }
// Otherwise at least one of T and V must be unnamed // Otherwise at least one of T and V must not be defined
// and they must have the same kind. // and they must have the same kind.
if T.Name() != "" && V.Name() != "" || T.Kind() != V.Kind() { if T.Name() != "" && V.Name() != "" || T.Kind() != V.Kind() {
return false return false
...@@ -1674,7 +1675,7 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool { ...@@ -1674,7 +1675,7 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
if cmpTags && tf.name.tag() != vf.name.tag() { if cmpTags && tf.name.tag() != vf.name.tag() {
return false return false
} }
if tf.offsetAnon != vf.offsetAnon { if tf.offsetEmbed != vf.offsetEmbed {
return false return false
} }
} }
...@@ -2388,13 +2389,13 @@ func StructOf(fields []StructField) Type { ...@@ -2388,13 +2389,13 @@ func StructOf(fields []StructField) Type {
name := f.name.name() name := f.name.name()
hash = fnv1(hash, []byte(name)...) hash = fnv1(hash, []byte(name)...)
repr = append(repr, (" " + name)...) repr = append(repr, (" " + name)...)
if f.anon() { if f.embedded() {
// Embedded field // Embedded field
if f.typ.Kind() == Ptr { if f.typ.Kind() == Ptr {
// Embedded ** and *interface{} are illegal // Embedded ** and *interface{} are illegal
elem := ft.Elem() elem := ft.Elem()
if k := elem.Kind(); k == Ptr || k == Interface { if k := elem.Kind(); k == Ptr || k == Interface {
panic("reflect.StructOf: illegal anonymous field type " + ft.String()) panic("reflect.StructOf: illegal embedded field type " + ft.String())
} }
} }
...@@ -2544,7 +2545,7 @@ func StructOf(fields []StructField) Type { ...@@ -2544,7 +2545,7 @@ func StructOf(fields []StructField) Type {
typalign = ft.align typalign = ft.align
} }
size = offset + ft.size size = offset + ft.size
f.offsetAnon |= offset << 1 f.offsetEmbed |= offset << 1
if ft.size == 0 { if ft.size == 0 {
lastzero = size lastzero = size
...@@ -2780,16 +2781,16 @@ func runtimeStructField(field StructField) structField { ...@@ -2780,16 +2781,16 @@ func runtimeStructField(field StructField) structField {
panic("reflect.StructOf: field \"" + field.Name + "\" is unexported but missing PkgPath") panic("reflect.StructOf: field \"" + field.Name + "\" is unexported but missing PkgPath")
} }
offsetAnon := uintptr(0) offsetEmbed := uintptr(0)
if field.Anonymous { if field.Anonymous {
offsetAnon |= 1 offsetEmbed |= 1
} }
resolveReflectType(field.Type.common()) // install in runtime resolveReflectType(field.Type.common()) // install in runtime
return structField{ return structField{
name: newName(field.Name, string(field.Tag), true), name: newName(field.Name, string(field.Tag), true),
typ: field.Type.common(), typ: field.Type.common(),
offsetAnon: offsetAnon, offsetEmbed: offsetEmbed,
} }
} }
......
...@@ -792,7 +792,7 @@ func (v Value) Field(i int) Value { ...@@ -792,7 +792,7 @@ func (v Value) Field(i int) Value {
fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind()) fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind())
// Using an unexported field forces flagRO. // Using an unexported field forces flagRO.
if !field.name.isExported() { if !field.name.isExported() {
if field.anon() { if field.embedded() {
fl |= flagEmbedRO fl |= flagEmbedRO
} else { } else {
fl |= flagStickyRO fl |= flagStickyRO
...@@ -2319,7 +2319,7 @@ func convertOp(dst, src *rtype) func(Value, Type) Value { ...@@ -2319,7 +2319,7 @@ func convertOp(dst, src *rtype) func(Value, Type) Value {
return cvtDirect return cvtDirect
} }
// dst and src are unnamed pointer types with same underlying base type. // dst and src are non-defined pointer types with same underlying base type.
if dst.Kind() == Ptr && dst.Name() == "" && if dst.Kind() == Ptr && dst.Name() == "" &&
src.Kind() == Ptr && src.Name() == "" && src.Kind() == Ptr && src.Name() == "" &&
haveIdenticalUnderlyingType(dst.Elem().common(), src.Elem().common(), false) { haveIdenticalUnderlyingType(dst.Elem().common(), src.Elem().common(), false) {
......
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