Commit 73becbf9 authored by Robert Griesemer's avatar Robert Griesemer

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

This was already partially fixed by commit 99843e22
(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/109139Reviewed-by: 's avatarAlan Donovan <adonovan@google.com>
parent f2df0ec7
......@@ -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()
......
......@@ -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
}
......
// 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)
}
// 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
}
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