go: proposal: spec: allow omitting type parameters in methods that don't use them
In the current generics proposal, all methods on a generic type must mention the type’s type parameters.
For example:
type Foo[T1, T2 any] struct {...}
func (f *Foo[T1, T2]) Something() {}
It seems to be very common that methods like this don’t actually need to mention the type parameters by name, which makes it tedious to declare them. One possibility is to avoid giving them names:
func (f *Foo[_, _]) Something() {}
but that doesn’t help the extra verbosity much.
I propose that the type parameter clause in methods should only be required if the method body actually uses the type parameters.
This also makes it easier to refactor code when we might wish to add or remove type parameters to a type without undue code churn.
So we’d allow this, even though Foo is a generic type:
func (f *Foo) Something() {}
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 28
- Comments: 17 (12 by maintainers)
This seems like a premature optimization. Also the signal in the method that Foo is a parameterized type seems important to preserve.
Should we be concerned about this causing confusion about the nature of Go generics? I believe there’s no other place in the language where a generic type can be referenced without type parameters, and that reflects Go’s lack of support for passing around “meta-types” or using “raw types”, as they’re called in Java. This consistency seems desirable to me.
That said, I am sympathetic to the motivation behind this proposal. I wonder if syntax that keeps the brackets but avoids enumerating the type arguments would be more clear, maybe by using ellipses:
This syntax is still preferable to using underscores, because it never needs to be changed as the number of type parameters changes.
Based on the discussion above, this proposal seems like a likely decline. — rsc for the proposal review group
No change in consensus, so declined. — rsc for the proposal review group
I will go against the flow here. I think func (f *Foo[_, _]) Something() {} is fine. It’s explicit, yes, but then it’s very clear that we are defining a method of a generic type.
Please consider that the method Something might be defined in a different file than the type Foo, e g. in case of code generation. Then, allowing to omit the type parameters is confusing because it seems like we are defining a method on a normal type.
So for the sake of readability and explicitness, I respectfully oppose this proposal.
That’s the data point that a colleague encountered at work, which made me ask Roger about this feature yesterday, triggering the proposal 😃 Essentially, someone was trying type parameters on a large existing codebase, and a type with dozens of methods only needed to use the receiver’s type parameters in about half of its methods. The other methods all had to gain repetitive
[_, _]bits.It’s just one data point, so I can’t argue how often this will be the case with methods on generic types. But it seems like an easy win to make this optional, just like other bits of a function declaration (return parameters, receiver, parameter names) are also optional.