From 3f4e1665b14d2daa495f146a9ee55f7b14318318 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Wed, 3 Feb 2021 11:48:03 +0100 Subject: [PATCH] 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. --- _test/time16.go | 11 +++++++++++ interp/type.go | 17 ++++++++++++++++- interp/typecheck.go | 9 ++++----- 3 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 _test/time16.go diff --git a/_test/time16.go b/_test/time16.go new file mode 100644 index 000000000..8a7cdb99a --- /dev/null +++ b/_test/time16.go @@ -0,0 +1,11 @@ +package main + +import "time" + +func main() { + localTime := time.ANSIC + println(localTime) +} + +// Output: +// Mon Jan _2 15:04:05 2006 diff --git a/interp/type.go b/interp/type.go index 1da514f6a..852b2fc6a 100644 --- a/interp/type.go +++ b/interp/type.go @@ -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 diff --git a/interp/typecheck.go b/interp/typecheck.go index e98ed6442..b05080fb4 100644 --- a/interp/typecheck.go +++ b/interp/typecheck.go @@ -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.