go.tools/go/types: constants must have constant types

R=adonovan
CC=golang-dev
https://golang.org/cl/33210043
This commit is contained in:
Robert Griesemer 2013-11-26 12:42:52 -08:00
parent f2a9326f67
commit 3d343e42d1
3 changed files with 30 additions and 22 deletions

View File

@ -68,15 +68,23 @@ func (check *checker) assignment(x *operand, T Type) bool {
} }
func (check *checker) initConst(lhs *Const, x *operand) { 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 x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
if lhs.typ == nil { if lhs.typ == nil {
lhs.typ = Typ[Invalid] 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 the lhs doesn't have a type yet, use the type of x.
if lhs.typ == nil { if lhs.typ == nil {
lhs.typ = x.typ lhs.typ = x.typ
@ -86,16 +94,10 @@ func (check *checker) initConst(lhs *Const, x *operand) {
if x.mode != invalid { if x.mode != invalid {
check.errorf(x.pos(), "cannot define constant %s (type %s) as %s", lhs.Name(), lhs.typ, x) check.errorf(x.pos(), "cannot define constant %s (type %s) as %s", lhs.Name(), lhs.typ, x)
} }
lhs.val = exact.MakeUnknown()
return 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 lhs.val = x.val
} }
@ -104,7 +106,7 @@ func (check *checker) initVar(lhs *Var, x *operand) Type {
if lhs.typ == nil { if lhs.typ == nil {
lhs.typ = Typ[Invalid] 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. // 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] { if typ == Typ[UntypedNil] {
check.errorf(x.pos(), "use of untyped nil") check.errorf(x.pos(), "use of untyped nil")
lhs.typ = Typ[Invalid] lhs.typ = Typ[Invalid]
return nil // nothing else to check return nil
} }
typ = defaultType(typ) typ = defaultType(typ)
} }
@ -202,7 +204,12 @@ func (check *checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos)
l := len(lhs) l := len(lhs)
get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid()) get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid())
if l != r { if l != r {
invalidateVars(lhs) // invalidate lhs
for _, obj := range lhs {
if obj.typ == nil {
obj.typ = Typ[Invalid]
}
}
if returnPos.IsValid() { if returnPos.IsValid() {
check.errorf(returnPos, "wrong number of return values (want %d, got %d)", l, r) check.errorf(returnPos, "wrong number of return values (want %d, got %d)", l, r)
return 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 :=") 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]
}
}
}

View File

@ -657,7 +657,13 @@ func (check *checker) constDecl(obj *Const, typ, init ast.Expr) {
// determine type, if any // determine type, if any
if typ != nil { 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 // check initialization

View File

@ -10,6 +10,9 @@ package const0
var x = 0 var x = 0
const c0 = x /* ERROR "not constant" */ const c0 = x /* ERROR "not constant" */
// typed constants must have constant types
const _ interface /* ERROR invalid constant type */ {} = 0
// untyped constants // untyped constants
const ( const (
// boolean values // boolean values