aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/internal/reflectlite
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/internal/reflectlite')
-rw-r--r--libgo/go/internal/reflectlite/reflect_mirror_test.go131
-rw-r--r--libgo/go/internal/reflectlite/set_test.go9
-rw-r--r--libgo/go/internal/reflectlite/type.go6
-rw-r--r--libgo/go/internal/reflectlite/value.go12
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