Never types and inference

An ! argument is a contradiction at compile time, because you cannot obtain a ! value in the first place to call the function with. Merely obtaining a ! is undefined behaviour. The compiler doesn't have to emit the function body at all; it's dead code. And all dead code is equivalent.

There is no contradiction in different impls having different associated types. The proposal is to allow ! to have multiple impls of a single trait in certain conditions; namely, for 'purely negative' traits I mentioned. Impls of such traits for ! can only differ in their choice of associated types, and are otherwise equivalent. Choosing a specific impl is therefore a mere matter of type inference, no different from choosing a specific instance of a generic type.

Of course this would require re-working some fundamentals. For one thing, instantiating a generic with a trait bound would require establishing an identity for the impl and passing it along with the type; the compiler can no longer 're-derive' the impl each time the type is used. But it's not a priori inconsistent.

Also, general impl-relevance has been requested before:

@canndrew's proposal leaves vacuous impls for ! anonymous, because type inference is sufficient to distinguish between them – at least in the motivating cases. I can imagine some (admittedly rather contrived) cases where it wouldn't be:

trait Foo {
    type Iter: Iterator;
}

struct Bar;

impl Foo for Bar {
    type Iter = !;
}

What is <Bar as Foo>::Iter::Item? A specific impl of Iterator for ! would have to be chosen by the time Foo is implemented for Bar, but there is no syntax to disambiguate it.

1 Like