diff --git a/go/types/assignments.go b/go/types/assignments.go index af875a00..73aa55b3 100644 --- a/go/types/assignments.go +++ b/go/types/assignments.go @@ -68,15 +68,23 @@ func (check *checker) assignment(x *operand, T Type) bool { } func (check *checker) initConst(lhs *Const, x *operand) { - lhs.val = exact.MakeUnknown() - if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] { if lhs.typ == nil { lhs.typ = Typ[Invalid] } - return // nothing else to check + return } + // rhs must be a constant + if x.mode != constant { + check.errorf(x.pos(), "%s is not constant", x) + if lhs.typ == nil { + lhs.typ = Typ[Invalid] + } + return + } + assert(isConstType(x.typ)) + // If the lhs doesn't have a type yet, use the type of x. if lhs.typ == nil { lhs.typ = x.typ @@ -86,16 +94,10 @@ func (check *checker) initConst(lhs *Const, x *operand) { if x.mode != invalid { check.errorf(x.pos(), "cannot define constant %s (type %s) as %s", lhs.Name(), lhs.typ, x) } + lhs.val = exact.MakeUnknown() return } - // rhs must be a constant - if x.mode != constant { - check.errorf(x.pos(), "%s is not constant", x) - return - } - - assert(isConstType(x.typ)) lhs.val = x.val } @@ -104,7 +106,7 @@ func (check *checker) initVar(lhs *Var, x *operand) Type { if lhs.typ == nil { lhs.typ = Typ[Invalid] } - return nil // nothing else to check + return nil } // If the lhs doesn't have a type yet, use the type of x. @@ -115,7 +117,7 @@ func (check *checker) initVar(lhs *Var, x *operand) Type { if typ == Typ[UntypedNil] { check.errorf(x.pos(), "use of untyped nil") lhs.typ = Typ[Invalid] - return nil // nothing else to check + return nil } typ = defaultType(typ) } @@ -202,7 +204,12 @@ func (check *checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos) l := len(lhs) get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid()) if l != r { - invalidateVars(lhs) + // invalidate lhs + for _, obj := range lhs { + if obj.typ == nil { + obj.typ = Typ[Invalid] + } + } if returnPos.IsValid() { check.errorf(returnPos, "wrong number of return values (want %d, got %d)", l, r) return @@ -300,11 +307,3 @@ func (check *checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) { check.errorf(pos, "no new variables on left side of :=") } } - -func invalidateVars(list []*Var) { - for _, obj := range list { - if obj.typ == nil { - obj.typ = Typ[Invalid] - } - } -} diff --git a/go/types/resolver.go b/go/types/resolver.go index 66d69f70..15f58ab5 100644 --- a/go/types/resolver.go +++ b/go/types/resolver.go @@ -657,7 +657,13 @@ func (check *checker) constDecl(obj *Const, typ, init ast.Expr) { // determine type, if any if typ != nil { - obj.typ = check.typ(typ, nil, false) + t := check.typ(typ, nil, false) + if !isConstType(t) { + check.errorf(typ.Pos(), "invalid constant type %s", t) + obj.typ = Typ[Invalid] + return + } + obj.typ = t } // check initialization diff --git a/go/types/testdata/const0.src b/go/types/testdata/const0.src index 4581fe97..b39151dd 100644 --- a/go/types/testdata/const0.src +++ b/go/types/testdata/const0.src @@ -10,6 +10,9 @@ package const0 var x = 0 const c0 = x /* ERROR "not constant" */ +// typed constants must have constant types +const _ interface /* ERROR invalid constant type */ {} = 0 + // untyped constants const ( // boolean values