diff options
Diffstat (limited to 'libgo/go/internal/reflectlite')
-rw-r--r-- | libgo/go/internal/reflectlite/reflect_mirror_test.go | 131 | ||||
-rw-r--r-- | libgo/go/internal/reflectlite/set_test.go | 9 | ||||
-rw-r--r-- | libgo/go/internal/reflectlite/type.go | 6 | ||||
-rw-r--r-- | libgo/go/internal/reflectlite/value.go | 12 |
4 files changed, 146 insertions, 12 deletions
diff --git a/libgo/go/internal/reflectlite/reflect_mirror_test.go b/libgo/go/internal/reflectlite/reflect_mirror_test.go new file mode 100644 index 0000000..fbb6fb3 --- /dev/null +++ b/libgo/go/internal/reflectlite/reflect_mirror_test.go @@ -0,0 +1,131 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package reflectlite_test + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "os" + "path/filepath" + "runtime" + "strings" + "sync" + "testing" +) + +var typeNames = []string{ + "rtype", + "uncommonType", + "arrayType", + "chanType", + "funcType", + "interfaceType", + "mapType", + "ptrType", + "sliceType", + "structType", +} + +type visitor struct { + m map[string]map[string]bool +} + +func newVisitor() visitor { + v := visitor{} + v.m = make(map[string]map[string]bool) + + return v +} +func (v visitor) filter(name string) bool { + for _, typeName := range typeNames { + if typeName == name { + return true + } + } + return false +} + +func (v visitor) Visit(n ast.Node) ast.Visitor { + switch x := n.(type) { + case *ast.TypeSpec: + if v.filter(x.Name.String()) { + if st, ok := x.Type.(*ast.StructType); ok { + v.m[x.Name.String()] = make(map[string]bool) + for _, field := range st.Fields.List { + k := fmt.Sprintf("%s", field.Type) + if len(field.Names) > 0 { + k = field.Names[0].Name + } + v.m[x.Name.String()][k] = true + } + } + } + } + return v +} + +func loadTypes(path, pkgName string, v visitor) { + fset := token.NewFileSet() + + filter := func(fi os.FileInfo) bool { + return strings.HasSuffix(fi.Name(), ".go") + } + pkgs, err := parser.ParseDir(fset, path, filter, 0) + if err != nil { + panic(err) + } + + pkg := pkgs[pkgName] + + for _, f := range pkg.Files { + ast.Walk(v, f) + } +} + +func TestMirrorWithReflect(t *testing.T) { + reflectDir := filepath.Join(runtime.GOROOT(), "src", "reflect") + if _, err := os.Stat(reflectDir); os.IsNotExist(err) { + // On some mobile builders, the test binary executes on a machine without a + // complete GOROOT source tree. + t.Skipf("GOROOT source not present") + } + + var wg sync.WaitGroup + rl, r := newVisitor(), newVisitor() + + for _, tc := range []struct { + path, pkg string + v visitor + }{ + {".", "reflectlite", rl}, + {reflectDir, "reflect", r}, + } { + tc := tc + wg.Add(1) + go func() { + defer wg.Done() + loadTypes(tc.path, tc.pkg, tc.v) + }() + } + wg.Wait() + + if len(rl.m) != len(r.m) { + t.Fatalf("number of types mismatch, reflect: %d, reflectlite: %d", len(r.m), len(rl.m)) + } + + for typName := range r.m { + if len(r.m[typName]) != len(rl.m[typName]) { + t.Errorf("type %s number of fields mismatch, reflect: %d, reflectlite: %d", typName, len(r.m[typName]), len(rl.m[typName])) + continue + } + for field := range r.m[typName] { + if _, ok := rl.m[typName][field]; !ok { + t.Errorf(`Field mismatch, reflect have "%s", relectlite does not.`, field) + } + } + } +} diff --git a/libgo/go/internal/reflectlite/set_test.go b/libgo/go/internal/reflectlite/set_test.go index 817e4be..a610499 100644 --- a/libgo/go/internal/reflectlite/set_test.go +++ b/libgo/go/internal/reflectlite/set_test.go @@ -39,6 +39,8 @@ var implementsTests = []struct { {new(notASTExpr), new(ast.Expr), false}, {new(ast.Expr), new(notASTExpr), false}, {new(*notAnExpr), new(notASTExpr), true}, + {new(mapError), new(error), true}, + {new(*mapError), new(error), true}, } type notAnExpr struct{} @@ -53,6 +55,13 @@ type notASTExpr interface { exprNode() } +type mapError map[string]string + +func (mapError) Error() string { return "mapError" } + +var _ error = mapError{} +var _ error = new(mapError) + func TestImplements(t *testing.T) { for _, tt := range implementsTests { xv := TypeOf(tt.x).Elem() diff --git a/libgo/go/internal/reflectlite/type.go b/libgo/go/internal/reflectlite/type.go index 35cf1a4..e700a55 100644 --- a/libgo/go/internal/reflectlite/type.go +++ b/libgo/go/internal/reflectlite/type.go @@ -351,6 +351,10 @@ func (t *rtype) PkgPath() string { return t.uncommonType.PkgPath() } +func (t *rtype) hasName() bool { + return t.uncommonType != nil && t.uncommonType.name != nil +} + func (t *rtype) Name() string { return t.uncommonType.Name() } @@ -574,7 +578,7 @@ func directlyAssignable(T, V *rtype) bool { // Otherwise at least one of T and V must not be defined // and they must have the same kind. - if T.Name() != "" && V.Name() != "" || T.Kind() != V.Kind() { + if T.hasName() && V.hasName() || T.Kind() != V.Kind() { return false } diff --git a/libgo/go/internal/reflectlite/value.go b/libgo/go/internal/reflectlite/value.go index bfc321f..9a14d18 100644 --- a/libgo/go/internal/reflectlite/value.go +++ b/libgo/go/internal/reflectlite/value.go @@ -180,16 +180,6 @@ type emptyInterface struct { word unsafe.Pointer } -// nonEmptyInterface is the header for an interface value with methods. -type nonEmptyInterface struct { - // see ../runtime/iface.go:/Itab - itab *struct { - typ *rtype // dynamic concrete type - fun [100000]unsafe.Pointer // method table - } - word unsafe.Pointer -} - // mustBeExported panics if f records that the value was obtained using // an unexported field. func (f flag) mustBeExported() { @@ -316,7 +306,7 @@ func (v Value) IsNil() bool { // IsValid reports whether v represents a value. // It returns false if v is the zero Value. // If IsValid returns false, all other methods except String panic. -// Most functions and methods never return an invalid value. +// Most functions and methods never return an invalid Value. // If one does, its documentation states the conditions explicitly. func (v Value) IsValid() bool { return v.flag != 0 |