]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types, types2: better error message for invalid array length
authorRobert Griesemer <gri@golang.org>
Fri, 11 Feb 2022 21:16:52 +0000 (13:16 -0800)
committerRobert Griesemer <gri@golang.org>
Fri, 11 Feb 2022 22:01:05 +0000 (22:01 +0000)
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>

src/cmd/compile/internal/types2/testdata/fixedbugs/issue43527.go2
src/cmd/compile/internal/types2/testdata/fixedbugs/issue51145.go [new file with mode: 0644]
src/cmd/compile/internal/types2/typexpr.go
src/go/types/errorcodes.go
src/go/types/testdata/fixedbugs/issue43527.go2
src/go/types/testdata/fixedbugs/issue51145.go [new file with mode: 0644]
src/go/types/typexpr.go
test/fixedbugs/bug255.go

index e4bcee51fe5f90420af7c385a53e748f485a4edc..2955c261f954ee33e647b83b6ddadbe651e57ca7 100644 (file)
@@ -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
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51145.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51145.go
new file mode 100644 (file)
index 0000000..b84391d
--- /dev/null
@@ -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
index de778fb010bf549b81503057079fc86746cacaa8..149bd5b0b3dfccc42448aa003e19fa7c7eec6887 100644 (file)
@@ -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
index 51f091a9cbe857c5f83ad57f9c2c71f89cdb1268..a7514b317a0ce11ff3953cf634df1419511edcf1 100644 (file)
@@ -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
index e4bcee51fe5f90420af7c385a53e748f485a4edc..2955c261f954ee33e647b83b6ddadbe651e57ca7 100644 (file)
@@ -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
diff --git a/src/go/types/testdata/fixedbugs/issue51145.go b/src/go/types/testdata/fixedbugs/issue51145.go
new file mode 100644 (file)
index 0000000..b84391d
--- /dev/null
@@ -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
index 00c250b5b6378714aa730eaaf615b45a044c26a1..db6a904aaa50e73bf82fc65d2eec926d4d735216 100644 (file)
@@ -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
index 38df7813c9d5a1dbee651fd3d421d1f5ddfb7a0d..184ff2d378b58d722711a78859437d757694ba72 100644 (file)
@@ -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