cmd/compile/internal/syntax: fix constraint literal parsing for generic functions
Fixes #49174.
Change-Id: I943c370f7abd5f50a541e682f130b3526c3b5bdb
Reviewed-on: https://go-review.googlesource.com/c/go/+/359014
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go
index e78e775..af5a505 100644
--- a/src/cmd/compile/internal/syntax/parser.go
+++ b/src/cmd/compile/internal/syntax/parser.go
@@ -588,19 +588,24 @@
d.Name = p.name()
if p.tok == _Lbrack {
// array/slice or generic type
+ // name "[" ...
pos := p.pos()
p.next()
switch p.tok {
case _Rbrack:
+ // name "[" "]" ...
p.next()
d.Type = p.sliceType(pos)
case _Name:
// array or generic type
+ // name "[" name ...
p.xnest++
+ // TODO(gri) p.expr may consume an opening "[" when it shouldn't (issue #49175)
x := p.expr()
p.xnest--
if name0, ok := x.(*Name); p.allowGenerics() && ok && p.tok != _Rbrack {
// generic type
+ // name "[" name ...
d.TParamList = p.paramList(name0, _Rbrack, true)
pos := p.pos()
if p.gotAssign() {
@@ -609,12 +614,14 @@
d.Type = p.typeOrNil()
} else {
// x is the array length expression
+ // name "[" x ...
if debug && x == nil {
panic("length expression is nil")
}
d.Type = p.arrayType(pos, x)
}
default:
+ // name "[" ...
d.Type = p.arrayType(pos, nil)
}
} else {
@@ -1816,7 +1823,7 @@
// ParameterDecl = [ IdentifierList ] [ "..." ] Type .
func (p *parser) paramDeclOrNil(name *Name, follow token) *Field {
if trace {
- defer p.trace("paramDecl")()
+ defer p.trace("paramDeclOrNil")()
}
// type set notation is ok in type parameter lists
@@ -1849,6 +1856,11 @@
// name "[" n "]" E
f.Name = name
}
+ if typeSetsOk && p.tok == _Operator && p.op == Or {
+ // name "[" ... "]" "|" ...
+ // name "[" n "]" E "|" ...
+ f = p.embeddedElem(f)
+ }
return f
}
diff --git a/src/cmd/compile/internal/syntax/testdata/typeset.go2 b/src/cmd/compile/internal/syntax/testdata/typeset.go2
index a173bb1..78d3fe1 100644
--- a/src/cmd/compile/internal/syntax/testdata/typeset.go2
+++ b/src/cmd/compile/internal/syntax/testdata/typeset.go2
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
// This file contains test cases for typeset-only constraint elements.
-// TODO(gri) gofmt once/if gofmt supports this notation.
package p
@@ -44,8 +43,20 @@
_[_ ~t|struct{}] t
_[_ t|~struct{}] t
_[_ ~t|~struct{}] t
+
+ // TODO(gri) fix this (issue #49175)
+ // _[_ []t]t
+ _[_ ~[]t]t
)
+// test cases for issue #49174
+func _[_ t]() {}
+func _[_ []t]() {}
+func _[_ []t | t]() {}
+func _[_ t | []t]() {}
+func _[_ []t | []t]() {}
+func _[_ t[t] | t[t]]() {}
+
// Single-expression type parameter lists and those that don't start
// with a (type parameter) name are considered array sizes.
// The term must be a valid expression (it could be a type - and then