check.errorf(call.Pos(), "%v expects %d or %d arguments; found %d", call, min, min+1, nargs)
return
}
+ types := []Type{T}
var sizes []int64 // constant integer arguments, if any
for _, arg := range call.Args[1:] {
- if s, ok := check.index(arg, -1); ok && s >= 0 {
- sizes = append(sizes, s)
+ typ, size := check.index(arg, -1) // ok to continue with typ == Typ[Invalid]
+ types = append(types, typ)
+ if size >= 0 {
+ sizes = append(sizes, size)
}
}
if len(sizes) == 2 && sizes[0] > sizes[1] {
x.mode = value
x.typ = T
if check.Types != nil {
- params := [...]Type{T, Typ[Int], Typ[Int]}
- check.recordBuiltinType(call.Fun, makeSig(x.typ, params[:nargs]...))
+ check.recordBuiltinType(call.Fun, makeSig(x.typ, types...))
}
case _New:
{"make", `var c int; _ = make([]int, 0, c)`, `func([]int, int, int) []int`},
{"make", `var l, c int; _ = make([]int, l, c)`, `func([]int, int, int) []int`},
- // TODO(gri) enable once the issue is fixed
// issue #37393
- // {"make", ` _ = make([]int , 0 )`, `func([]int, int) []int`},
- // {"make", `var l byte ; _ = make([]int8 , l )`, `func([]int8, byte) []int8`},
- // {"make", ` _ = make([]int16 , 0, 0)`, `func([]int16, int, int) []int16`},
- // {"make", `var l int16; _ = make([]string , l, 0)`, `func([]string, int16, int) []string`},
- // {"make", `var c int32; _ = make([]float64 , 0, c)`, `func([]float64, int, int32) []float64`},
- // {"make", `var l, c uint ; _ = make([]complex128, l, c)`, `func([]complex128, uint, uint) []complex128`},
+ {"make", ` _ = make([]int , 0 )`, `func([]int, int) []int`},
+ {"make", `var l byte ; _ = make([]int8 , l )`, `func([]int8, byte) []int8`},
+ {"make", ` _ = make([]int16 , 0, 0)`, `func([]int16, int, int) []int16`},
+ {"make", `var l int16; _ = make([]string , l, 0)`, `func([]string, int16, int) []string`},
+ {"make", `var c int32; _ = make([]float64 , 0, c)`, `func([]float64, int, int32) []float64`},
+ {"make", `var l, c uint ; _ = make([]complex128, l, c)`, `func([]complex128, uint, uint) []complex128`},
{"new", `_ = new(int)`, `func(int) *int`},
{"new", `type T struct{}; _ = new(T)`, `func(p.T) *p.T`},
// index checks an index expression for validity.
// If max >= 0, it is the upper bound for index.
-// If index is valid and the result i >= 0, then i is the constant value of index.
-func (check *Checker) index(index ast.Expr, max int64) (i int64, valid bool) {
+// If the result typ is != Typ[Invalid], index is valid and typ is its (possibly named) integer type.
+// If the result val >= 0, index is valid and val is its constant int value.
+func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) {
+ typ = Typ[Invalid]
+ val = -1
+
var x operand
check.expr(&x, index)
if x.mode == invalid {
return
}
+ if x.mode != constant_ {
+ return x.typ, -1
+ }
+
// a constant index i must be in bounds
- if x.mode == constant_ {
- if constant.Sign(x.val) < 0 {
- check.invalidArg(x.pos(), "index %s must not be negative", &x)
- return
- }
- i, valid = constant.Int64Val(constant.ToInt(x.val))
- if !valid || max >= 0 && i >= max {
- check.errorf(x.pos(), "index %s is out of bounds", &x)
- return i, false
- }
- // 0 <= i [ && i < max ]
- return i, true
+ if constant.Sign(x.val) < 0 {
+ check.invalidArg(x.pos(), "index %s must not be negative", &x)
+ return
+ }
+
+ v, valid := constant.Int64Val(constant.ToInt(x.val))
+ if !valid || max >= 0 && v >= max {
+ check.errorf(x.pos(), "index %s is out of bounds", &x)
+ return
}
- return -1, true
+ // 0 <= v [ && v < max ]
+ return Typ[Int], v
}
// indexElts checks the elements (elts) of an array or slice composite literal
validIndex := false
eval := e
if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
- if i, ok := check.index(kv.Key, length); ok {
+ if typ, i := check.index(kv.Key, length); typ != Typ[Invalid] {
if i >= 0 {
index = i
validIndex = true
if length >= 0 {
max = length + 1
}
- if t, ok := check.index(expr, max); ok && t >= 0 {
- x = t
+ if _, v := check.index(expr, max); v >= 0 {
+ x = v
}
case i == 0:
// default is 0 for the first index