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