mirror of https://github.com/golang/go.git
go/parser: complain if type parameters are not permitted
Always accept them but complain if they are not permitted. The analogous parser check was lost in a recent change. Also: Fix index computation in collectTypeParams. Change-Id: I7cb89944984df6dadd7f603b56f0c3941d60f7c5
This commit is contained in:
parent
c47bad9a28
commit
46442bd4a9
|
|
@ -1116,11 +1116,14 @@ func (p *parser) parseTypeParams(scope *ast.Scope) *ast.FieldList {
|
||||||
return &ast.FieldList{Opening: lbrack, List: fields, Closing: rbrack}
|
return &ast.FieldList{Opening: lbrack, List: fields, Closing: rbrack}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) parseParameters(scope *ast.Scope, typeParamsOk, ellipsisOk bool) (tparams, params *ast.FieldList) {
|
func (p *parser) parseParameters(scope *ast.Scope, typeParamsOk, ellipsisOk bool, context string) (tparams, params *ast.FieldList) {
|
||||||
if p.trace {
|
if p.trace {
|
||||||
defer un(trace(p, "Parameters"))
|
defer un(trace(p, "Parameters"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We always accept type parameters for robustness
|
||||||
|
// and complain later if they are not permitted.
|
||||||
|
|
||||||
var lparen token.Pos
|
var lparen token.Pos
|
||||||
if useBrackets && p.tok == token.LBRACK {
|
if useBrackets && p.tok == token.LBRACK {
|
||||||
// assume [type T](params) syntax
|
// assume [type T](params) syntax
|
||||||
|
|
@ -1142,6 +1145,11 @@ func (p *parser) parseParameters(scope *ast.Scope, typeParamsOk, ellipsisOk bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tparams != nil && !typeParamsOk {
|
||||||
|
p.error(tparams.Opening, context+" must have no type parameters")
|
||||||
|
tparams = nil
|
||||||
|
}
|
||||||
|
|
||||||
var fields []*ast.Field
|
var fields []*ast.Field
|
||||||
if p.tok != token.RPAREN {
|
if p.tok != token.RPAREN {
|
||||||
fields = p.parseParameterList(scope, ellipsisOk)
|
fields = p.parseParameterList(scope, ellipsisOk)
|
||||||
|
|
@ -1159,7 +1167,7 @@ func (p *parser) parseResult(scope *ast.Scope, typeContext bool) *ast.FieldList
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.tok == token.LPAREN {
|
if p.tok == token.LPAREN {
|
||||||
_, results := p.parseParameters(scope, false, false)
|
_, results := p.parseParameters(scope, false, false, "result")
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1180,7 +1188,7 @@ func (p *parser) parseFuncType(typeContext bool) (*ast.FuncType, *ast.Scope) {
|
||||||
|
|
||||||
pos := p.expect(token.FUNC)
|
pos := p.expect(token.FUNC)
|
||||||
scope := ast.NewScope(p.topScope) // function scope
|
scope := ast.NewScope(p.topScope) // function scope
|
||||||
_, params := p.parseParameters(scope, false, true)
|
_, params := p.parseParameters(scope, false, true, "function type")
|
||||||
results := p.parseResult(scope, typeContext)
|
results := p.parseResult(scope, typeContext)
|
||||||
|
|
||||||
return &ast.FuncType{Func: pos, Params: params, Results: results}, scope
|
return &ast.FuncType{Func: pos, Params: params, Results: results}, scope
|
||||||
|
|
@ -1199,7 +1207,7 @@ func (p *parser) parseMethodSpec(scope *ast.Scope) *ast.Field {
|
||||||
// method
|
// method
|
||||||
idents = []*ast.Ident{ident}
|
idents = []*ast.Ident{ident}
|
||||||
scope := ast.NewScope(nil) // method scope
|
scope := ast.NewScope(nil) // method scope
|
||||||
_, params := p.parseParameters(scope, false, true)
|
_, params := p.parseParameters(scope, false, true, "method")
|
||||||
results := p.parseResult(scope, true)
|
results := p.parseResult(scope, true)
|
||||||
typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results}
|
typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1340,7 +1348,7 @@ func (p *parser) parseConstraint() *ast.Constraint {
|
||||||
// method
|
// method
|
||||||
mname = ident
|
mname = ident
|
||||||
scope := ast.NewScope(nil) // method scope
|
scope := ast.NewScope(nil) // method scope
|
||||||
_, params := p.parseParameters(scope, false, true)
|
_, params := p.parseParameters(scope, false, true, "method")
|
||||||
results := p.parseResult(scope, true)
|
results := p.parseResult(scope, true)
|
||||||
typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results}
|
typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results}
|
||||||
}
|
}
|
||||||
|
|
@ -2886,12 +2894,12 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl {
|
||||||
|
|
||||||
var recv *ast.FieldList
|
var recv *ast.FieldList
|
||||||
if p.tok == token.LPAREN {
|
if p.tok == token.LPAREN {
|
||||||
_, recv = p.parseParameters(scope, false, false)
|
_, recv = p.parseParameters(scope, false, false, "receiver")
|
||||||
}
|
}
|
||||||
|
|
||||||
ident := p.parseIdent()
|
ident := p.parseIdent()
|
||||||
|
|
||||||
tparams, params := p.parseParameters(scope, recv == nil, true)
|
tparams, params := p.parseParameters(scope, recv == nil, true, "method") // context string only used in methods
|
||||||
results := p.parseResult(scope, true)
|
results := p.parseResult(scope, true)
|
||||||
|
|
||||||
var body *ast.BlockStmt
|
var body *ast.BlockStmt
|
||||||
|
|
|
||||||
|
|
@ -635,13 +635,12 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeNam
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the type parameter's bound
|
// set the type parameter's bound
|
||||||
if bound != nil {
|
// (do this even if bound == nil to make sure index is correctly increasing)
|
||||||
for _, name := range f.Names {
|
for _, name := range f.Names {
|
||||||
tname := tparams[index]
|
tname := tparams[index]
|
||||||
assert(name.Name == tname.name)
|
assert(name.Name == tname.name) // keep - this assertion caught index errors
|
||||||
tname.typ.(*TypeParam).bound = bound
|
tname.typ.(*TypeParam).bound = bound
|
||||||
index++
|
index++
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue