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.
|
// is missing or simply has the wrong type.
|
||||||
//
|
//
|
||||||
func MissingMethod(typ Type, T *Interface) (method *Func, wrongType bool) {
|
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
|
// fast path for common case
|
||||||
if T.NumMethods() == 0 {
|
if T.NumMethods() == 0 {
|
||||||
return
|
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 {
|
if ityp, _ := typ.Underlying().(*Interface); ityp != nil {
|
||||||
for _, m := range T.methods {
|
for _, m := range T.methods {
|
||||||
_, obj := lookupMethod(ityp.methods, m.pkg, m.name)
|
_, obj := lookupMethod(ityp.methods, m.pkg, m.name)
|
||||||
if obj == nil {
|
if obj != nil && !IsIdentical(obj.Type(), m.typ) {
|
||||||
return m, false
|
|
||||||
}
|
|
||||||
if !IsIdentical(obj.Type(), m.typ) {
|
|
||||||
return m, true
|
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
|
"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
|
"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
|
"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
|
"bug165.go", // TODO(gri) isComparable not working for incomplete struct type
|
||||||
"bug176.go", // TODO(gri) composite literal array index must be non-negative constant
|
"bug176.go", // TODO(gri) composite literal array index must be non-negative constant
|
||||||
"bug200.go", // TODO(gri) complete duplicate checking in expr switches
|
"bug200.go", // TODO(gri) complete duplicate checking in expr switches
|
||||||
|
|
|
||||||
|
|
@ -44,12 +44,19 @@ func interface_conversions() {
|
||||||
|
|
||||||
type I2 interface{
|
type I2 interface{
|
||||||
m1()
|
m1()
|
||||||
m2()
|
m2(x int)
|
||||||
|
}
|
||||||
|
|
||||||
|
type I3 interface{
|
||||||
|
m1()
|
||||||
|
m2() int
|
||||||
}
|
}
|
||||||
|
|
||||||
var e E
|
var e E
|
||||||
var i1 I1
|
var i1 I1
|
||||||
var i2 I2
|
var i2 I2
|
||||||
|
var i3 I3
|
||||||
|
|
||||||
_ = E(0)
|
_ = E(0)
|
||||||
_ = E(nil)
|
_ = E(nil)
|
||||||
_ = E(e)
|
_ = E(e)
|
||||||
|
|
@ -59,10 +66,18 @@ func interface_conversions() {
|
||||||
_ = I1 /* ERROR "cannot convert" */ (0)
|
_ = I1 /* ERROR "cannot convert" */ (0)
|
||||||
_ = I1(nil)
|
_ = I1(nil)
|
||||||
_ = I1(i1)
|
_ = I1(i1)
|
||||||
_ = I1 /* ERROR "cannot convert" */ (e)
|
_ = I1(e)
|
||||||
_ = I1(i2)
|
_ = 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
|
// TODO(gri) add more tests, improve error message
|
||||||
}
|
}
|
||||||
|
|
@ -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() {
|
func rangeloops() {
|
||||||
var (
|
var (
|
||||||
x int
|
x int
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue