interp: improve type assertions
In type assertion at compile time, compare signatures between function types only. Make `itype.numOut()` return the correct value for Go builtins (this was not strictly necessary due to above fix, but it is correct and improves maintainability). Fixes #1454.
This commit is contained in:
22
_test/issue-1454.go
Normal file
22
_test/issue-1454.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
type I2 interface {
|
||||
I2() string
|
||||
}
|
||||
|
||||
type I interface {
|
||||
I2
|
||||
}
|
||||
|
||||
type S struct{}
|
||||
|
||||
func (*S) I2() string { return "foo" }
|
||||
|
||||
func main() {
|
||||
var i I
|
||||
_, ok := i.(*S)
|
||||
println(ok)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// false
|
||||
@@ -1060,7 +1060,7 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
||||
}
|
||||
|
||||
n.gen = c0.sym.builtin
|
||||
c0.typ = &itype{cat: builtinT}
|
||||
c0.typ = &itype{cat: builtinT, name: bname}
|
||||
if n.typ, err = nodeType(interp, sc, n); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1249,8 +1249,13 @@ func (t *itype) numOut() int {
|
||||
if t.rtype.Kind() == reflect.Func {
|
||||
return t.rtype.NumOut()
|
||||
}
|
||||
case builtinT:
|
||||
switch t.name {
|
||||
case "append", "cap", "complex", "copy", "imag", "len", "make", "new", "real", "recover":
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
func (t *itype) out(i int) *itype {
|
||||
|
||||
@@ -625,6 +625,11 @@ func (check typecheck) typeAssertionExpr(n *node, typ *itype) error {
|
||||
return n.cfgErrorf("impossible type assertion: %s does not implement %s as %q method has a pointer receiver", typ.id(), n.typ.id(), name)
|
||||
}
|
||||
|
||||
if im.cat != funcT || tm.cat != funcT {
|
||||
// It only makes sense to compare in/out parameter types if both types are functions.
|
||||
continue
|
||||
}
|
||||
|
||||
err := n.cfgErrorf("impossible type assertion: %s does not implement %s", typ.id(), n.typ.id())
|
||||
if im.numIn() != tm.numIn() || im.numOut() != tm.numOut() {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user