diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 2a31418e6a..f9ca4d977b 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1119,9 +1119,7 @@ loop: p.syntaxError("cannot parenthesize type in composite literal") // already progressed, no need to advance } - pos := p.pos() - p.next() // consume _Lbrace - n := p.complitexpr(pos) + n := p.complitexpr() n.Type = x x = n @@ -1139,26 +1137,25 @@ func (p *parser) bare_complitexpr() Expr { defer p.trace("bare_complitexpr")() } - pos := p.pos() - if p.got(_Lbrace) { + if p.tok == _Lbrace { // '{' start_complit braced_keyval_list '}' - return p.complitexpr(pos) + return p.complitexpr() } return p.expr() } // LiteralValue = "{" [ ElementList [ "," ] ] "}" . -// "{" has already been consumed, and pos is its position. -func (p *parser) complitexpr(pos Pos) *CompositeLit { +func (p *parser) complitexpr() *CompositeLit { if trace { defer p.trace("complitexpr")() } x := new(CompositeLit) - x.pos = pos + x.pos = p.pos() p.xnest++ + p.want(_Lbrace) x.Rbrace = p.list(_Comma, _Rbrace, func() bool { // value e := p.bare_complitexpr() @@ -1403,6 +1400,7 @@ func (p *parser) interfaceType() *InterfaceType { switch p.tok { case _Name: typ.MethodList = append(typ.MethodList, p.methodDecl()) + case _Type: // TODO(gri) factor this better type_ := new(Name) @@ -1424,6 +1422,15 @@ func (p *parser) interfaceType() *InterfaceType { } } + 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) + default: p.syntaxError("expecting method, interface name, or type list") p.advance(_Semi, _Rbrace) @@ -1520,12 +1527,36 @@ func (p *parser) fieldDecl(styp *StructType) { p.addField(styp, name.Pos(), name, typ, tag) } - case _Lparen, _Star: - // embedded, possibly generic type - // (using the enclosing parentheses to distinguish it from a named field declaration) - // TODO(gri) This may be too liberal. Maybe only permit ()'s if necessary. - // See also fixedbugs/bug299.go. - typ := p.type_() + case _Star: + p.next() + var typ Expr + if p.tok == _Lparen { + // *(T) + p.syntaxError("cannot parenthesize embedded type") + p.next() + typ = p.qualifiedName(nil) + p.want(_Rparen) + } else { + // *T + typ = p.qualifiedName(nil) + } + tag := p.oliteral() + p.addField(styp, pos, nil, newIndirect(pos, typ), tag) + + case _Lparen: + p.syntaxError("cannot parenthesize embedded type") + p.next() + var typ Expr + if p.tok == _Star { + // (*T) + pos := p.pos() + p.next() + typ = newIndirect(pos, p.qualifiedName(nil)) + } else { + // (T) + typ = p.qualifiedName(nil) + } + p.want(_Rparen) tag := p.oliteral() p.addField(styp, pos, nil, typ, tag) @@ -1737,7 +1768,7 @@ func (p *parser) paramList(name *Name, close token) (list []*Field) { name = nil // 1st name was consumed if present if par != nil { if debug && par.Name == nil && par.Type == nil { - panic("(type) parameter without name or type") + panic("parameter without name or type") } if par.Name != nil && par.Type != nil { named++ diff --git a/src/cmd/compile/internal/types2/stdlib_test.go b/src/cmd/compile/internal/types2/stdlib_test.go index d4dc61a339..ef4d3d7847 100644 --- a/src/cmd/compile/internal/types2/stdlib_test.go +++ b/src/cmd/compile/internal/types2/stdlib_test.go @@ -178,7 +178,6 @@ func TestStdFixed(t *testing.T) { "issue31747.go", // go/types does not have constraints on language level (-lang=go1.12) (see #31793) "issue34329.go", // go/types does not have constraints on language level (-lang=go1.13) (see #31793) "bug251.go", // issue #34333 which was exposed with fix for #34151 - "bug299.go", // go/types permits parenthesized embedded fields "issue14652.go", // any is currently permitted // TODO(gri) fix this ) } diff --git a/test/fixedbugs/bug299.go b/test/fixedbugs/bug299.go index 1ffd448b6d..cf11bcc1e0 100644 --- a/test/fixedbugs/bug299.go +++ b/test/fixedbugs/bug299.go @@ -1,4 +1,4 @@ -// compile +// errorcheck // Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -12,16 +12,10 @@ type T struct { y (int) int *float64 - /* // not legal according to spec (complex128) // ERROR "non-declaration|expected|parenthesize" (*string) // ERROR "non-declaration|expected|parenthesize" *(bool) // ERROR "non-declaration|expected|parenthesize" - */ - // generic Go permits (and in some cases requires) parentheses for embedded types - (complex128) - (*string) - *(bool) } // legal according to spec