mirror of
https://github.com/golang/go
synced 2024-11-23 23:50:08 -07:00
go/types: copy embedded methods unchanged when completing interfaces
The existing code adjusted the receivers of embedded interface methods to match the embedding interface type. That required cloning (shallow copying) the embedded methods and destroyed their object identity in the process. Don't do this anymore. The consequence to clients is that they might see different methods of an interface having different receiver types; they are always the type of the interface that explicitly declared the method (which is what one usually would want, anyway). Fixes #28282. Change-Id: I2e6f1497f46affdf7510547a64601de3787367db Reviewed-on: https://go-review.googlesource.com/c/143757 Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
ffbf479ae1
commit
e9b39417e4
@ -422,3 +422,25 @@ func TestIssue28005(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue28282(t *testing.T) {
|
||||
// create type interface { error }
|
||||
et := Universe.Lookup("error").Type()
|
||||
it := NewInterfaceType(nil, []Type{et})
|
||||
it.Complete()
|
||||
// verify that after completing the interface, the embedded method remains unchanged
|
||||
want := et.Underlying().(*Interface).Method(0)
|
||||
got := it.Method(0)
|
||||
if got != want {
|
||||
t.Fatalf("%s.Method(0): got %q (%p); want %q (%p)", it, got, got, want, want)
|
||||
}
|
||||
// verify that lookup finds the same method in both interfaces (redundant check)
|
||||
obj, _, _ := LookupFieldOrMethod(et, false, nil, "Error")
|
||||
if obj != want {
|
||||
t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", et, obj, obj, want, want)
|
||||
}
|
||||
obj, _, _ = LookupFieldOrMethod(it, false, nil, "Error")
|
||||
if obj != want {
|
||||
t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", it, obj, obj, want, want)
|
||||
}
|
||||
}
|
||||
|
@ -231,11 +231,6 @@ func typecheck(t *testing.T, path string, filenames []string) {
|
||||
|
||||
// Perform checks of API invariants.
|
||||
|
||||
// The code below fails at the moment - see issue #28282.
|
||||
// Exit early for now to keep the longtest builder happy.
|
||||
// TODO(gri) fix this ASAP and uncomment the code below.
|
||||
|
||||
/*
|
||||
// All Objects have a package, except predeclared ones.
|
||||
errorError := Universe.Lookup("error").Type().Underlying().(*Interface).ExplicitMethod(0) // (error).Error
|
||||
for id, obj := range info.Uses {
|
||||
@ -249,7 +244,6 @@ func typecheck(t *testing.T, path string, filenames []string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// pkgFilenames returns the list of package filenames for the given directory.
|
||||
|
@ -352,19 +352,14 @@ func (t *Interface) Complete() *Interface {
|
||||
return t
|
||||
}
|
||||
|
||||
// collect all methods
|
||||
var allMethods []*Func
|
||||
allMethods = append(allMethods, t.methods...)
|
||||
for _, et := range t.embeddeds {
|
||||
it := et.Underlying().(*Interface)
|
||||
it.Complete()
|
||||
for _, tm := range it.allMethods {
|
||||
// Make a copy of the method and adjust its receiver type.
|
||||
newm := *tm
|
||||
newmtyp := *tm.typ.(*Signature)
|
||||
newm.typ = &newmtyp
|
||||
newmtyp.recv = NewVar(newm.pos, newm.pkg, "", t)
|
||||
allMethods = append(allMethods, &newm)
|
||||
}
|
||||
// copy embedded methods unchanged (see issue #28282)
|
||||
allMethods = append(allMethods, it.allMethods...)
|
||||
}
|
||||
sort.Sort(byUniqueMethodName(allMethods))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user