Skip to content

proposal: spec: allow interface types to instantiate comparable type parameters #52509

@zephyrtronium

Description

@zephyrtronium

Background

Out of caution over backward compatibility of features introduced with generics, with little discussion with the community when changing a major proposal that had already been accepted, Go 1.18 defined the predeclared constraint comparable to be "the set of all non-interface types that are comparable." The majority of the conversation motivating the "non-interface" portion of that definition occurred in #50646 and #49587.

That interface types are comparable but not comparable is a significant pain point for a number of otherwise fine uses of generics: e.g., one cannot use x/exp/maps algorithms on map types which have reflect.Type as keys. #52474 (now retracted) was proposed to alleviate this problem, noting that the precise definition of comparable should include types like [1]reflect.Type, which is an array type supporting == rather than an interface type. A significant portion of the comments on that proposal noted that the entire motivation for the proposal is the inconsistency between "comparable" and comparable.

Proposal

The proposal here is to allow interface types to instantiate type parameters constrained by comparable. In essence, I propose to remove the term "non-interface" from the definition of comparable, so that "comparable" and comparable mean the same thing in every context in Go.

@atdiar points out that other language in the spec would produce contradictions following that simple change. This proposal would additionally require a change to the definition of type sets or the definition of implementing interfaces, likely splitting either or both into two senses for type parameters and otherwise.

A consequence of this proposal is that it becomes possible to write generic code using comparable which panics on comparison with non-comparable concrete types. That is an aspect of the type system which has existed since long before Go 1.0; in particular, see @nield's demonstration that the results are very similar to the situation we've always had. What we gain is the ability to write code generic over all comparable types, rather than most of them with no solution for the remainder.

For the concrete change to the Go specification that I propose to implement this, see #52509 (comment). It is not the only possible approach. @jimmyfrasche proposes #52509 (comment), and @Merovius proposes #52509 (comment) with an enumeration of examples at #52509 (comment).

Related Proposals

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions