]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/syntax: better error message for missing type constraint
authorRobert Griesemer <gri@golang.org>
Thu, 9 Sep 2021 04:30:01 +0000 (21:30 -0700)
committerRobert Griesemer <gri@golang.org>
Thu, 9 Sep 2021 22:17:54 +0000 (22:17 +0000)
For #43527.

Change-Id: I8c706e68572286d5675383eb2dfd75b5618b646b
Reviewed-on: https://go-review.googlesource.com/c/go/+/348730
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/syntax/parser.go
src/cmd/compile/internal/syntax/testdata/issue43527.go2 [new file with mode: 0644]
src/cmd/compile/internal/syntax/testdata/tparams.go2
src/cmd/compile/internal/types2/testdata/fixedbugs/issue47996.go2

index e89796cb31f2b2d2db40d1356ea7cebd0fcb792f..c836a21c2fd437b8bf6fe46bc5a2d4708b7ef618 100644 (file)
@@ -1908,8 +1908,9 @@ func (p *parser) paramList(name *Name, close token, requireNames bool) (list []*
                defer p.trace("paramList")()
        }
 
-       var named int // number of parameters that have an explicit name and type/bound
-       p.list(_Comma, close, func() bool {
+       var named int // number of parameters that have an explicit name and type
+       var typed int // number of parameters that have an explicit type
+       end := p.list(_Comma, close, func() bool {
                par := p.paramDeclOrNil(name)
                name = nil // 1st name was consumed if present
                if par != nil {
@@ -1919,6 +1920,9 @@ func (p *parser) paramList(name *Name, close token, requireNames bool) (list []*
                        if par.Name != nil && par.Type != nil {
                                named++
                        }
+                       if par.Type != nil {
+                               typed++
+                       }
                        list = append(list, par)
                }
                return false
@@ -1939,10 +1943,11 @@ func (p *parser) paramList(name *Name, close token, requireNames bool) (list []*
                }
        } else if named != len(list) {
                // some named => all must have names and types
-               var pos Pos // left-most error position (or unknown)
-               var typ Expr
+               var pos Pos  // left-most error position (or unknown)
+               var typ Expr // current type (from right to left)
                for i := len(list) - 1; i >= 0; i-- {
-                       if par := list[i]; par.Type != nil {
+                       par := list[i]
+                       if par.Type != nil {
                                typ = par.Type
                                if par.Name == nil {
                                        pos = typ.Pos()
@@ -1961,7 +1966,12 @@ func (p *parser) paramList(name *Name, close token, requireNames bool) (list []*
                if pos.IsKnown() {
                        var msg string
                        if requireNames {
-                               msg = "type parameters must be named"
+                               if named == typed {
+                                       pos = end // position error at closing ]
+                                       msg = "missing type constraint"
+                               } else {
+                                       msg = "type parameters must be named"
+                               }
                        } else {
                                msg = "mixed named and unnamed parameters"
                        }
diff --git a/src/cmd/compile/internal/syntax/testdata/issue43527.go2 b/src/cmd/compile/internal/syntax/testdata/issue43527.go2
new file mode 100644 (file)
index 0000000..dd2c9b1
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2021 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
+
+type (
+        // 0 and 1-element []-lists are syntactically valid
+        _[A, B /* ERROR missing type constraint */ ] int
+        _[A, /* ERROR type parameters must be named */ interface{}] int
+        _[A, B, C /* ERROR missing type constraint */ ] int
+        _[A B, C /* ERROR missing type constraint */ ] int
+        _[A B, /* ERROR type parameters must be named */ interface{}] int
+        _[A B, /* ERROR type parameters must be named */ interface{}, C D] int
+        _[A B, /* ERROR type parameters must be named */ interface{}, C, D] int
+        _[A B, /* ERROR type parameters must be named */ interface{}, C, interface{}] int
+        _[A B, C interface{}, D, /* ERROR type parameters must be named */ interface{}] int
+)
+
+// function type parameters use the same parsing routine - just have a couple of tests
+
+func _[A, B /* ERROR missing type constraint */ ]() {}
+func _[A, /* ERROR type parameters must be named */ interface{}]() {}
index 42031c32774f9419625b21b3ea14d005a2cf5449..8e47ff5ed84d9ce44c25d91737962ea63407a18f 100644 (file)
@@ -4,8 +4,8 @@
 
 package p
 
-type t[ /* ERROR type parameters must be named */ a, b] struct{}
-type t[a t, b t, /* ERROR type parameters must be named */ c] struct{}
+type t[a, b /* ERROR missing type constraint */ ] struct{}
+type t[a t, b t, c /* ERROR missing type constraint */ ] struct{}
 type t struct {
        t [n]byte
        t[a]
@@ -18,5 +18,5 @@ type t interface {
 }
 
 func f[ /* ERROR empty type parameter list */ ]()
-func f[ /* ERROR type parameters must be named */ a, b]()
-func f[a t, b t, /* ERROR type parameters must be named */ c]()
+func f[a, b /* ERROR missing type constraint */ ]()
+func f[a t, b t, c /* ERROR missing type constraint */ ]()
index 56e90942ab6bfac0cc22aa0787e0cb1c56ff9585..2c4b6610fecb69b9f3be3de784631648fa34caf6 100644 (file)
@@ -5,4 +5,4 @@
 package p
 
 // don't crash
-func T /* ERROR missing */ [P /* ERROR named */ ] m /* ERROR m */ () /* ERROR \) */ { /* ERROR { */ } /* ERROR } */
+func T /* ERROR missing */ [P] /* ERROR missing */ m /* ERROR unexpected */ () /* ERROR \) */ { /* ERROR { */ } /* ERROR } */