Commit 2ddc3e94 authored by Ian Lance Taylor's avatar Ian Lance Taylor

reflect: check pkgPath for unexported methods in Implements

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: 's avatarDavid Crawshaw <crawshaw@golang.org>
parent 755fd93b
...@@ -7,6 +7,7 @@ package reflect_test ...@@ -7,6 +7,7 @@ package reflect_test
import ( import (
"bytes" "bytes"
"go/ast" "go/ast"
"go/token"
"io" "io"
. "reflect" . "reflect"
"testing" "testing"
...@@ -172,6 +173,23 @@ var implementsTests = []struct { ...@@ -172,6 +173,23 @@ var implementsTests = []struct {
{new(bytes.Buffer), new(io.Reader), false}, {new(bytes.Buffer), new(io.Reader), false},
{new(*bytes.Buffer), new(io.ReaderAt), false}, {new(*bytes.Buffer), new(io.ReaderAt), false},
{new(*ast.Ident), new(ast.Expr), true}, {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) { func TestImplements(t *testing.T) {
......
...@@ -1515,8 +1515,23 @@ func implements(T, V *rtype) bool { ...@@ -1515,8 +1515,23 @@ func implements(T, V *rtype) bool {
i := 0 i := 0
for j := 0; j < len(v.methods); j++ { for j := 0; j < len(v.methods); j++ {
tm := &t.methods[i] tm := &t.methods[i]
tmName := t.nameOff(tm.name)
vm := &v.methods[j] 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) { if i++; i >= len(t.methods) {
return true return true
} }
...@@ -1533,8 +1548,23 @@ func implements(T, V *rtype) bool { ...@@ -1533,8 +1548,23 @@ func implements(T, V *rtype) bool {
vmethods := v.methods() vmethods := v.methods()
for j := 0; j < int(v.mcount); j++ { for j := 0; j < int(v.mcount); j++ {
tm := &t.methods[i] tm := &t.methods[i]
tmName := t.nameOff(tm.name)
vm := vmethods[j] 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) { if i++; i >= len(t.methods) {
return true return true
} }
......
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