Skip to content

Commit badba35

Browse files
committed
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 <[email protected]> Run-TryBot: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent bcee121 commit badba35

File tree

8 files changed

+75
-25
lines changed

8 files changed

+75
-25
lines changed

src/cmd/compile/internal/types2/testdata/fixedbugs/issue43527.go2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const L = 10
99
type (
1010
_ [L]struct{}
1111
_ [A /* ERROR undeclared name A for array length */ ]struct{}
12-
_ [B /* ERROR not an expression */ ]struct{}
12+
_ [B /* ERROR invalid array length B */ ]struct{}
1313
_[A any] struct{}
1414

1515
B int
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
import "fmt"
8+
9+
type (
10+
_ [fmt /* ERROR invalid array length fmt */ ]int
11+
_ [float64 /* ERROR invalid array length float64 */ ]int
12+
_ [f /* ERROR invalid array length f */ ]int
13+
_ [nil /* ERROR invalid array length nil */ ]int
14+
)
15+
16+
func f()
17+
18+
var _ fmt.Stringer // use fmt

src/cmd/compile/internal/types2/typexpr.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -502,12 +502,20 @@ func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *
502502
// and returns the constant length >= 0, or a value < 0
503503
// to indicate an error (and thus an unknown length).
504504
func (check *Checker) arrayLength(e syntax.Expr) int64 {
505-
// If e is an undeclared identifier, the array declaration might be an
506-
// attempt at a parameterized type declaration with missing constraint.
507-
// Provide a better error message than just "undeclared name: X".
508-
if name, _ := e.(*syntax.Name); name != nil && check.lookup(name.Value) == nil {
509-
check.errorf(name, "undeclared name %s for array length", name.Value)
510-
return -1
505+
// If e is an identifier, the array declaration might be an
506+
// attempt at a parameterized type declaration with missing
507+
// constraint. Provide an error message that mentions array
508+
// length.
509+
if name, _ := e.(*syntax.Name); name != nil {
510+
obj := check.lookup(name.Value)
511+
if obj == nil {
512+
check.errorf(name, "undeclared name %s for array length", name.Value)
513+
return -1
514+
}
515+
if _, ok := obj.(*Const); !ok {
516+
check.errorf(name, "invalid array length %s", name.Value)
517+
return -1
518+
}
511519
}
512520

513521
var x operand

src/go/types/errorcodes.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,10 @@ const (
9898
// _InvalidDeclCycle occurs when a declaration cycle is not valid.
9999
//
100100
// Example:
101-
// import "unsafe"
102-
//
103-
// type T struct {
104-
// a [n]int
101+
// type S struct {
102+
// S
105103
// }
106104
//
107-
// var n = unsafe.Sizeof(T{})
108105
_InvalidDeclCycle
109106

110107
// _InvalidTypeCycle occurs when a cycle in type definitions results in a

src/go/types/testdata/fixedbugs/issue43527.go2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const L = 10
99
type (
1010
_ [L]struct{}
1111
_ [A /* ERROR undeclared name A for array length */ ]struct{}
12-
_ [B /* ERROR not an expression */ ]struct{}
12+
_ [B /* ERROR invalid array length B */ ]struct{}
1313
_[A any] struct{}
1414

1515
B int
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
import "fmt"
8+
9+
type (
10+
_ [fmt /* ERROR invalid array length fmt */ ]int
11+
_ [float64 /* ERROR invalid array length float64 */ ]int
12+
_ [f /* ERROR invalid array length f */ ]int
13+
_ [nil /* ERROR invalid array length nil */ ]int
14+
)
15+
16+
func f()
17+
18+
var _ fmt.Stringer // use fmt

src/go/types/typexpr.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -487,12 +487,20 @@ func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (re
487487
// and returns the constant length >= 0, or a value < 0
488488
// to indicate an error (and thus an unknown length).
489489
func (check *Checker) arrayLength(e ast.Expr) int64 {
490-
// If e is an undeclared identifier, the array declaration might be an
491-
// attempt at a parameterized type declaration with missing constraint.
492-
// Provide a better error message than just "undeclared name: X".
493-
if name, _ := e.(*ast.Ident); name != nil && check.lookup(name.Name) == nil {
494-
check.errorf(name, _InvalidArrayLen, "undeclared name %s for array length", name.Name)
495-
return -1
490+
// If e is an identifier, the array declaration might be an
491+
// attempt at a parameterized type declaration with missing
492+
// constraint. Provide an error message that mentions array
493+
// length.
494+
if name, _ := e.(*ast.Ident); name != nil {
495+
obj := check.lookup(name.Name)
496+
if obj == nil {
497+
check.errorf(name, _InvalidArrayLen, "undeclared name %s for array length", name.Name)
498+
return -1
499+
}
500+
if _, ok := obj.(*Const); !ok {
501+
check.errorf(name, _InvalidArrayLen, "invalid array length %s", name.Name)
502+
return -1
503+
}
496504
}
497505

498506
var x operand

test/fixedbugs/bug255.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66

77
package main
88

9-
var a [10]int // ok
10-
var b [1e1]int // ok
11-
var c [1.5]int // ERROR "truncated|must be integer"
12-
var d ["abc"]int // ERROR "invalid array bound|not numeric|must be integer"
13-
var e [nil]int // ERROR "use of untyped nil|invalid array bound|not numeric|must be constant"
14-
var f [e]int // ok: error already reported for e
9+
var a [10]int // ok
10+
var b [1e1]int // ok
11+
var c [1.5]int // ERROR "truncated|must be integer"
12+
var d ["abc"]int // ERROR "invalid array bound|not numeric|must be integer"
13+
var e [nil]int // ERROR "use of untyped nil|invalid array (bound|length)|not numeric|must be constant"
14+
// var f [e]int // ok with Go 1.17 because an error was reported for e; leads to an error for Go 1.18
15+
var f [ee]int // ERROR "undefined|undeclared"
1516
var g [1 << 65]int // ERROR "array bound is too large|overflows|must be integer"
1617
var h [len(a)]int // ok
1718

0 commit comments

Comments
 (0)