From 86fa2551fb12338405721089d6db1b9d78e4f05e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 18 Apr 2022 17:19:47 -0700 Subject: [PATCH] cmd/compile/internal/types2: permit parentheses around types in interfaces Before Go 1.18, an embedded type name in an interface could not be parenthesized. With generalized embedding of types in interfaces, where one might write ~(chan<- int) for clarity (making clear that the ~ applies to the entire channel type), it also makes sense to permit (chan<- int), or (int) for that matter. Adjust the parser accordingly to match the spec. (go/types already accepts the notation as specified by the spec.) Fixes #52391. Change-Id: Ifdd9a199c5ccc3473b2dac40dbca31d2df10d12b Reviewed-on: https://go-review.googlesource.com/c/go/+/400797 Reviewed-by: Ian Lance Taylor Reviewed-by: Robert Griesemer Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/syntax/parser.go | 44 +++---------------- .../internal/syntax/testdata/issue52391.go | 17 +++++++ 2 files changed, 24 insertions(+), 37 deletions(-) create mode 100644 src/cmd/compile/internal/syntax/testdata/issue52391.go diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index f18d526877..9de6d4f45e 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1499,44 +1499,14 @@ func (p *parser) interfaceType() *InterfaceType { p.want(_Interface) p.want(_Lbrace) p.list("interface type", _Semi, _Rbrace, func() bool { - switch p.tok { - case _Name: - f := p.methodDecl() - if f.Name == nil { - f = p.embeddedElem(f) - } - typ.MethodList = append(typ.MethodList, f) - return false - - case _Lparen: - p.syntaxError("cannot parenthesize embedded type") - f := new(Field) - f.pos = p.pos() - p.next() - f.Type = p.qualifiedName(nil) - p.want(_Rparen) - typ.MethodList = append(typ.MethodList, f) - return false - - case _Operator: - if p.op == Tilde { - typ.MethodList = append(typ.MethodList, p.embeddedElem(nil)) - return false - } - - default: - pos := p.pos() - if t := p.typeOrNil(); t != nil { - f := new(Field) - f.pos = pos - f.Type = t - typ.MethodList = append(typ.MethodList, p.embeddedElem(f)) - return false - } + var f *Field + if p.tok == _Name { + f = p.methodDecl() } - - p.syntaxError("expecting method or embedded element") - p.advance(_Semi, _Rbrace) + if f == nil || f.Name == nil { + f = p.embeddedElem(f) + } + typ.MethodList = append(typ.MethodList, f) return false }) diff --git a/src/cmd/compile/internal/syntax/testdata/issue52391.go b/src/cmd/compile/internal/syntax/testdata/issue52391.go new file mode 100644 index 0000000000..f2098ceadb --- /dev/null +++ b/src/cmd/compile/internal/syntax/testdata/issue52391.go @@ -0,0 +1,17 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type _ interface { + int + (int) + (*int) + *([]byte) + ~(int) + (int) | (string) + (int) | ~(string) + (/* ERROR unexpected ~ */ ~int) + (int /* ERROR unexpected \| */ | /* ERROR unexpected string */ string /* ERROR unexpected \) */ ) +} -- 2.50.0