mirror of
https://github.com/golang/go
synced 2024-11-18 18:44:42 -07:00
go.tools/go/types: fix interface vs interface type assertion
R=adonovan CC=golang-dev https://golang.org/cl/12378043
This commit is contained in:
parent
e06b897351
commit
3209d6ad73
@ -225,22 +225,18 @@ func consolidateMultiples(list []embeddedType) []embeddedType {
|
||||
// is missing or simply has the wrong type.
|
||||
//
|
||||
func MissingMethod(typ Type, T *Interface) (method *Func, wrongType bool) {
|
||||
// an interface type implements T if it has no methods with conflicting signatures
|
||||
// Note: This is stronger than the current spec. Should the spec require this?
|
||||
|
||||
// fast path for common case
|
||||
if T.NumMethods() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// An interface type implements T if it has at least the methods of T.
|
||||
// The dynamic type of a value stored in an interface may implement T,
|
||||
// but only if all the shared interface methods have matching signatures.
|
||||
// Note: This is stronger than the current spec. Should the spec require this?
|
||||
if ityp, _ := typ.Underlying().(*Interface); ityp != nil {
|
||||
for _, m := range T.methods {
|
||||
_, obj := lookupMethod(ityp.methods, m.pkg, m.name)
|
||||
if obj == nil {
|
||||
return m, false
|
||||
}
|
||||
if !IsIdentical(obj.Type(), m.typ) {
|
||||
if obj != nil && !IsIdentical(obj.Type(), m.typ) {
|
||||
return m, true
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +108,7 @@ func TestStdfixed(t *testing.T) {
|
||||
"bug050.go", "bug088.go", "bug106.go", // TODO(gri) parser loses comments when bailing out early
|
||||
"bug222.go", "bug282.go", "bug306.go", // TODO(gri) parser loses comments when bailing out early
|
||||
"bug136.go", "bug179.go", "bug344.go", // TODO(gri) implement missing label checks
|
||||
"bug251.go", // TODO(gri) incorrect cycle checks for interface types
|
||||
"bug165.go", // TODO(gri) isComparable not working for incomplete struct type
|
||||
"bug176.go", // TODO(gri) composite literal array index must be non-negative constant
|
||||
"bug200.go", // TODO(gri) complete duplicate checking in expr switches
|
||||
|
21
go/types/testdata/conversions.src
vendored
21
go/types/testdata/conversions.src
vendored
@ -44,12 +44,19 @@ func interface_conversions() {
|
||||
|
||||
type I2 interface{
|
||||
m1()
|
||||
m2()
|
||||
m2(x int)
|
||||
}
|
||||
|
||||
type I3 interface{
|
||||
m1()
|
||||
m2() int
|
||||
}
|
||||
|
||||
var e E
|
||||
var i1 I1
|
||||
var i2 I2
|
||||
var i3 I3
|
||||
|
||||
_ = E(0)
|
||||
_ = E(nil)
|
||||
_ = E(e)
|
||||
@ -59,10 +66,18 @@ func interface_conversions() {
|
||||
_ = I1 /* ERROR "cannot convert" */ (0)
|
||||
_ = I1(nil)
|
||||
_ = I1(i1)
|
||||
_ = I1 /* ERROR "cannot convert" */ (e)
|
||||
_ = I1(e)
|
||||
_ = I1(i2)
|
||||
|
||||
_ = I2 /* ERROR "cannot convert" */ (i1)
|
||||
_ = I2(nil)
|
||||
_ = I2(i1)
|
||||
_ = I2(i2)
|
||||
_ = I2 /* ERROR "cannot convert" */ (i3)
|
||||
|
||||
_ = I3(nil)
|
||||
_ = I3(i1)
|
||||
_ = I3 /* ERROR "cannot convert" */ (i2)
|
||||
_ = I3(i3)
|
||||
|
||||
// TODO(gri) add more tests, improve error message
|
||||
}
|
13
go/types/testdata/stmt0.src
vendored
13
go/types/testdata/stmt0.src
vendored
@ -298,6 +298,19 @@ func typeswitch1() {
|
||||
}
|
||||
}
|
||||
|
||||
// Test correct typeswitch against interface types.
|
||||
type A interface { a() }
|
||||
type B interface { b() }
|
||||
type C interface { a(int) }
|
||||
|
||||
func typeswitch2() {
|
||||
switch A(nil).(type) {
|
||||
case A:
|
||||
case B:
|
||||
case C /* ERROR "cannot have dynamic type" */:
|
||||
}
|
||||
}
|
||||
|
||||
func rangeloops() {
|
||||
var (
|
||||
x int
|
||||
|
Loading…
Reference in New Issue
Block a user