mirror of
https://github.com/golang/go
synced 2024-11-12 02:10:21 -07:00
[dev.typeparams] go/parser: accept embedded type literals
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>
This commit is contained in:
parent
ab4b3c4b15
commit
54f854fb41
@ -1071,10 +1071,13 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType {
|
|||||||
|
|
||||||
pos := p.expect(token.INTERFACE)
|
pos := p.expect(token.INTERFACE)
|
||||||
lbrace := p.expect(token.LBRACE)
|
lbrace := p.expect(token.LBRACE)
|
||||||
|
|
||||||
var list []*ast.Field
|
var list []*ast.Field
|
||||||
for p.tok == token.IDENT || p.parseTypeParams() && (p.tok == token.TYPE || p.tok == token.TILDE) {
|
|
||||||
switch p.tok {
|
parseElements:
|
||||||
case token.IDENT:
|
for {
|
||||||
|
switch {
|
||||||
|
case p.tok == token.IDENT:
|
||||||
f := p.parseMethodSpec()
|
f := p.parseMethodSpec()
|
||||||
if f.Names == nil && p.parseTypeParams() {
|
if f.Names == nil && p.parseTypeParams() {
|
||||||
f = p.embeddedElem(f)
|
f = p.embeddedElem(f)
|
||||||
@ -1082,12 +1085,12 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType {
|
|||||||
p.expectSemi()
|
p.expectSemi()
|
||||||
f.Comment = p.lineComment
|
f.Comment = p.lineComment
|
||||||
list = append(list, f)
|
list = append(list, f)
|
||||||
case token.TILDE:
|
case p.tok == token.TILDE && p.parseTypeParams():
|
||||||
f := p.embeddedElem(nil)
|
f := p.embeddedElem(nil)
|
||||||
p.expectSemi()
|
p.expectSemi()
|
||||||
f.Comment = p.lineComment
|
f.Comment = p.lineComment
|
||||||
list = append(list, f)
|
list = append(list, f)
|
||||||
case token.TYPE:
|
case p.tok == token.TYPE && p.parseTypeParams():
|
||||||
// TODO(rfindley): remove TypeList syntax and refactor the clauses above.
|
// TODO(rfindley): remove TypeList syntax and refactor the clauses above.
|
||||||
|
|
||||||
// all types in a type list share the same field name "type"
|
// 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})
|
list = append(list, &ast.Field{Names: name, Type: typ})
|
||||||
}
|
}
|
||||||
p.expectSemi()
|
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
|
// TODO(rfindley): the error produced here could be improved, since we could
|
||||||
// accept a identifier, 'type', or a '}' at this point.
|
// accept a identifier, 'type', or a '}' at this point.
|
||||||
rbrace := p.expect(token.RBRACE)
|
rbrace := p.expect(token.RBRACE)
|
||||||
|
@ -200,10 +200,12 @@ var invalids = []string{
|
|||||||
`package p; func (type /* ERROR "found 'type'" */ T)(T) _()`,
|
`package p; func (type /* ERROR "found 'type'" */ T)(T) _()`,
|
||||||
`package p; type _[A+B, /* ERROR "expected ']'" */ ] int`,
|
`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];`,
|
`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
|
// issue 8656
|
||||||
`package p; func f() (a b string /* ERROR "missing ','" */ , ok bool)`,
|
`package p; func f() (a b string /* ERROR "missing ','" */ , ok bool)`,
|
||||||
|
45
src/go/parser/testdata/interface.go2
vendored
45
src/go/parser/testdata/interface.go2
vendored
@ -25,7 +25,6 @@ type _ interface {
|
|||||||
~int | ~string
|
~int | ~string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type _ interface {
|
type _ interface {
|
||||||
m()
|
m()
|
||||||
~int
|
~int
|
||||||
@ -35,3 +34,47 @@ type _ interface {
|
|||||||
type bool, int, float64
|
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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user