1
0
mirror of https://github.com/golang/go synced 2024-11-18 02:24:45 -07:00

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>
This commit is contained in:
Robert Griesemer 2021-10-26 21:12:31 -07:00
parent c0ac39c70e
commit bb49eb3e6a
2 changed files with 25 additions and 2 deletions

View File

@ -588,19 +588,24 @@ func (p *parser) typeDecl(group *Group) Decl {
d.Name = p.name() d.Name = p.name()
if p.tok == _Lbrack { if p.tok == _Lbrack {
// array/slice or generic type // array/slice or generic type
// name "[" ...
pos := p.pos() pos := p.pos()
p.next() p.next()
switch p.tok { switch p.tok {
case _Rbrack: case _Rbrack:
// name "[" "]" ...
p.next() p.next()
d.Type = p.sliceType(pos) d.Type = p.sliceType(pos)
case _Name: case _Name:
// array or generic type // array or generic type
// name "[" name ...
p.xnest++ p.xnest++
// TODO(gri) p.expr may consume an opening "[" when it shouldn't (issue #49175)
x := p.expr() x := p.expr()
p.xnest-- p.xnest--
if name0, ok := x.(*Name); p.allowGenerics() && ok && p.tok != _Rbrack { if name0, ok := x.(*Name); p.allowGenerics() && ok && p.tok != _Rbrack {
// generic type // generic type
// name "[" name ...
d.TParamList = p.paramList(name0, _Rbrack, true) d.TParamList = p.paramList(name0, _Rbrack, true)
pos := p.pos() pos := p.pos()
if p.gotAssign() { if p.gotAssign() {
@ -609,12 +614,14 @@ func (p *parser) typeDecl(group *Group) Decl {
d.Type = p.typeOrNil() d.Type = p.typeOrNil()
} else { } else {
// x is the array length expression // x is the array length expression
// name "[" x ...
if debug && x == nil { if debug && x == nil {
panic("length expression is nil") panic("length expression is nil")
} }
d.Type = p.arrayType(pos, x) d.Type = p.arrayType(pos, x)
} }
default: default:
// name "[" ...
d.Type = p.arrayType(pos, nil) d.Type = p.arrayType(pos, nil)
} }
} else { } else {
@ -1816,7 +1823,7 @@ func (p *parser) embeddedTerm() Expr {
// ParameterDecl = [ IdentifierList ] [ "..." ] Type . // ParameterDecl = [ IdentifierList ] [ "..." ] Type .
func (p *parser) paramDeclOrNil(name *Name, follow token) *Field { func (p *parser) paramDeclOrNil(name *Name, follow token) *Field {
if trace { if trace {
defer p.trace("paramDecl")() defer p.trace("paramDeclOrNil")()
} }
// type set notation is ok in type parameter lists // 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 // name "[" n "]" E
f.Name = name f.Name = name
} }
if typeSetsOk && p.tok == _Operator && p.op == Or {
// name "[" ... "]" "|" ...
// name "[" n "]" E "|" ...
f = p.embeddedElem(f)
}
return f return f
} }

View File

@ -3,7 +3,6 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// This file contains test cases for typeset-only constraint elements. // This file contains test cases for typeset-only constraint elements.
// TODO(gri) gofmt once/if gofmt supports this notation.
package p package p
@ -44,8 +43,20 @@ type (
_[_ ~t|struct{}] t _[_ ~t|struct{}] t
_[_ t|~struct{}] t _[_ 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 // Single-expression type parameter lists and those that don't start
// with a (type parameter) name are considered array sizes. // with a (type parameter) name are considered array sizes.
// The term must be a valid expression (it could be a type - and then // The term must be a valid expression (it could be a type - and then