Repository: go
Issue: proposal: spec: allow methods on generic structs which meet subset of type constraint
Labels: LanguageChange,Proposal,generics,LanguageChangeReview

### Go Programming Experience

Experienced

### Other Languages Experience

JS, C, Python

### Related Idea

- [ ] Has this idea, or one like it, been proposed before?
- [ ] Does this affect error handling?
- [X] Is this about generics?
- [X] Is this change backward compatible? Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit

### Has this idea, or one like it, been proposed before?

No, not to my searching

### Does this affect error handling?

No

### Is this about generics?

Yes. This proposal allows adding methods on a subset of generic types.

### Proposal

Consider a generic type, such as:

```go
// Validator is a function which returns true if the argument is valid and false otherwise.
type Validator[T any] func(T) bool
```

I may want to write the following function:
```go
// Ignore returns a new validator which does not attempt to validate values who are equal to value.
// Otherwise, it uses the existing validator.
func (v Validator[T comparable]) Ignore(value T) Validator[T] {
  return func(t T) bool {
    if t == value {
      return true
    }

    return v(t)
  }
}
```

However, this is not allowed because I cannot further constrain T after Validator has been defined. I propose allowing further restrictions on T if and only if the further restriction is a subtype of the original type. A is a subtype of B if the set of types described by A is completely contained within B.

This will be helpful when writing methods which are not critical to the functionality of a type (i.e., it still makes sense to have validator functions where T is not comparable) but some subset of values of the type benefit from extra methods.

Here is another use case that could be useful:

```go
type SliceWrapper[T any] []T

func (s SliceWrapper[T constraints.Ordered]) Sort() SliceWrapper[T] {
  ...
}
```

### Language Spec Changes

Methods on generic types have only been permitted to omit constraints on the generic type. They may now either specify or omit it, if omitted it is by default the value from the type definition.

Not all methods defined on a generic type will be available to every instance, they will only be available if the extra constraints are met.

### Informal Change

_No response_

### Is this change backward compatible?

Yes, the type constraint may still be omitted as before.

### Orthogonality: How does this change interact or overlap with existing features?

The goal of this change is to improve the usability of generic utility types. Its success should be measured by its usage.

### Would this change make Go easier or harder to learn, and why?

In general, I don't think this increases the complexity of the language too much. However, I could see some possible confusion from this change. If a new go user sees a method defined on a generic type which their instance does not meet it could be confusing as to why this method is not available on their instance. Although, if the users understands type constraints this concept is no more complicated.

### Cost Description

Not every instance of a generic type will have the same method set, and the compiler will need to check this.

### Changes to Go ToolChain

_No response_

### Performance Costs

Compile time costs: negligible if not used. Run time cost: better than interface smuggling.

### Prototype

_No response_