go.tools/go/types: set array type even if length is invalid
This avoids some follow-up errors due to invalid array declarations. LGTM=adonovan R=adonovan CC=golang-codereviews https://golang.org/cl/57640043
This commit is contained in:
parent
ffc6416213
commit
aea9f68811
|
|
@ -234,7 +234,7 @@ const (
|
||||||
_b1 = assert(iota + iota2 == 5)
|
_b1 = assert(iota + iota2 == 5)
|
||||||
_b2 = len([iota]int{}) // iota may appear in a type!
|
_b2 = len([iota]int{}) // iota may appear in a type!
|
||||||
_b3 = assert(_b2 == 2)
|
_b3 = assert(_b2 == 2)
|
||||||
_b4 = len(A /* ERROR "invalid composite literal" */ {})
|
_b4 = len(A{})
|
||||||
)
|
)
|
||||||
|
|
||||||
type A [iota /* ERROR "cannot use iota" */ ]int
|
type A [iota /* ERROR "cannot use iota" */ ]int
|
||||||
|
|
|
||||||
|
|
@ -245,30 +245,12 @@ func (check *checker) typInternal(e ast.Expr, def *Named, cycleOk bool) Type {
|
||||||
|
|
||||||
case *ast.ArrayType:
|
case *ast.ArrayType:
|
||||||
if e.Len != nil {
|
if e.Len != nil {
|
||||||
var x operand
|
|
||||||
check.expr(&x, e.Len)
|
|
||||||
if x.mode != constant {
|
|
||||||
if x.mode != invalid {
|
|
||||||
check.errorf(x.pos(), "array length %s must be constant", &x)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if !x.isInteger() {
|
|
||||||
check.errorf(x.pos(), "array length %s must be integer", &x)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
n, ok := exact.Int64Val(x.val)
|
|
||||||
if !ok || n < 0 {
|
|
||||||
check.errorf(x.pos(), "invalid array length %s", &x)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
typ := new(Array)
|
typ := new(Array)
|
||||||
if def != nil {
|
if def != nil {
|
||||||
def.underlying = typ
|
def.underlying = typ
|
||||||
}
|
}
|
||||||
|
|
||||||
typ.len = n
|
typ.len = check.arrayLength(e.Len)
|
||||||
typ.elem = check.typ(e.Elt, nil, cycleOk)
|
typ.elem = check.typ(e.Elt, nil, cycleOk)
|
||||||
return typ
|
return typ
|
||||||
|
|
||||||
|
|
@ -383,6 +365,27 @@ func (check *checker) typOrNil(e ast.Expr) Type {
|
||||||
return Typ[Invalid]
|
return Typ[Invalid]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (check *checker) arrayLength(e ast.Expr) int64 {
|
||||||
|
var x operand
|
||||||
|
check.expr(&x, e)
|
||||||
|
if x.mode != constant {
|
||||||
|
if x.mode != invalid {
|
||||||
|
check.errorf(x.pos(), "array length %s must be constant", &x)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if !x.isInteger() {
|
||||||
|
check.errorf(x.pos(), "array length %s must be integer", &x)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
n, ok := exact.Int64Val(x.val)
|
||||||
|
if !ok || n < 0 {
|
||||||
|
check.errorf(x.pos(), "invalid array length %s", &x)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
func (check *checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, isVariadic bool) {
|
func (check *checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, isVariadic bool) {
|
||||||
if list == nil {
|
if list == nil {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue