Skip to content

Commit

Permalink
interp: fix default type for constants from runtime
Browse files Browse the repository at this point in the history
The default type must be derived from the constant value when necessary,
otherwise the type check fails wrongly.

Fixes #1026.
  • Loading branch information
mvertes authored Feb 3, 2021
1 parent b9b0897 commit 3f4e166
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 6 deletions.
11 changes: 11 additions & 0 deletions _test/time16.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package main

import "time"

func main() {
localTime := time.ANSIC
println(localTime)
}

// Output:
// Mon Jan _2 15:04:05 2006
17 changes: 16 additions & 1 deletion interp/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 4 additions & 5 deletions interp/typecheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 3f4e166

Please sign in to comment.