interp: fix a bug when assigning to an empty interface
The concrete type was not forwarded propertly in case of a binary expression involving a valueT. The corresponding part in type.go has been refactored and the now the multi-assign case should be handled as well. Fixes #1094.
This commit is contained in:
@@ -277,40 +277,26 @@ func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Because an empty interface concrete type "mutates" as different values are
|
||||
// assigned to it, we need to make a new itype from scratch everytime a new
|
||||
// assignment is made, and not let different nodes (of the same variable) share the
|
||||
// same itype. Otherwise they would overwrite each other.
|
||||
if n.anc.kind == assignStmt && isInterface(n.anc.child[0].typ) && len(n.anc.child[0].typ.field) == 0 {
|
||||
// TODO(mpl): do the indexes properly for multiple assignments on the same line.
|
||||
// Also, maybe we should use nodeType to figure out dt.cat? but isn't it always
|
||||
// gonna be an interfaceT anyway?
|
||||
dt := new(itype)
|
||||
dt.cat = interfaceT
|
||||
val := new(itype)
|
||||
val.cat = t.cat
|
||||
dt.val = val
|
||||
// TODO(mpl): do the indexes properly for multiple assignments on the same line.
|
||||
// Also, maybe we should use nodeType to figure out dt.cat? but isn't it always
|
||||
// gonna be an interfaceT anyway?
|
||||
n.anc.child[0].typ = dt
|
||||
// TODO(mpl): not sure yet whether we should do that last step. It doesn't seem
|
||||
// to change anything either way though.
|
||||
// t = dt
|
||||
break
|
||||
}
|
||||
|
||||
// If the node is to be assigned or returned, the node type is the destination type.
|
||||
dt := t
|
||||
|
||||
switch a := n.anc; {
|
||||
case a.kind == assignStmt && isEmptyInterface(a.child[0].typ):
|
||||
// Because an empty interface concrete type "mutates" as different values are
|
||||
// assigned to it, we need to make a new itype from scratch everytime a new
|
||||
// assignment is made, and not let different nodes (of the same variable) share the
|
||||
// same itype. Otherwise they would overwrite each other.
|
||||
a.child[0].typ = &itype{cat: interfaceT, val: dt}
|
||||
|
||||
case a.kind == defineStmt && len(a.child) > a.nleft+a.nright:
|
||||
if dt, err = nodeType(interp, sc, a.child[a.nleft]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
case a.kind == returnStmt:
|
||||
dt = sc.def.typ.ret[childPos(n)]
|
||||
}
|
||||
|
||||
if isInterface(dt) {
|
||||
dt.val = t
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user