]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: check pkgPath for unexported methods in Implements
authorIan Lance Taylor <iant@golang.org>
Wed, 31 May 2017 22:38:34 +0000 (15:38 -0700)
committerIan Lance Taylor <iant@golang.org>
Thu, 8 Jun 2017 00:54:14 +0000 (00:54 +0000)
Fixes #20541.

Change-Id: Ifdfdf3616482b71761daf6d114b779a8ec532051
Reviewed-on: https://go-review.googlesource.com/44495
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
src/reflect/set_test.go
src/reflect/type.go

index bc35c78e1bb3964de047de147a3a5100411338ee..7c39623a9dbb136ed15c031e8a95019999519582 100644 (file)
@@ -7,6 +7,7 @@ package reflect_test
 import (
        "bytes"
        "go/ast"
+       "go/token"
        "io"
        . "reflect"
        "testing"
@@ -172,6 +173,23 @@ var implementsTests = []struct {
        {new(bytes.Buffer), new(io.Reader), false},
        {new(*bytes.Buffer), new(io.ReaderAt), false},
        {new(*ast.Ident), new(ast.Expr), true},
+       {new(*notAnExpr), new(ast.Expr), false},
+       {new(*ast.Ident), new(notASTExpr), false},
+       {new(notASTExpr), new(ast.Expr), false},
+       {new(ast.Expr), new(notASTExpr), false},
+       {new(*notAnExpr), new(notASTExpr), true},
+}
+
+type notAnExpr struct{}
+
+func (notAnExpr) Pos() token.Pos { return token.NoPos }
+func (notAnExpr) End() token.Pos { return token.NoPos }
+func (notAnExpr) exprNode()      {}
+
+type notASTExpr interface {
+       Pos() token.Pos
+       End() token.Pos
+       exprNode()
 }
 
 func TestImplements(t *testing.T) {
index 1849c4b8d407a4c63054dd4ba3dedc6822986f4c..58f39a19b22b136acaeb9210ea7c8c88971ae862 100644 (file)
@@ -1515,8 +1515,23 @@ func implements(T, V *rtype) bool {
                i := 0
                for j := 0; j < len(v.methods); j++ {
                        tm := &t.methods[i]
+                       tmName := t.nameOff(tm.name)
                        vm := &v.methods[j]
-                       if V.nameOff(vm.name).name() == t.nameOff(tm.name).name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
+                       vmName := V.nameOff(vm.name)
+                       if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
+                               if !tmName.isExported() {
+                                       tmPkgPath := tmName.pkgPath()
+                                       if tmPkgPath == "" {
+                                               tmPkgPath = t.pkgPath.name()
+                                       }
+                                       vmPkgPath := vmName.pkgPath()
+                                       if vmPkgPath == "" {
+                                               vmPkgPath = v.pkgPath.name()
+                                       }
+                                       if tmPkgPath != vmPkgPath {
+                                               continue
+                                       }
+                               }
                                if i++; i >= len(t.methods) {
                                        return true
                                }
@@ -1533,8 +1548,23 @@ func implements(T, V *rtype) bool {
        vmethods := v.methods()
        for j := 0; j < int(v.mcount); j++ {
                tm := &t.methods[i]
+               tmName := t.nameOff(tm.name)
                vm := vmethods[j]
-               if V.nameOff(vm.name).name() == t.nameOff(tm.name).name() && V.typeOff(vm.mtyp) == t.typeOff(tm.typ) {
+               vmName := V.nameOff(vm.name)
+               if vmName.name() == tmName.name() && V.typeOff(vm.mtyp) == t.typeOff(tm.typ) {
+                       if !tmName.isExported() {
+                               tmPkgPath := tmName.pkgPath()
+                               if tmPkgPath == "" {
+                                       tmPkgPath = t.pkgPath.name()
+                               }
+                               vmPkgPath := vmName.pkgPath()
+                               if vmPkgPath == "" {
+                                       vmPkgPath = V.nameOff(v.pkgPath).name()
+                               }
+                               if tmPkgPath != vmPkgPath {
+                                       continue
+                               }
+                       }
                        if i++; i >= len(t.methods) {
                                return true
                        }