]> Cypherpunks repositories - gostls13.git/commitdiff
go/parser: allow trailing commas in embedded instantiated types
authorcia-rana <kiwamura0314@gmail.com>
Mon, 14 Nov 2022 08:01:03 +0000 (17:01 +0900)
committerRobert Griesemer <gri@google.com>
Thu, 17 Nov 2022 17:02:15 +0000 (17:02 +0000)
go/parser can correctly parse interfaces that instantiate and embed
generic interfaces, but not structs. This is because in the case of
structs, it does not expect RBRACK as a token trailing COMMA in the type
argument, even though it is allowed by the spec.

For example, go/parser produces an error for the type declaration below:

type A struct {
    B[byte, []byte,]
}

Fixes #56748

Change-Id: Ibb2addd6cf9b381d8470a6d20eedb93f13f93cd6
Reviewed-on: https://go-review.googlesource.com/c/go/+/450175
Run-TryBot: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
src/go/parser/parser.go
src/go/parser/testdata/tparams.go2

index 4dcfaca29928f653ea11c47e68997052f6a43c98..fac24dfa05cc8a55b944fb3f1399f91cdf44baa7 100644 (file)
@@ -587,15 +587,19 @@ func (p *parser) parseArrayFieldOrTypeInstance(x *ast.Ident) (*ast.Ident, ast.Ex
                defer un(trace(p, "ArrayFieldOrTypeInstance"))
        }
 
-       // TODO(gri) Should we allow a trailing comma in a type argument
-       //           list such as T[P,]? (We do in parseTypeInstance).
        lbrack := p.expect(token.LBRACK)
+       trailingComma := token.NoPos // if valid, the position of a trailing comma preceding the ']'
        var args []ast.Expr
        if p.tok != token.RBRACK {
                p.exprLev++
                args = append(args, p.parseRhs())
                for p.tok == token.COMMA {
+                       comma := p.pos
                        p.next()
+                       if p.tok == token.RBRACK {
+                               trailingComma = comma
+                               break
+                       }
                        args = append(args, p.parseRhs())
                }
                p.exprLev--
@@ -613,6 +617,10 @@ func (p *parser) parseArrayFieldOrTypeInstance(x *ast.Ident) (*ast.Ident, ast.Ex
                elt := p.tryIdentOrType()
                if elt != nil {
                        // x [P]E
+                       if trailingComma.IsValid() {
+                               // Trailing commas are invalid in array type fields.
+                               p.error(trailingComma, "unexpected comma; expecting ]")
+                       }
                        return x, &ast.ArrayType{Lbrack: lbrack, Len: args[0], Elt: elt}
                }
        }
index abde5dc05045b67f61209d23044c161e95f145df..1a9a6c635de53542e29c348b427cbc18944da34c 100644 (file)
@@ -9,12 +9,19 @@ type _[a t, b t, c /* ERROR "type parameters must be named" */ ] struct{}
 type _ struct {
        t [n]byte
        t[a]
+       t[a,]
        t[a, b]
+       t[a, b,]
+}
+type _ struct {
+       t [n, /* ERROR "unexpected comma; expecting ]" */ ]byte
 }
 type _ interface {
        t[a]
+       t[a,]
        m[ /* ERROR "method must have no type parameters" */ _ _, /* ERROR mixed */ _]()
        t[a, b]
+       t[a, b,]
 }
 
 func _[] /* ERROR "empty type parameter list" */ ()