]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] go/parser: accept embedded type literals
authorRob Findley <rfindley@google.com>
Mon, 7 Jun 2021 23:50:15 +0000 (19:50 -0400)
committerRobert Findley <rfindley@google.com>
Thu, 17 Jun 2021 02:06:15 +0000 (02:06 +0000)
This is an approximate port of CL 321109 to go/parser, though go/parser
does not have the same internal APIs as cmd/compile/internal/syntax, so
this CL required some refactoring.

Change-Id: I146ef530c969d61bab99f98f4de94b862e103ddc
Reviewed-on: https://go-review.googlesource.com/c/go/+/325703
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/go/parser/parser.go
src/go/parser/short_test.go
src/go/parser/testdata/interface.go2

index 5ccba02e5caec946e43ee69681c941b158a13346..869d14c2c13655a253a4fa8b534efc09fc34589b 100644 (file)
@@ -1071,10 +1071,13 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType {
 
        pos := p.expect(token.INTERFACE)
        lbrace := p.expect(token.LBRACE)
+
        var list []*ast.Field
-       for p.tok == token.IDENT || p.parseTypeParams() && (p.tok == token.TYPE || p.tok == token.TILDE) {
-               switch p.tok {
-               case token.IDENT:
+
+parseElements:
+       for {
+               switch {
+               case p.tok == token.IDENT:
                        f := p.parseMethodSpec()
                        if f.Names == nil && p.parseTypeParams() {
                                f = p.embeddedElem(f)
@@ -1082,12 +1085,12 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType {
                        p.expectSemi()
                        f.Comment = p.lineComment
                        list = append(list, f)
-               case token.TILDE:
+               case p.tok == token.TILDE && p.parseTypeParams():
                        f := p.embeddedElem(nil)
                        p.expectSemi()
                        f.Comment = p.lineComment
                        list = append(list, f)
-               case token.TYPE:
+               case p.tok == token.TYPE && p.parseTypeParams():
                        // TODO(rfindley): remove TypeList syntax and refactor the clauses above.
 
                        // all types in a type list share the same field name "type"
@@ -1099,8 +1102,22 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType {
                                list = append(list, &ast.Field{Names: name, Type: typ})
                        }
                        p.expectSemi()
+               case p.parseTypeParams():
+                       if t := p.tryIdentOrType(); t != nil {
+                               f := new(ast.Field)
+                               f.Type = t
+                               f = p.embeddedElem(f)
+                               p.expectSemi()
+                               f.Comment = p.lineComment
+                               list = append(list, f)
+                       } else {
+                               break parseElements
+                       }
+               default:
+                       break parseElements
                }
        }
+
        // TODO(rfindley): the error produced here could be improved, since we could
        // accept a identifier, 'type', or a '}' at this point.
        rbrace := p.expect(token.RBRACE)
index 67fef15665583db4e4a1ba7aad93a081b8c9bfc9..2467ccb4a7756f5496c024c80bc77388b7c47a80 100644 (file)
@@ -200,10 +200,12 @@ var invalids = []string{
        `package p; func (type /* ERROR "found 'type'" */ T)(T) _()`,
        `package p; type _[A+B, /* ERROR "expected ']'" */ ] int`,
 
-       // TODO: this error should be positioned on the ':'
+       // TODO(rfindley): this error should be positioned on the ':'
        `package p; var a = a[[]int:[ /* ERROR "expected expression" */ ]int];`,
-       // TODO: the compiler error is better here: "cannot parenthesize embedded type"
-       `package p; type I1 interface{}; type I2 interface{ (/* ERROR "expected '}', found '\('" */ I1) }`,
+
+       // TODO(rfindley): the compiler error is better here: "cannot parenthesize embedded type"
+       // TODO(rfindley): confirm that parenthesized types should now be accepted.
+       // `package p; type I1 interface{}; type I2 interface{ (/* ERROR "expected '}', found '\('" */ I1) }`,
 
        // issue 8656
        `package p; func f() (a b string /* ERROR "missing ','" */ , ok bool)`,
index c631055202b77b83846d3ced9ae859d9576134aa..b399d7514889f39c5e8889088dd2c4ada0d2c857 100644 (file)
@@ -25,7 +25,6 @@ type _ interface {
        ~int | ~string
 }
 
-
 type _ interface {
        m()
        ~int
@@ -35,3 +34,47 @@ type _ interface {
        type bool, int, float64
 }
 
+type _ interface {
+       int
+       []byte
+       [10]int
+       struct{}
+       *int
+       func()
+       interface{}
+       map[string]int
+       chan T
+       chan<- T
+       <-chan T
+       T[int]
+}
+
+type _ interface {
+       int | string
+       []byte | string
+       [10]int | string
+       struct{} | string
+       *int | string
+       func() | string
+       interface{} | string
+       map[string]int | string
+       chan T | string
+       chan<- T | string
+       <-chan T | string
+       T[int] | string
+}
+
+type _ interface {
+       ~int | string
+       ~[]byte | string
+       ~[10]int | string
+       ~struct{} | string
+       ~*int | string
+       ~func() | string
+       ~interface{} | string
+       ~map[string]int | string
+       ~chan T | string
+       ~chan<- T | string
+       ~<-chan T | string
+       ~T[int] | string
+}