1
0
mirror of https://github.com/golang/go synced 2024-11-26 22:11:25 -07:00

go/types: use correct (file) scopes when computing interface method sets

This was already partially fixed by commit 99843e22e8
(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>
This commit is contained in:
Robert Griesemer 2018-04-24 14:38:18 -07:00
parent f2df0ec7dd
commit 73becbf9e2
4 changed files with 32 additions and 7 deletions

View 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()

View 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
}

15
src/go/types/testdata/issue25008a.src vendored Normal file
View File

@ -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)
}

9
src/go/types/testdata/issue25008b.src vendored Normal file
View File

@ -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
}