mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
go/types, types2: better error message for invalid array length
If an invalid array length is just an identifier, mention "array length" so that it's clear this is an invalid array declaration and not a (invalid) generic type declaration. Fixes #51145. Change-Id: I8878cbb6c7b1277fc0a9a014712ec8d55499c5c7 Reviewed-on: https://go-review.googlesource.com/c/go/+/385255 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
bcee121ae4
commit
badba359da
|
@ -9,7 +9,7 @@ const L = 10
|
|||
type (
|
||||
_ [L]struct{}
|
||||
_ [A /* ERROR undeclared name A for array length */ ]struct{}
|
||||
_ [B /* ERROR not an expression */ ]struct{}
|
||||
_ [B /* ERROR invalid array length B */ ]struct{}
|
||||
_[A any] struct{}
|
||||
|
||||
B int
|
||||
|
|
18
src/cmd/compile/internal/types2/testdata/fixedbugs/issue51145.go
vendored
Normal file
18
src/cmd/compile/internal/types2/testdata/fixedbugs/issue51145.go
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
|
||||
import "fmt"
|
||||
|
||||
type (
|
||||
_ [fmt /* ERROR invalid array length fmt */ ]int
|
||||
_ [float64 /* ERROR invalid array length float64 */ ]int
|
||||
_ [f /* ERROR invalid array length f */ ]int
|
||||
_ [nil /* ERROR invalid array length nil */ ]int
|
||||
)
|
||||
|
||||
func f()
|
||||
|
||||
var _ fmt.Stringer // use fmt
|
|
@ -502,12 +502,20 @@ func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *
|
|||
// and returns the constant length >= 0, or a value < 0
|
||||
// to indicate an error (and thus an unknown length).
|
||||
func (check *Checker) arrayLength(e syntax.Expr) int64 {
|
||||
// If e is an undeclared identifier, the array declaration might be an
|
||||
// attempt at a parameterized type declaration with missing constraint.
|
||||
// Provide a better error message than just "undeclared name: X".
|
||||
if name, _ := e.(*syntax.Name); name != nil && check.lookup(name.Value) == nil {
|
||||
check.errorf(name, "undeclared name %s for array length", name.Value)
|
||||
return -1
|
||||
// If e is an identifier, the array declaration might be an
|
||||
// attempt at a parameterized type declaration with missing
|
||||
// constraint. Provide an error message that mentions array
|
||||
// length.
|
||||
if name, _ := e.(*syntax.Name); name != nil {
|
||||
obj := check.lookup(name.Value)
|
||||
if obj == nil {
|
||||
check.errorf(name, "undeclared name %s for array length", name.Value)
|
||||
return -1
|
||||
}
|
||||
if _, ok := obj.(*Const); !ok {
|
||||
check.errorf(name, "invalid array length %s", name.Value)
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
var x operand
|
||||
|
|
|
@ -98,13 +98,10 @@ const (
|
|||
// _InvalidDeclCycle occurs when a declaration cycle is not valid.
|
||||
//
|
||||
// Example:
|
||||
// import "unsafe"
|
||||
//
|
||||
// type T struct {
|
||||
// a [n]int
|
||||
// type S struct {
|
||||
// S
|
||||
// }
|
||||
//
|
||||
// var n = unsafe.Sizeof(T{})
|
||||
_InvalidDeclCycle
|
||||
|
||||
// _InvalidTypeCycle occurs when a cycle in type definitions results in a
|
||||
|
|
|
@ -9,7 +9,7 @@ const L = 10
|
|||
type (
|
||||
_ [L]struct{}
|
||||
_ [A /* ERROR undeclared name A for array length */ ]struct{}
|
||||
_ [B /* ERROR not an expression */ ]struct{}
|
||||
_ [B /* ERROR invalid array length B */ ]struct{}
|
||||
_[A any] struct{}
|
||||
|
||||
B int
|
||||
|
|
18
src/go/types/testdata/fixedbugs/issue51145.go
vendored
Normal file
18
src/go/types/testdata/fixedbugs/issue51145.go
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
|
||||
import "fmt"
|
||||
|
||||
type (
|
||||
_ [fmt /* ERROR invalid array length fmt */ ]int
|
||||
_ [float64 /* ERROR invalid array length float64 */ ]int
|
||||
_ [f /* ERROR invalid array length f */ ]int
|
||||
_ [nil /* ERROR invalid array length nil */ ]int
|
||||
)
|
||||
|
||||
func f()
|
||||
|
||||
var _ fmt.Stringer // use fmt
|
|
@ -487,12 +487,20 @@ func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (re
|
|||
// and returns the constant length >= 0, or a value < 0
|
||||
// to indicate an error (and thus an unknown length).
|
||||
func (check *Checker) arrayLength(e ast.Expr) int64 {
|
||||
// If e is an undeclared identifier, the array declaration might be an
|
||||
// attempt at a parameterized type declaration with missing constraint.
|
||||
// Provide a better error message than just "undeclared name: X".
|
||||
if name, _ := e.(*ast.Ident); name != nil && check.lookup(name.Name) == nil {
|
||||
check.errorf(name, _InvalidArrayLen, "undeclared name %s for array length", name.Name)
|
||||
return -1
|
||||
// If e is an identifier, the array declaration might be an
|
||||
// attempt at a parameterized type declaration with missing
|
||||
// constraint. Provide an error message that mentions array
|
||||
// length.
|
||||
if name, _ := e.(*ast.Ident); name != nil {
|
||||
obj := check.lookup(name.Name)
|
||||
if obj == nil {
|
||||
check.errorf(name, _InvalidArrayLen, "undeclared name %s for array length", name.Name)
|
||||
return -1
|
||||
}
|
||||
if _, ok := obj.(*Const); !ok {
|
||||
check.errorf(name, _InvalidArrayLen, "invalid array length %s", name.Name)
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
var x operand
|
||||
|
|
|
@ -6,12 +6,13 @@
|
|||
|
||||
package main
|
||||
|
||||
var a [10]int // ok
|
||||
var b [1e1]int // ok
|
||||
var c [1.5]int // ERROR "truncated|must be integer"
|
||||
var d ["abc"]int // ERROR "invalid array bound|not numeric|must be integer"
|
||||
var e [nil]int // ERROR "use of untyped nil|invalid array bound|not numeric|must be constant"
|
||||
var f [e]int // ok: error already reported for e
|
||||
var a [10]int // ok
|
||||
var b [1e1]int // ok
|
||||
var c [1.5]int // ERROR "truncated|must be integer"
|
||||
var d ["abc"]int // ERROR "invalid array bound|not numeric|must be integer"
|
||||
var e [nil]int // ERROR "use of untyped nil|invalid array (bound|length)|not numeric|must be constant"
|
||||
// var f [e]int // ok with Go 1.17 because an error was reported for e; leads to an error for Go 1.18
|
||||
var f [ee]int // ERROR "undefined|undeclared"
|
||||
var g [1 << 65]int // ERROR "array bound is too large|overflows|must be integer"
|
||||
var h [len(a)]int // ok
|
||||
|
||||
|
|
Loading…
Reference in a new issue