]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: use correct (file) scopes when computing interface method sets
authorRobert Griesemer <gri@golang.org>
Tue, 24 Apr 2018 21:38:18 +0000 (14:38 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 25 Apr 2018 18:24:59 +0000 (18:24 +0000)
This was already partially fixed by commit 99843e22e81
(https://go-review.googlesource.com/c/go/+/96376); but
we missed a couple of places where we also need to
propagate the scope.

Fixes #25008.

Change-Id: I041fa74d1f6d3b5a8edb922efa126ff1dacd7900
Reviewed-on: https://go-review.googlesource.com/109139
Reviewed-by: Alan Donovan <adonovan@google.com>
src/go/types/check_test.go
src/go/types/interfaces.go
src/go/types/testdata/issue25008a.src [new file with mode: 0644]
src/go/types/testdata/issue25008b.src [new file with mode: 0644]

index 720d8db293971e77c272a14fefa61357270b43ef..fb18ac87d27d6989fdca2e9471330e98ec1a358b 100644 (file)
@@ -90,6 +90,7 @@ var tests = [][]string{
        {"testdata/labels.src"},
        {"testdata/issues.src"},
        {"testdata/blank.src"},
+       {"testdata/issue25008b.src", "testdata/issue25008a.src"}, // order (b before a) is crucial!
 }
 
 var fset = token.NewFileSet()
index d82f1c83ebbba65dd6c5697c89df765c26aa1faa..1ce5e1ed976dfa0d763aba8e9478ba1d69f793cb 100644 (file)
@@ -221,9 +221,9 @@ func (check *Checker) infoFromTypeLit(scope *Scope, iface *ast.InterfaceType, tn
                                var e *ifaceInfo
                                switch ename := f.Type.(type) {
                                case *ast.Ident:
-                                       e = check.infoFromTypeName(ename, path)
+                                       e = check.infoFromTypeName(scope, ename, path)
                                case *ast.SelectorExpr:
-                                       e = check.infoFromQualifiedTypeName(ename)
+                                       e = check.infoFromQualifiedTypeName(scope, ename)
                                default:
                                        // The parser makes sure we only see one of the above.
                                        // Constructed ASTs may contain other (invalid) nodes;
@@ -262,7 +262,7 @@ func (check *Checker) infoFromTypeLit(scope *Scope, iface *ast.InterfaceType, tn
 // which must denote a type whose underlying type is an interface.
 // The same result qualifications apply as for infoFromTypeLit.
 // infoFromTypeName should only be called from infoFromTypeLit.
-func (check *Checker) infoFromTypeName(name *ast.Ident, path []*TypeName) *ifaceInfo {
+func (check *Checker) infoFromTypeName(scope *Scope, name *ast.Ident, path []*TypeName) *ifaceInfo {
        // A single call of infoFromTypeName handles a sequence of (possibly
        // recursive) type declarations connected via unqualified type names.
        // Each type declaration leading to another typename causes a "tail call"
@@ -291,7 +291,7 @@ func (check *Checker) infoFromTypeName(name *ast.Ident, path []*TypeName) *iface
 
 typenameLoop:
        // name must be a type name denoting a type whose underlying type is an interface
-       obj := check.lookup(name.Name)
+       _, obj := scope.LookupParent(name.Name, check.pos)
        if obj == nil {
                return nil
        }
@@ -333,7 +333,7 @@ typenameLoop:
                        goto typenameLoop
                case *ast.SelectorExpr:
                        // type tname p.T
-                       return check.infoFromQualifiedTypeName(typ)
+                       return check.infoFromQualifiedTypeName(decl.file, typ)
                case *ast.InterfaceType:
                        // type tname interface{...}
                        return check.infoFromTypeLit(decl.file, typ, tname, path)
@@ -360,13 +360,13 @@ typenameLoop:
 }
 
 // infoFromQualifiedTypeName computes the method set for the given qualified type name, or nil.
-func (check *Checker) infoFromQualifiedTypeName(qname *ast.SelectorExpr) *ifaceInfo {
+func (check *Checker) infoFromQualifiedTypeName(scope *Scope, qname *ast.SelectorExpr) *ifaceInfo {
        // see also Checker.selector
        name, _ := qname.X.(*ast.Ident)
        if name == nil {
                return nil
        }
-       obj1 := check.lookup(name.Name)
+       _, obj1 := scope.LookupParent(name.Name, check.pos)
        if obj1 == nil {
                return nil
        }
diff --git a/src/go/types/testdata/issue25008a.src b/src/go/types/testdata/issue25008a.src
new file mode 100644 (file)
index 0000000..cf71ca1
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2018 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 p
+
+import "io"
+
+type A interface {
+        io.Reader
+}
+
+func f(a A) {
+        a.Read(nil)
+}
diff --git a/src/go/types/testdata/issue25008b.src b/src/go/types/testdata/issue25008b.src
new file mode 100644 (file)
index 0000000..f132b7f
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2018 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 p
+
+type B interface {
+    A
+}