pos := p.expect(token.FUNC)
tparams, params := p.parseParameters(true)
if tparams != nil {
- p.error(tparams.Pos(), "function type cannot have type parameters")
+ p.error(tparams.Pos(), "function type must have no type parameters")
}
results := p.parseResult()
p.exprLev--
if name0, _ := x.(*ast.Ident); name0 != nil && p.tok != token.COMMA && p.tok != token.RBRACK {
// generic method m[T any]
- list := p.parseParameterList(name0, token.RBRACK)
- rbrack := p.expect(token.RBRACK)
- tparams := &ast.FieldList{Opening: lbrack, List: list, Closing: rbrack}
+ //
+ // Interface methods do not have type parameters. We parse them for a
+ // better error message and improved error recovery.
+ _ = p.parseParameterList(name0, token.RBRACK)
+ _ = p.expect(token.RBRACK)
+ p.error(lbrack, "interface method must have no type parameters")
+
// TODO(rfindley) refactor to share code with parseFuncType.
_, params := p.parseParameters(false)
results := p.parseResult()
idents = []*ast.Ident{ident}
typ = &ast.FuncType{
- Func: token.NoPos,
- TypeParams: tparams,
- Params: params,
- Results: results,
+ Func: token.NoPos,
+ Params: params,
+ Results: results,
}
} else {
// embedded instantiated type
ident := p.parseIdent()
tparams, params := p.parseParameters(true)
+ if recv != nil && tparams != nil {
+ // Method declarations do not have type parameters. We parse them for a
+ // better error message and improved error recovery.
+ p.error(tparams.Opening, "method must have no type parameters")
+ tparams = nil
+ }
results := p.parseResult()
var body *ast.BlockStmt
`package p; func _[ /* ERROR "expected '\(', found '\['" */ A, B any](a A) B`,
`package p; func _[ /* ERROR "expected '\(', found '\['" */ A, B C](a A) B`,
`package p; func _[ /* ERROR "expected '\(', found '\['" */ A, B C[A, B]](a A) B`,
- `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B any](a A) B`,
- `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B C](a A) B`,
- `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B C[A, B]](a A) B`,
+
`package p; type _[A, /* ERROR "expected ']', found ','" */ B any] interface { _(a A) B }`,
`package p; type _[A, /* ERROR "expected ']', found ','" */ B C[A, B]] interface { _(a A) B }`,
`package p; func _[ /* ERROR "expected '\(', found '\['" */ T1, T2 interface{}](x T1) T2`,
`package p; var _ T[ /* ERROR "expected ';', found '\['" */ chan int]`,
// TODO(rfindley) this error message could be improved.
- `package p; func (_ /* ERROR "mixed named and unnamed parameters" */ R[P]) _[T any](x T)`,
- `package p; func (_ /* ERROR "mixed named and unnamed parameters" */ R[ P, Q]) _[T1, T2 any](x T)`,
+ `package p; func (_ /* ERROR "mixed named and unnamed parameters" */ R[P]) _(x T)`,
+ `package p; func (_ /* ERROR "mixed named and unnamed parameters" */ R[ P, Q]) _(x T)`,
- `package p; func (R[P] /* ERROR "missing element type" */ ) _[T any]()`,
+ `package p; func (R[P] /* ERROR "missing element type" */ ) _()`,
`package p; func _(T[P] /* ERROR "missing element type" */ )`,
`package p; func _(T[P1, /* ERROR "expected ']', found ','" */ P2, P3 ])`,
`package p; func _(T[P] /* ERROR "missing element type" */ ) T[P]`,
`package p; type _ interface{int| /* ERROR "expected ';'" */ float32; bool; m(); string;}`,
`package p; type I1[T any /* ERROR "expected ']', found any" */ ] interface{}; type I2 interface{ I1[int] }`,
`package p; type I1[T any /* ERROR "expected ']', found any" */ ] interface{}; type I2[T any] interface{ I1[T] }`,
- `package p; type _ interface { f[ /* ERROR "expected ';', found '\['" */ T any]() }`,
+ `package p; type _ interface { N[ /* ERROR "expected ';', found '\['" */ T] }`,
`package p; type T[P any /* ERROR "expected ']'" */ ] = T0`,
}
`package p; func _[ /* ERROR "expected '\(', found '\['" */ ]()`,
`package p; type _[A, /* ERROR "expected ']', found ','" */] struct{ A }`,
`package p; func _[ /* ERROR "expected '\(', found '\['" */ type P, *Q interface{}]()`,
+
+ `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B any](a A) B`,
+ `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B C](a A) B`,
+ `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B C[A, B]](a A) B`,
}
// invalidTParamErrs holds invalid source code examples annotated with the
// error messages produced when ParseTypeParams is set.
var invalidTParamErrs = []string{
`package p; type _[_ any] int; var _ = T[] /* ERROR "expected operand" */ {}`,
- `package p; var _ func[ /* ERROR "cannot have type parameters" */ T any](T)`,
+ `package p; var _ func[ /* ERROR "must have no type parameters" */ T any](T)`,
`package p; func _[]/* ERROR "empty type parameter list" */()`,
// TODO(rfindley) a better location would be after the ']'
- `package p; type _[A/* ERROR "all type parameters must be named" */,] struct{ A }`,
+ `package p; type _[A /* ERROR "all type parameters must be named" */ ,] struct{ A }`,
// TODO(rfindley) this error is confusing.
- `package p; func _[type /* ERROR "all type parameters must be named" */P, *Q interface{}]()`,
+ `package p; func _[type /* ERROR "all type parameters must be named" */ P, *Q interface{}]()`,
+
+ `package p; func (T) _[ /* ERROR "must have no type parameters" */ A, B any](a A) B`,
+ `package p; func (T) _[ /* ERROR "must have no type parameters" */ A, B C](a A) B`,
+ `package p; func (T) _[ /* ERROR "must have no type parameters" */ A, B C[A, B]](a A) B`,
}
func TestInvalid(t *testing.T) {
--- /dev/null
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T interface{ m[ /* ERROR "must have no type parameters" */ P any]() }
+
+func _(t T) {
+ var _ interface{ m[ /* ERROR "must have no type parameters" */ P any](); n() } = t
+}
+
+type S struct{}
+
+func (S) m[ /* ERROR "must have no type parameters" */ P any]() {}
+
+func _(s S) {
+ var _ interface{ m[ /* ERROR "must have no type parameters" */ P any](); n() } = s
+}
// _InvalidMethodTypeParams occurs when methods have type parameters.
//
- // Example:
- // type T int
- //
- // func (T) m[P any]() {}
+ // It cannot be encountered with an AST parsed using go/parser.
_InvalidMethodTypeParams
// _MisplacedTypeParam occurs when a type parameter is used in a place where
type T struct {}
func (T) m1() {}
-func (T) m2[ /* ERROR methods cannot have type parameters */ _ any]() {}
-func (T) m3[ /* ERROR methods cannot have type parameters */ P any]() {}
+func (T) m2[ /* ERROR method must have no type parameters */ _ any]() {}
+func (T) m3[ /* ERROR method must have no type parameters */ P any]() {}
// type inference across parameterized types
// type parameters in methods (generalization)
-type R0 struct{}
+// Type Parameter lists are not allowed on methods, and are not produced by
+// go/parser. The test cases below are preserved for consistency with types2,
+// which produces an error but stores type parameters.
+// type R0 struct{}
-func (R0) _[ /* ERROR methods cannot have type parameters */ T any](x T) {}
-func (R0 /* ERROR invalid receiver */ ) _[ /* ERROR methods cannot have type parameters */ R0 any]() {} // scope of type parameters starts at "func"
+// func (R0) _[ /* ERROR methods cannot have type parameters */ T any](x T) {}
+// func (R0 /* ERROR invalid receiver */ ) _[ /* ERROR methods cannot have type parameters */ R0 any]() {} // scope of type parameters starts at "func"
-type R1[A, B any] struct{}
+// type R1[A, B any] struct{}
-func (_ R1[A, B]) m0(A, B)
-func (_ R1[A, B]) m1[ /* ERROR methods cannot have type parameters */ T any](A, B, T) T { panic(0) }
-func (_ R1 /* ERROR not a generic type */ [R1, _]) _()
-func (_ R1[A, B]) _[ /* ERROR methods cannot have type parameters */ A /* ERROR redeclared */ any](B) {}
+// func (_ R1[A, B]) m0(A, B)
+// func (_ R1[A, B]) m1[ /* ERROR methods cannot have type parameters */ T any](A, B, T) T { panic(0) }
+// func (_ R1 /* ERROR not a generic type */ [R1, _]) _()
+// func (_ R1[A, B]) _[ /* ERROR methods cannot have type parameters */ A /* ERROR redeclared */ any](B) {}
-func _() {
- var r R1[int, string]
- r.m1[rune](42, "foo", 'a')
- r.m1[rune](42, "foo", 1.2 /* ERROR cannot use .* as rune .* \(truncated\) */)
- r.m1(42, "foo", 1.2) // using type inference
- var _ float64 = r.m1(42, "foo", 1.2)
-}
+// func _() {
+// var r R1[int, string]
+// r.m1[rune](42, "foo", 'a')
+// r.m1[rune](42, "foo", 1.2 /* ERROR cannot use .* as rune .* \(truncated\) */)
+// r.m1(42, "foo", 1.2) // using type inference
+// var _ float64 = r.m1(42, "foo", 1.2)
+// }
type I1[A any] interface {
m1(A)
var x T25 /* ERROR without instantiation */ .m1
// crash 26
-type T26 = interface{ F26[ /* ERROR methods cannot have type parameters */ Z any]() }
+type T26 = interface{ F26[ /* ERROR interface method must have no type parameters */ Z any]() }
// The error messages on the line below differ from types2 because for backward
// compatibility go/parser must produce an IndexExpr with BadExpr index for the
// expression F26[].
--- /dev/null
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// The parser no longer parses type parameters for methods.
+// In the past, type checking the code below led to a crash (#50427).
+
+type T interface{ m[ /* ERROR "must have no type parameters" */ P any]() }
+
+func _(t T) {
+ var _ interface{ m[ /* ERROR "must have no type parameters" */ P any](); n() } = t /* ERROR "does not implement" */
+}
+
+type S struct{}
+
+func (S) m[ /* ERROR "must have no type parameters" */ P any]() {}
+
+func _(s S) {
+ var _ interface{ m[ /* ERROR "must have no type parameters" */ P any](); n() } = s /* ERROR "does not implement" */
+
+}