Code change:
The following code compiles on nightly (): But if the wrapper type is moved into a module to make the field private, then it does not: (): Making the field makes it compile again. Is this expected? I suppose I could understand if it is; the private fields could change to make actually be constructable and therefore make the pattern refutable. But if that's the case, then I think the compiler should point this out, like . If indeed this is expected, is there any way for me as a library author to somehow convince the compiler that I will never change the fields to make the type constructable? I want users of my library to be able to elide match arms when I give them an . label +T-compiler +F-never_type +D-confusing +requires-nightly +S-bug-has-mcve
label +F-exhaustive_patterns
are we sure this is actually a bug? As I said, I could understand how it's not:
I'm not sure either way - however at the very least, as you point out, it makes sense to have some better diagnostics
This is definitely intentional. But yeah, it should have a better error message. Not currently I don't think. It would probably require us to add an trait, eg. something like: This trait would then need to be a lang item so that the exhaustiveness check could make use of it. Adding this trait would require an RFC but I doubt there'll be much enthusiasm for adding another special trait for such a niche use-case. Alternatively, you could give an or method to expose the uninhabitedness of the inner value. It's not quite what you're asking for but it's still concise-ish:
Is supposed to be “injected” where an otherwise required match arm was omitted? Wouldn't that run into the same discussions project-deref-patterns had about impure code (code with side effects) inside patterns? Their existence would heavily hinder optimizations of match expressions (like translation to jump tables or reordering).
If the type implementing really is uninhabited then there won't actually be any impure code in the match. The call to would only need to be injected for types that fake uninhabitedness with an impl that panics/aborts. We could also rule that out be instead making -only like .
Making a trait isn't straightforward exactly because inhabitedness depends on visibility questions. It would probably have to mean "Uninhabited as far as the outside world is concerned", or it could use a trick like the in to make it depend on the module.

Related discussion:
text: AdtDefinedHere { adt_def_span, ty, variants } }; <ins> // Emit an extra note if the first uncovered witness is // visibly uninhabited anywhere in the current crate. let witness_1_is_privately_uninhabited = if cx.tcx.features().exhaustive_patterns && let Some(witness_1) = witnesses.get(0) && let ty::Adt(adt, substs) = witness_1.ty().kind() && adt.is_enum() && let Constructor::Variant(variant_index) = witness_1.ctor() { let variant = adt.variant(*variant_index); let inhabited = variant.inhabited_predicate(cx.tcx, *adt).subst(cx.tcx, substs); assert!(inhabited.apply(cx.tcx, cx.param_env, cx.module)); !inhabited.apply_ignore_module(cx.tcx, cx.param_env) } else { false }; </ins> self.error = Err(self.tcx.sess.emit_err(PatternNotCovered { span: pat.span, origin, uncovered: Uncovered::new(pat.span, &cx, witnesses), inform, interpreted_as_const, <ins> witness_1_is_privately_uninhabited: witness_1_is_privately_uninhabited.then_some(()), </ins> _p: (), pattern_ty, let_suggestion,