So I basically agree with @glaebhoerl here, and think bool as an analogue is very compelling.
I'd like to thank @arielb1 for addressing the bool case:
Our previous consensus was that values must always have legal values, so Ok(42): Option is not possible to have even in unsafe code without UB, but say Ok(&42): Option<&bool> is possible, and matching on it results in UB.
Loosely inspired by Agda's absurd patterns, we can actually make a coherent policy out this by forcing one to get the value in a "match arm stub", e.g.:
match void_ref_result {
Err(e) => ... ,
Ok(&_), // no arm needed
}
This would add clarity when the uninhabited type is deeply nested. I'd consider this an excellent compromise for everywhere, or convent sugar for unsafe code for
match void_ref_result {
Err(e) => ... ,
Ok(&r) => match r { },
}
Where one relies on UB to remove the extra branching instead of being explicit.