# Satisfying a type constraint

##### August 8, 2023

## Satisfying a type constraint

A type argument

`T`

satisfiesa type constraint`C`

if`T`

is an element of the type set defined by`C`

; i.e., if`T`

implements`C`

. As an exception, a strictly comparable type constraint may also be satisfied by a comparable (not necessarily strictly comparable) type argument. More precisely:A type

`T`

satisfies a constraint`C`

if

`T`

implements`C`

; or`C`

can be written in the form`interface{ comparable; E }`

, where`E`

is a basic interface and`T`

is comparable and implements E.

WUT?

I feel like Lone Starr after Dark Helmet says “I am your father’s brother’s nephew’s cousin’s former roommate.”.

Let’s see if we can’t make some sense of this. The spec includes a table of examples that helps a bit:

`type argument type constraint // constraint satisfaction int interface{ ~int } // satisfied: int implements interface{ ~int } string comparable // satisfied: string implements comparable (string is stricty comparable) []byte comparable // not satisfied: slices are not comparable any interface{ comparable; int } // not satisfied: any does not implement interface{ int } any comparable // satisfied: any is comparable and implements the basic interface any struct{f any} comparable // satisfied: struct{f any} is comparable and implements the basic interface any any interface{ comparable; m() } // not satisfied: any does not implement the basic interface interface{ m() } interface{ m() } interface{ comparable; m() } // satisfied: interface{ m() } is comparable and implements the basic interface interface{ m() }`

Let’s step back and break down the requirements one at a time.

The first one, I think, is pretty straight forward: “A type `T`

satisfies a constraint `C`

if: `T`

implements `C`

” No problems here.

The seconde one is where I think things get muddy: “`C`

can be written in the form `interface{ comparable; E }`

, where `E`

is a basic interface and `T`

is comparable and implements `E`

.”

Fortunately, this second clause only matters if your type constraint contians the `comparable`

interface, so you can just ignore it in all other cases.

If your constraint *does* contain the `comparable`

interface, then you have four possible scenarios:

- It contains
*only*the`comparable`

interface, in which case the first clause is all you need: Does your type implement`comparable`

? - It contains the
`comparable`

interface and some other type element which is not`comparable`

, introducing a disallowed contradiction, thus it’s not mentioned in the spec. - It contains the
`comparable`

interface, and some other element type whihc*is*`comparable`

, making it redundant, thus it’s not mentioned in the spec. - It contains the
`comparable`

interface, and some other*basic*interface. This*is*what’s mentioned in the spec.

I find that breaking it down like this makes it more clear why the spec is worded the way it is. And now it becomes apparent to me that the spec isn’t describing some archane bother’s nephew’s cousin’s roomate type of situation; rather it’s just explaining the only logical combination of `comparable`

and any other constraint.

This section of the spec has one last detail to mention, which I’ll throw in for good measure:

Because of the exception in the constraint satisfaction rule, comparing operands of type parameter type may panic at run-time (even though comparable type parameters are always strictly comparable).

So just avoid doing that. ðŸ˜Š

Or if you can’t, and you need to guard against such runtime panics, you’ll need to use a deferred `recover`

.

Quotes from *The Go Programming Language Specification* Version of December 15, 2022