The compiler does not recognise Ok(&'r !) as an infallible variant. I'm starting with the assumption that the error is in my own understanding and/or syntax and am turning up a blank on solving this.
#![feature(never_type)]
#![feature(try_trait_v2)]
use std::ops::FromResidual;
enum MyResult<'r, T, E> {
Ok(&'r T),
Err(&'r E),
}
// This should compile - instead it gives error[E0004]: non-exhaustive patterns: `lifetimes::MyResult::Ok(_)` not covered
impl<'r, T, E> FromResidual<MyResult<'r, !, E>> for MyResult<'r, T, E> {
fn from_residual(residual: MyResult<'r, !, E>) -> Self {
match residual {
MyResult::Err(_) => todo!(),
}
}
}
// Longhand alternative ...
enum MyResidual<'r, E> {
Ok(&'r !),
Err(&'r E),
}
// ... also refuses to compile with error[E0004]: non-exhaustive patterns: `MyResidual::Ok(_)` not covered
impl<'r, T, E> FromResidual<MyResidual<'r, E>> for MyResult<'r, T, E> {
fn from_residual(residual: MyResidual<'r, E>) -> Self {
match residual {
MyResidual::Err(_) => todo!(),
}
}
}
// For comparison this works fine ...
enum MyOwnedResidual<'r, E> {
Ok(!),
Err(&'r E),
}
// ... and compiles without requiring an Ok(_) pattern
impl<'r, T, E> FromResidual<MyOwnedResidual<'r, E>> for MyResult<'r, T, E> {
fn from_residual(residual: MyOwnedResidual<'r, E>) -> Self {
match residual {
MyOwnedResidual::Err(_) => todo!(),
}
}
}
you need to exhaustively match your own enum, in doing so you destructure the Ok variant and bind a variable to a never type, which can then be eliminated as an uninhabited type, e.g. with match or coercion.
impl<'r, T, E> FromResidual<MyResult<'r, !, E>> for MyResult<'r, T, E> {
fn from_residual(residual: MyResult<'r, !, E>) -> Self {
match residual {
MyResult::Err(_) => todo!(),
MyResult::Ok(&never) => match never {}
// also valid, because `!` coerce to arbitrary type:
//MyResult::Ok(&never) => never,
}
}
}
The advantage is that the compiler checks that the code is actually unreachable; whereas if you write unreachable!(), there is no such check. unreachable!() should be used when you can't write the code in a way that the compiler can see the unreachability, but in this case you can — it’s just less obvious than the way you hoped for.