mirror of
https://github.com/golang/go
synced 2024-09-05 07:54:46 +00: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)
|
||||
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)
|
||||
|
|
|
@ -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)`,
|
||||
|
|
45
src/go/parser/testdata/interface.go2
vendored
45
src/go/parser/testdata/interface.go2
vendored
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue