mirror of
https://github.com/golang/go
synced 2024-11-22 03:54:39 -07:00
go/parser: accept corner cases of signature syntax
- func f(int,) is a legal signature - func f(...int,) is a legal signature Defer checking for correct use of "..." with last paremeter type to type checker instead of parser. R=rsc CC=golang-dev https://golang.org/cl/4973059
This commit is contained in:
parent
c10679009a
commit
0783dd9027
@ -610,9 +610,6 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
|
|||||||
p.error(pos, "'...' parameter is missing type")
|
p.error(pos, "'...' parameter is missing type")
|
||||||
typ = &ast.BadExpr{pos, p.pos}
|
typ = &ast.BadExpr{pos, p.pos}
|
||||||
}
|
}
|
||||||
if p.tok != token.RPAREN {
|
|
||||||
p.error(pos, "can use '...' with last parameter type only")
|
|
||||||
}
|
|
||||||
return &ast.Ellipsis{pos, typ}
|
return &ast.Ellipsis{pos, typ}
|
||||||
}
|
}
|
||||||
return p.tryIdentOrType(false)
|
return p.tryIdentOrType(false)
|
||||||
@ -635,21 +632,21 @@ func (p *parser) parseVarList(isParam bool) (list []ast.Expr, typ ast.Expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// a list of identifiers looks like a list of type names
|
// a list of identifiers looks like a list of type names
|
||||||
for {
|
//
|
||||||
// parseVarType accepts any type (including parenthesized ones)
|
// parse/tryVarType accepts any type (including parenthesized
|
||||||
// even though the syntax does not permit them here: we
|
// ones) even though the syntax does not permit them here: we
|
||||||
// accept them all for more robust parsing and complain
|
// accept them all for more robust parsing and complain later
|
||||||
// afterwards
|
for typ := p.parseVarType(isParam); typ != nil; {
|
||||||
list = append(list, p.parseVarType(isParam))
|
list = append(list, typ)
|
||||||
if p.tok != token.COMMA {
|
if p.tok != token.COMMA {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
|
typ = p.tryVarType(isParam) // maybe nil as in: func f(int,) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we had a list of identifiers, it must be followed by a type
|
// if we had a list of identifiers, it must be followed by a type
|
||||||
typ = p.tryVarType(isParam)
|
if typ = p.tryVarType(isParam); typ != nil {
|
||||||
if typ != nil {
|
|
||||||
p.resolve(typ)
|
p.resolve(typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,9 @@ var validPrograms = []interface{}{
|
|||||||
`package p; func f(...T);`,
|
`package p; func f(...T);`,
|
||||||
`package p; func f(float, ...int);`,
|
`package p; func f(float, ...int);`,
|
||||||
`package p; func f(x int, a ...int) { f(0, a...); f(1, a...,) };`,
|
`package p; func f(x int, a ...int) { f(0, a...); f(1, a...,) };`,
|
||||||
|
`package p; func f(int,) {};`,
|
||||||
|
`package p; func f(...int,) {};`,
|
||||||
|
`package p; func f(x ...int,) {};`,
|
||||||
`package p; type T []int; var a []bool; func f() { if a[T{42}[0]] {} };`,
|
`package p; type T []int; var a []bool; func f() { if a[T{42}[0]] {} };`,
|
||||||
`package p; type T []int; func g(int) bool { return true }; func f() { if g(T{42}[0]) {} };`,
|
`package p; type T []int; func g(int) bool { return true }; func f() { if g(T{42}[0]) {} };`,
|
||||||
`package p; type T []int; func f() { for _ = range []int{T{42}[0]} {} };`,
|
`package p; type T []int; func f() { for _ = range []int{T{42}[0]} {} };`,
|
||||||
@ -77,7 +80,7 @@ var validPrograms = []interface{}{
|
|||||||
|
|
||||||
func TestParseValidPrograms(t *testing.T) {
|
func TestParseValidPrograms(t *testing.T) {
|
||||||
for _, src := range validPrograms {
|
for _, src := range validPrograms {
|
||||||
_, err := ParseFile(fset, "", src, 0)
|
_, err := ParseFile(fset, "", src, SpuriousErrors)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("ParseFile(%q): %v", src, err)
|
t.Errorf("ParseFile(%q): %v", src, err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user