interp: fix default type for constants from runtime

The default type must be derived from the constant value when necessary,
otherwise the type check fails wrongly.

Fixes #1026.
This commit is contained in:
Marc Vertes
2021-02-03 11:48:03 +01:00
committed by GitHub
parent b9b0897d95
commit 3f4e1665b1
3 changed files with 31 additions and 6 deletions

11
_test/time16.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "time"
func main() {
localTime := time.ANSIC
println(localTime)
}
// Output:
// Mon Jan _2 15:04:05 2006

View File

@@ -1502,10 +1502,25 @@ func (t *itype) implements(it *itype) bool {
}
// defaultType returns the default type of an untyped type.
func (t *itype) defaultType() *itype {
func (t *itype) defaultType(v reflect.Value) *itype {
if !t.untyped {
return t
}
// The default type can also be derived from a constant value.
if v.IsValid() && t.TypeOf().Implements(constVal) {
switch v.Interface().(constant.Value).Kind() {
case constant.String:
t = untypedString()
case constant.Bool:
t = untypedBool()
case constant.Int:
t = untypedInt()
case constant.Float:
t = untypedFloat()
case constant.Complex:
t = untypedComplex()
}
}
typ := *t
typ.untyped = false
return &typ

View File

@@ -37,7 +37,7 @@ func (check typecheck) assignment(n *node, typ *itype, context string) error {
if typ == nil && n.typ.cat == nilT {
return n.cfgErrorf("use of untyped nil in %s", context)
}
typ = n.typ.defaultType()
typ = n.typ.defaultType(n.rval)
}
if err := check.convertUntyped(n, typ); err != nil {
return err
@@ -65,7 +65,7 @@ func (check typecheck) assignExpr(n, dest, src *node) error {
isConst := n.anc.kind == constDecl
if !isConst {
// var operations must be typed
dest.typ = dest.typ.defaultType()
dest.typ = dest.typ.defaultType(src.rval)
}
return check.assignment(src, dest.typ, "assignment")
@@ -636,7 +636,7 @@ func (check typecheck) conversion(n *node, typ *itype) error {
return nil
}
if isInterface(typ) || !isConstType(typ) {
typ = n.typ.defaultType()
typ = n.typ.defaultType(n.rval)
}
return check.convertUntyped(n, typ)
}
@@ -1037,9 +1037,8 @@ func (check typecheck) convertUntyped(n *node, typ *itype) error {
if len(n.typ.methods()) > 0 { // untyped cannot be set to iface
return convErr
}
ityp = n.typ.defaultType()
ityp = n.typ.defaultType(n.rval)
rtyp = ntyp
case isArray(typ) || isMap(typ) || isChan(typ) || isFunc(typ) || isPtr(typ):
// TODO(nick): above we are acting on itype, but really it is an rtype check. This is not clear which type
// plain we are in. Fix this later.