From bb49eb3e6a464fbbebd425c4b84c32609b27ecf2 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 26 Oct 2021 21:12:31 -0700 Subject: [PATCH] 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 Reviewed-by: Robert Findley --- src/cmd/compile/internal/syntax/parser.go | 14 +++++++++++++- .../compile/internal/syntax/testdata/typeset.go2 | 13 ++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index e78e77561d..af5a505cdb 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -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 } diff --git a/src/cmd/compile/internal/syntax/testdata/typeset.go2 b/src/cmd/compile/internal/syntax/testdata/typeset.go2 index a173bb1d4f..78d3fe1ae5 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 @@ 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 -- 2.48.1