From 46442bd4a959bd69ffe72a2fa3b6fcb154553ad9 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 20 Nov 2019 15:00:05 -0800 Subject: [PATCH] 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 --- src/go/parser/parser.go | 22 +++++++++++++++------- src/go/types/decl.go | 13 ++++++------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index ec15a7a3c4..cb37e5229a 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -1116,11 +1116,14 @@ func (p *parser) parseTypeParams(scope *ast.Scope) *ast.FieldList { 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 { defer un(trace(p, "Parameters")) } + // 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 @@ -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 if p.tok != token.RPAREN { 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 { - _, results := p.parseParameters(scope, false, false) + _, results := p.parseParameters(scope, false, false, "result") return results } @@ -1180,7 +1188,7 @@ func (p *parser) parseFuncType(typeContext bool) (*ast.FuncType, *ast.Scope) { pos := p.expect(token.FUNC) 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) return &ast.FuncType{Func: pos, Params: params, Results: results}, scope @@ -1199,7 +1207,7 @@ func (p *parser) parseMethodSpec(scope *ast.Scope) *ast.Field { // method idents = []*ast.Ident{ident} scope := ast.NewScope(nil) // method scope - _, params := p.parseParameters(scope, false, true) + _, params := p.parseParameters(scope, false, true, "method") results := p.parseResult(scope, true) typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results} } else { @@ -1340,7 +1348,7 @@ func (p *parser) parseConstraint() *ast.Constraint { // method mname = ident scope := ast.NewScope(nil) // method scope - _, params := p.parseParameters(scope, false, true) + _, params := p.parseParameters(scope, false, true, "method") results := p.parseResult(scope, true) typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results} } @@ -2886,12 +2894,12 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl { var recv *ast.FieldList if p.tok == token.LPAREN { - _, recv = p.parseParameters(scope, false, false) + _, recv = p.parseParameters(scope, false, false, "receiver") } 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) var body *ast.BlockStmt diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 30ad852e79..bf0e1e6e5f 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -635,13 +635,12 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeNam } // set the type parameter's bound - if bound != nil { - for _, name := range f.Names { - tname := tparams[index] - assert(name.Name == tname.name) - tname.typ.(*TypeParam).bound = bound - index++ - } + // (do this even if bound == nil to make sure index is correctly increasing) + for _, name := range f.Names { + tname := tparams[index] + assert(name.Name == tname.name) // keep - this assertion caught index errors + tname.typ.(*TypeParam).bound = bound + index++ } }