go.tools/go/types: fix logic error in MissingMethod and type assert code
R=adonovan CC=golang-dev https://golang.org/cl/10448046
This commit is contained in:
parent
decfd079c5
commit
628104465d
|
@ -1564,7 +1564,7 @@ func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type, iota int, cycle
|
||||||
}
|
}
|
||||||
// x.(type) expressions are handled explicitly in type switches
|
// x.(type) expressions are handled explicitly in type switches
|
||||||
if e.Type == nil {
|
if e.Type == nil {
|
||||||
check.errorf(e.Pos(), "use of .(type) outside type switch")
|
check.invalidAST(e.Pos(), "use of .(type) outside type switch")
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
typ := check.typ(e.Type, false)
|
typ := check.typ(e.Type, false)
|
||||||
|
@ -1575,10 +1575,15 @@ func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type, iota int, cycle
|
||||||
var msg string
|
var msg string
|
||||||
if wrongType {
|
if wrongType {
|
||||||
msg = "%s cannot have dynamic type %s (wrong type for method %s)"
|
msg = "%s cannot have dynamic type %s (wrong type for method %s)"
|
||||||
} else {
|
} else if _, ok := typ.Underlying().(*Interface); !ok {
|
||||||
|
// Concrete types must have all methods of T. Interfaces
|
||||||
|
// may not have all methods of T statically, but may have
|
||||||
|
// them dynamically; don't report an error in that case.
|
||||||
msg = "%s cannot have dynamic type %s (missing method %s)"
|
msg = "%s cannot have dynamic type %s (missing method %s)"
|
||||||
}
|
}
|
||||||
|
if msg != "" {
|
||||||
check.errorf(e.Type.Pos(), msg, x, typ, method.name)
|
check.errorf(e.Type.Pos(), msg, x, typ, method.name)
|
||||||
|
}
|
||||||
// ok to continue
|
// ok to continue
|
||||||
}
|
}
|
||||||
x.mode = valueok
|
x.mode = valueok
|
||||||
|
|
|
@ -188,17 +188,21 @@ func MissingMethod(typ Type, T *Interface) (method *Func, wrongType bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An interface type implements T if it has at least the methods of T.
|
||||||
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 && !IsIdentical(obj.Type(), m.typ) {
|
if obj == nil {
|
||||||
|
return m, false
|
||||||
|
}
|
||||||
|
if !IsIdentical(obj.Type(), m.typ) {
|
||||||
return m, true
|
return m, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// a concrete type implements T if it implements all methods of T.
|
// A concrete type implements T if it implements all methods of T.
|
||||||
for _, m := range T.methods {
|
for _, m := range T.methods {
|
||||||
obj, _, indirect := LookupFieldOrMethod(typ, m.pkg, m.name)
|
obj, _, indirect := LookupFieldOrMethod(typ, m.pkg, m.name)
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
|
@ -222,6 +226,7 @@ func MissingMethod(typ Type, T *Interface) (method *Func, wrongType bool) {
|
||||||
return m, true
|
return m, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,3 +34,35 @@ func string_conversions() {
|
||||||
var (
|
var (
|
||||||
_ = int8(0)
|
_ = int8(0)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func interface_conversions() {
|
||||||
|
type E interface{}
|
||||||
|
|
||||||
|
type I1 interface{
|
||||||
|
m1()
|
||||||
|
}
|
||||||
|
|
||||||
|
type I2 interface{
|
||||||
|
m1()
|
||||||
|
m2()
|
||||||
|
}
|
||||||
|
|
||||||
|
var e E
|
||||||
|
var i1 I1
|
||||||
|
var i2 I2
|
||||||
|
_ = E(0)
|
||||||
|
_ = E(nil)
|
||||||
|
_ = E(e)
|
||||||
|
_ = E(i1)
|
||||||
|
_ = E(i2)
|
||||||
|
|
||||||
|
_ = I1 /* ERROR "cannot convert" */ (0)
|
||||||
|
_ = I1(nil)
|
||||||
|
_ = I1(i1)
|
||||||
|
_ = I1 /* ERROR "cannot convert" */ (e)
|
||||||
|
_ = I1(i2)
|
||||||
|
|
||||||
|
_ = I2 /* ERROR "cannot convert" */ (i1)
|
||||||
|
|
||||||
|
// TODO(gri) add more tests, improve error message
|
||||||
|
}
|
|
@ -281,6 +281,9 @@ func type_asserts() {
|
||||||
_ = t.(T1 /* ERROR "missing method m" */ )
|
_ = t.(T1 /* ERROR "missing method m" */ )
|
||||||
_ = t.(T2 /* ERROR "wrong type for method m" */ )
|
_ = t.(T2 /* ERROR "wrong type for method m" */ )
|
||||||
_ = t.(I2 /* ERROR "wrong type for method m" */ )
|
_ = t.(I2 /* ERROR "wrong type for method m" */ )
|
||||||
|
|
||||||
|
// e doesn't statically have an m, but may have one dynamically.
|
||||||
|
_ = e.(I2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func f0() {}
|
func f0() {}
|
||||||
|
|
Loading…
Reference in New Issue