1
0
mirror of https://github.com/golang/go synced 2024-11-17 21:54:49 -07:00

go/types: report correct argument types for make() built-in calls

Change Checker.index to return the type and constant index value
rather than just a boolean valid flag and the constant value.
While at it, rename some variables and simplify the control flow.

Adjust all uses of Checker.index to new signature. In code for
make() built-in, collect type information for signature reporting.

Fixes #37393.

Change-Id: Id70196faa9539ed5a0d6b59e0f3ea05e05f2f6a2
Reviewed-on: https://go-review.googlesource.com/c/go/+/220585
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Robert Griesemer 2020-02-23 13:36:46 -08:00
parent 3093959ee1
commit d243408ae5
3 changed files with 37 additions and 30 deletions

View File

@ -441,10 +441,13 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
check.errorf(call.Pos(), "%v expects %d or %d arguments; found %d", call, min, min+1, nargs) check.errorf(call.Pos(), "%v expects %d or %d arguments; found %d", call, min, min+1, nargs)
return return
} }
types := []Type{T}
var sizes []int64 // constant integer arguments, if any var sizes []int64 // constant integer arguments, if any
for _, arg := range call.Args[1:] { for _, arg := range call.Args[1:] {
if s, ok := check.index(arg, -1); ok && s >= 0 { typ, size := check.index(arg, -1) // ok to continue with typ == Typ[Invalid]
sizes = append(sizes, s) types = append(types, typ)
if size >= 0 {
sizes = append(sizes, size)
} }
} }
if len(sizes) == 2 && sizes[0] > sizes[1] { if len(sizes) == 2 && sizes[0] > sizes[1] {
@ -454,8 +457,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
x.mode = value x.mode = value
x.typ = T x.typ = T
if check.Types != nil { if check.Types != nil {
params := [...]Type{T, Typ[Int], Typ[Int]} check.recordBuiltinType(call.Fun, makeSig(x.typ, types...))
check.recordBuiltinType(call.Fun, makeSig(x.typ, params[:nargs]...))
} }
case _New: case _New:

View File

@ -79,14 +79,13 @@ var builtinCalls = []struct {
{"make", `var c int; _ = make([]int, 0, c)`, `func([]int, int, int) []int`}, {"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`}, {"make", `var l, c int; _ = make([]int, l, c)`, `func([]int, int, int) []int`},
// TODO(gri) enable once the issue is fixed
// issue #37393 // issue #37393
// {"make", ` _ = make([]int , 0 )`, `func([]int, int) []int`}, {"make", ` _ = make([]int , 0 )`, `func([]int, int) []int`},
// {"make", `var l byte ; _ = make([]int8 , l )`, `func([]int8, byte) []int8`}, {"make", `var l byte ; _ = make([]int8 , l )`, `func([]int8, byte) []int8`},
// {"make", ` _ = make([]int16 , 0, 0)`, `func([]int16, int, int) []int16`}, {"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 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 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", `var l, c uint ; _ = make([]complex128, l, c)`, `func([]complex128, uint, uint) []complex128`},
{"new", `_ = new(int)`, `func(int) *int`}, {"new", `_ = new(int)`, `func(int) *int`},
{"new", `type T struct{}; _ = new(T)`, `func(p.T) *p.T`}, {"new", `type T struct{}; _ = new(T)`, `func(p.T) *p.T`},

View File

@ -868,8 +868,12 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
// index checks an index expression for validity. // index checks an index expression for validity.
// If max >= 0, it is the upper bound for index. // 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. // If the result typ is != Typ[Invalid], index is valid and typ is its (possibly named) integer type.
func (check *Checker) index(index ast.Expr, max int64) (i int64, valid bool) { // 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 var x operand
check.expr(&x, index) check.expr(&x, index)
if x.mode == invalid { if x.mode == invalid {
@ -888,22 +892,24 @@ func (check *Checker) index(index ast.Expr, max int64) (i int64, valid bool) {
return return
} }
if x.mode != constant_ {
return x.typ, -1
}
// a constant index i must be in bounds // a constant index i must be in bounds
if x.mode == constant_ {
if constant.Sign(x.val) < 0 { if constant.Sign(x.val) < 0 {
check.invalidArg(x.pos(), "index %s must not be negative", &x) check.invalidArg(x.pos(), "index %s must not be negative", &x)
return return
} }
i, valid = constant.Int64Val(constant.ToInt(x.val))
if !valid || max >= 0 && i >= max { 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) check.errorf(x.pos(), "index %s is out of bounds", &x)
return i, false return
}
// 0 <= i [ && i < max ]
return i, true
} }
return -1, true // 0 <= v [ && v < max ]
return Typ[Int], v
} }
// indexElts checks the elements (elts) of an array or slice composite literal // indexElts checks the elements (elts) of an array or slice composite literal
@ -919,7 +925,7 @@ func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64
validIndex := false validIndex := false
eval := e eval := e
if kv, _ := e.(*ast.KeyValueExpr); kv != nil { 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 { if i >= 0 {
index = i index = i
validIndex = true validIndex = true
@ -1411,8 +1417,8 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
if length >= 0 { if length >= 0 {
max = length + 1 max = length + 1
} }
if t, ok := check.index(expr, max); ok && t >= 0 { if _, v := check.index(expr, max); v >= 0 {
x = t x = v
} }
case i == 0: case i == 0:
// default is 0 for the first index // default is 0 for the first index