go/parser: remove vestiges for [type T] style type parameters

We're not going back to that notation.

Change-Id: Ic3d9b2c931525df60c00ed0ba0e43c20be5f7b43
This commit is contained in:
Robert Griesemer 2019-12-21 20:42:55 -08:00
parent 9090a73d10
commit 3d4810b5ba
3 changed files with 24 additions and 161 deletions

View File

@ -26,11 +26,6 @@ import (
"unicode"
)
// Enable parsing of type parameters in [] rather than () parentheses.
// This code was an experiment which we eventually decided against due
// to various unpleasant ambiguities. Leave around for now, just in case.
const useBrackets = false
// The parser structure holds the parser's internal state.
type parser struct {
file *token.File
@ -722,45 +717,6 @@ func (p *parser) parseOptionalTag() (tag *ast.BasicLit) {
return
}
func (p *parser) parseArrayFieldOrTypeInstance(x *ast.Ident) (*ast.Ident, ast.Expr) {
if p.trace {
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)
var args []ast.Expr
if p.tok != token.RBRACK {
p.exprLev++
args = append(args, p.parseRhsOrType())
for p.tok == token.COMMA {
p.next()
args = append(args, p.parseRhsOrType())
}
p.exprLev--
}
rbrack := p.expect(token.RBRACK)
if len(args) == 0 {
// x []E
elt := p.parseType(true)
return x, &ast.ArrayType{Lbrack: lbrack, Elt: elt}
}
// x [P]E or x[P]
if len(args) == 1 {
elt := p.tryType(true)
if elt != nil {
// x [P]E
return x, &ast.ArrayType{Lbrack: lbrack, Len: args[0], Elt: elt}
}
}
// x[P], x[P1, P2], ...
return nil, &ast.CallExpr{Fun: x, Lparen: lbrack, Args: args, Rparen: rbrack}
}
func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
if p.trace {
defer un(trace(p, "FieldDecl"))
@ -782,8 +738,8 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
var typ ast.Expr = name
if p.tok == token.PERIOD {
typ = p.parseTypeName(name)
// A [ or ( indicates a type parameter (or a syntax error).
if useBrackets && p.tok == token.LBRACK || p.tok == token.LPAREN {
// A "(" indicates a type parameter (or a syntax error).
if p.tok == token.LPAREN {
typ = p.parseTypeInstance(typ)
}
} else {
@ -793,25 +749,12 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
p.expectSemi()
return makeField(typ, tag)
}
names := []*ast.Ident{name}
for p.tok == token.COMMA {
p.next()
names = append(names, p.parseIdent())
}
// Careful dance: We don't know if we have an embedded instantiated
// type T[P1, P2, ...] or a field T of array type []E or [P]E.
var typ ast.Expr
if len(names) == 1 && useBrackets && p.tok == token.LBRACK {
name, typ = p.parseArrayFieldOrTypeInstance(name)
if name == nil {
names = nil
}
} else {
// T P
typ = p.parseType(true)
}
typ := p.parseType(true)
tag := p.parseOptionalTag()
p.expectSemi()
return makeField(typ, tag, names...)
@ -951,12 +894,7 @@ func (p *parser) parseParamDeclOrNil() (f field) {
f.typ = p.parseType(true)
case token.LBRACK:
if useBrackets {
// name[type1, type2, ...] or name []type or name [len]type
f.name, f.typ = p.parseArrayFieldOrTypeInstance(f.name)
} else {
f.typ = p.parseType(true)
}
f.typ = p.parseType(true)
case token.ELLIPSIS:
// name ...type
@ -1089,15 +1027,7 @@ func (p *parser) parseTypeParams(scope *ast.Scope) *ast.FieldList {
defer un(trace(p, "TypeParams"))
}
// If we see a [, assume [type T1, T2, ... C] syntax.
// Otherwise, only assume T1, T2, ... C.
var lbrack, rbrack token.Pos
if useBrackets && p.tok == token.LBRACK {
lbrack = p.pos
p.next()
p.expect(token.TYPE)
}
p.expect(token.TYPE)
fields := p.parseParameterList(scope, false)
// determine which form we have (list of type parameters with optional
// contract, or type parameters, all with interfaces as type bounds)
@ -1109,11 +1039,7 @@ func (p *parser) parseTypeParams(scope *ast.Scope) *ast.FieldList {
}
}
if lbrack.IsValid() {
rbrack = p.expect(token.RBRACK)
}
return &ast.FieldList{Opening: lbrack, List: fields, Closing: rbrack}
return &ast.FieldList{List: fields}
}
func (p *parser) parseParameters(scope *ast.Scope, typeParamsOk, ellipsisOk bool, context string) (tparams, params *ast.FieldList) {
@ -1124,25 +1050,17 @@ func (p *parser) parseParameters(scope *ast.Scope, typeParamsOk, ellipsisOk bool
// We always accept type parameters for robustness
// and complain later if they are not permitted.
var lparen token.Pos
if useBrackets && p.tok == token.LBRACK {
// assume [type T](params) syntax
// assume (type T)(params) syntax
lparen := p.expect(token.LPAREN)
if p.tok == token.TYPE {
tparams = p.parseTypeParams(scope)
lparen = p.expect(token.LPAREN)
} else {
// assume (type T)(params) syntax
lparen = p.expect(token.LPAREN)
if p.tok == token.TYPE {
p.next()
tparams = p.parseTypeParams(scope)
rparen := p.expect(token.RPAREN)
rparen := p.expect(token.RPAREN)
// fix parentheses positions
tparams.Opening = lparen
tparams.Closing = rparen
// fix parentheses positions
tparams.Opening = lparen
tparams.Closing = rparen
lparen = p.expect(token.LPAREN)
}
lparen = p.expect(token.LPAREN)
}
if tparams != nil && !typeParamsOk {
@ -1308,7 +1226,7 @@ func (p *parser) parseConstraint() *ast.Constraint {
}
tname := p.parseTypeName(nil)
if useBrackets && p.tok == token.LBRACK || p.tok == token.LPAREN {
if p.tok == token.LPAREN {
// ContractTypeName "(" [ TypeList [ "," ] ] ")"
return &ast.Constraint{Types: []ast.Expr{p.parseTypeInstance(tname)}}
}
@ -1351,29 +1269,20 @@ func (p *parser) parseTypeInstance(typ ast.Expr) *ast.CallExpr {
defer un(trace(p, "TypeInstantiation"))
}
opening := p.pos
close := token.RBRACK
if useBrackets && p.tok == token.LBRACK {
p.next()
} else {
p.expect(token.LPAREN)
close = token.RPAREN
}
lparen := p.expect(token.LPAREN)
p.exprLev++
var list []ast.Expr
for p.tok != token.RPAREN && p.tok != token.EOF {
list = append(list, p.parseType(true))
if !p.atComma("type argument list", close) {
if !p.atComma("type argument list", token.RPAREN) {
break
}
p.next()
}
p.exprLev--
rparen := p.expectClosing(token.RPAREN, "type argument list")
closing := p.expectClosing(close, "type argument list")
return &ast.CallExpr{Fun: typ, Lparen: opening, Args: list, Rparen: closing}
return &ast.CallExpr{Fun: typ, Lparen: lparen, Args: list, Rparen: rparen}
}
// If the result is an identifier, it is not resolved.
@ -1386,7 +1295,7 @@ func (p *parser) tryIdentOrType(typeContext bool) ast.Expr {
switch p.tok {
case token.IDENT:
typ := p.parseTypeName(nil)
if typeContext && (useBrackets && p.tok == token.LBRACK || p.tok == token.LPAREN) {
if typeContext && p.tok == token.LPAREN {
typ = p.parseTypeInstance(typ)
}
return typ
@ -2741,38 +2650,11 @@ func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token
spec := &ast.TypeSpec{Doc: doc, Name: ident}
p.declare(spec, nil, p.topScope, ast.Typ, ident)
if useBrackets && p.tok == token.LBRACK {
lbrack := p.pos
p.next()
if p.tok == token.TYPE {
// parameterized type
p.next()
p.openScope()
tparams := p.parseTypeParams(p.topScope)
tparams.Opening = lbrack
tparams.Closing = p.expect(token.RBRACK)
spec.TParams = tparams
if p.tok == token.ASSIGN {
// type alias
spec.Assign = p.pos
p.next()
}
spec.Type = p.parseType(true)
p.closeScope()
} else {
// array type
alen := p.parseArrayLen()
p.expect(token.RBRACK)
elt := p.parseType(true)
spec.Type = &ast.ArrayType{Lbrack: lbrack, Len: alen, Elt: elt}
}
} else if p.tok == token.LPAREN {
if p.tok == token.LPAREN {
lparen := p.pos
p.next()
if p.tok == token.TYPE {
// parameterized type
p.next()
p.openScope()
tparams := p.parseTypeParams(p.topScope)
tparams.Opening = lparen

View File

@ -53,9 +53,6 @@ var valids = []string{
`package p; type T(type P comparable) struct { P }`,
`package p; type T(type P comparable(P)) struct { P }`,
`package p; type T(type P1, P2) struct { P1; f []P2 }`,
// `package p; type T[type] struct { P }`,
// `package p; type T[type P] struct { P }`,
// `package p; type T[type P1, P2] struct { P1; f []P2 }`,
`package p; var _ = [](T(int)){}`,
`package p; var _ = func()T(nil)`,
`package p; func _(type)()`,
@ -69,16 +66,6 @@ var valids = []string{
`package p; func _(type A, B)(a A) B`,
`package p; func _(type A, B C)(a A) B`,
`package p; func _(type A, B C(A, B))(a A) B`,
// `package p; type _ struct { T[P] }`,
// `package p; type _ struct { T []E }`,
// `package p; type _ struct { T [P]E }`,
// `package p; type _ struct { imported.T[P] }`,
// `package p; type _ struct { imported.T[P1, P2] }`,
// `package p; func _[type]()`,
// `package p; func _[type]()()`,
// `package p; func _[type A, B](a A) B`,
// `package p; func _[type A, B C](a A) B`,
// `package p; func _[type A, B C(A, B)](a A) B`,
`package p; contract C(){}`,
`package p; contract C(T, S, R,){}`,
`package p; contract C(T){ T (m(x, int)); }`,

View File

@ -4,12 +4,6 @@
package p
func f1 (type T interface{ type T }) ()
func f2 (type T, T2 interface{ type T, int }) ()
func _() {
f1(int)()
f1(string)()
f2(int, int)()
f2(int, string /* ERROR string does not satisfy */ )()
}
type B(type T) interface {
m() B(T)
}