]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/syntax: fix constraint literal parsing for generic functions
authorRobert Griesemer <gri@golang.org>
Wed, 27 Oct 2021 04:12:31 +0000 (21:12 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 27 Oct 2021 18:08:49 +0000 (18:08 +0000)
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>
src/cmd/compile/internal/syntax/parser.go
src/cmd/compile/internal/syntax/testdata/typeset.go2

index e78e77561df6a14dd806a8e59e485c2c71d54f6f..af5a505cdbe642d4b8842aae81a07b1f9458a441 100644 (file)
@@ -588,19 +588,24 @@ func (p *parser) typeDecl(group *Group) Decl {
        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 @@ func (p *parser) typeDecl(group *Group) Decl {
                                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 @@ func (p *parser) embeddedTerm() Expr {
 // 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 @@ func (p *parser) paramDeclOrNil(name *Name, follow token) *Field {
                                // name "[" n "]" E
                                f.Name = name
                        }
+                       if typeSetsOk && p.tok == _Operator && p.op == Or {
+                               // name "[" ... "]" "|" ...
+                               // name "[" n "]" E "|" ...
+                               f = p.embeddedElem(f)
+                       }
                        return f
                }
 
index a173bb1d4ff07b0643e613aaf83b5f9da5b59a5a..78d3fe1ae59a6d3b0f17b45c24a6846d5a1c5fcc 100644 (file)
@@ -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 @@ type (
         _[_ ~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