diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index dd56b13cb2f5e..15797e6a15ffe 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2523,7 +2523,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { let span = cx.tcx.def_span(adt_def.did()); let mut potential_variants = adt_def.variants().iter().filter_map(|variant| { let definitely_inhabited = match variant - .inhabited_predicate(cx.tcx, *adt_def) + .inhabited_predicate(cx.tcx) .instantiate(cx.tcx, args) .apply_any_module(cx.tcx, cx.typing_env()) { diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 632483c55d1ff..7c696d057c1d9 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2170,7 +2170,7 @@ rustc_queries! { feedable } - query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> { + query inhabited_predicate_for_def(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> { desc { "computing the uninhabited predicate of `{:?}`", key } } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 1d4c55aa34690..76d11e29e9201 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -46,12 +46,13 @@ use std::assert_matches; use rustc_data_structures::fx::FxHashSet; +use rustc_hir::def::DefKind; use rustc_span::def_id::LocalModId; use rustc_type_ir::TyKind::*; use tracing::instrument; use crate::query::Providers; -use crate::ty::{self, DefId, Ty, TyCtxt, TypeVisitableExt, VariantDef, Visibility}; +use crate::ty::{self, AdtDef, DefId, Ty, TyCtxt, TypeVisitableExt, VariantDef, Visibility}; pub mod inhabited_predicate; @@ -59,7 +60,7 @@ pub use inhabited_predicate::InhabitedPredicate; pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { - inhabited_predicate_adt, + inhabited_predicate_for_def, inhabited_predicate_type, is_opsem_inhabited_raw, ..*providers @@ -68,48 +69,64 @@ pub(crate) fn provide(providers: &mut Providers) { /// Returns an `InhabitedPredicate` that is generic over type parameters and /// requires calling [`InhabitedPredicate::instantiate`] -fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> { - if let Some(def_id) = def_id.as_local() { - tcx.ensure_ok().check_representability(def_id); +fn inhabited_predicate_for_def(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> { + match tcx.def_kind(def_id) { + DefKind::Enum => { + if let Some(def_id) = def_id.as_local() { + tcx.ensure_ok().check_representability(def_id); + } + let adt = tcx.adt_def(def_id); + InhabitedPredicate::any(tcx, adt.variants().iter().map(|v| v.inhabited_predicate(tcx))) + } + DefKind::Struct => { + if let Some(def_id) = def_id.as_local() { + tcx.ensure_ok().check_representability(def_id); + } + let adt = tcx.adt_def(def_id); + variant_inhabited_predicate(tcx, adt, adt.non_enum_variant()) + } + DefKind::Variant => { + let adt = tcx.adt_def(tcx.parent(def_id)); + let variant = adt.variant_with_id(def_id); + variant_inhabited_predicate(tcx, adt, variant) + } + def_kind => bug!("unexpected DefKind: {def_kind:?}"), } - - let adt = tcx.adt_def(def_id); - InhabitedPredicate::any( - tcx, - adt.variants().iter().map(|variant| variant.inhabited_predicate(tcx, adt)), - ) } -impl<'tcx> VariantDef { - /// Calculates the forest of `DefId`s from which this variant is visibly uninhabited. - pub fn inhabited_predicate( - &self, - tcx: TyCtxt<'tcx>, - adt: ty::AdtDef<'_>, - ) -> InhabitedPredicate<'tcx> { - debug_assert!(!adt.is_union()); - InhabitedPredicate::all( - tcx, - self.fields.iter().map(|field| { - let pred = tcx - .type_of(field.did) - .instantiate_identity() - .skip_norm_wip() - .inhabited_predicate(tcx); - if adt.is_enum() { - return pred; - } - match field.vis { - Visibility::Public => pred, - Visibility::Restricted(from) => { - InhabitedPredicate::NotInModule(from).or(tcx, pred) - } - } - }), - ) +impl VariantDef { + pub fn inhabited_predicate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx> { + if self.fields.is_empty() { + return InhabitedPredicate::True; + } + tcx.inhabited_predicate_for_def(self.def_id) } } +fn variant_inhabited_predicate<'tcx>( + tcx: TyCtxt<'tcx>, + adt: AdtDef<'tcx>, + variant: &VariantDef, +) -> InhabitedPredicate<'tcx> { + InhabitedPredicate::all( + tcx, + variant.fields.iter().map(|field| { + let pred = tcx + .type_of(field.did) + .instantiate_identity() + .skip_norm_wip() + .inhabited_predicate(tcx); + if adt.is_enum() { + return pred; + } + match field.vis { + Visibility::Public => pred, + Visibility::Restricted(from) => InhabitedPredicate::NotInModule(from).or(tcx, pred), + } + }), + ) +} + impl<'tcx> Ty<'tcx> { #[instrument(level = "debug", skip(tcx), ret)] pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx> { @@ -231,7 +248,7 @@ impl<'tcx> Ty<'tcx> { /// N.B. this query should only be called through `Ty::inhabited_predicate` fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedPredicate<'tcx> { match *ty.kind() { - Adt(adt, args) => tcx.inhabited_predicate_adt(adt.did()).instantiate(tcx, args), + Adt(adt, args) => tcx.inhabited_predicate_for_def(adt.did()).instantiate(tcx, args), Tuple(tys) => { InhabitedPredicate::all(tcx, tys.iter().map(|ty| ty.inhabited_predicate(tcx))) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 41806547932cd..e3b24b7748cc6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -734,7 +734,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { { let variant_inhabited = adt .variant(*variant_index) - .inhabited_predicate(self.tcx, *adt) + .inhabited_predicate(self.tcx) .instantiate(self.tcx, args); variant_inhabited.apply(self.tcx, cx.typing_env, cx.module) && !variant_inhabited.apply_ignore_module(self.tcx, cx.typing_env) diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index c3b3d14848982..09528b58cbf2f 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -380,7 +380,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { let variant_def_id = def.variant(idx).def_id; // Visibly uninhabited variants. let is_inhabited = v - .inhabited_predicate(cx.tcx, *def) + .inhabited_predicate(cx.tcx) .instantiate(cx.tcx, args) .apply_revealing_opaque(cx.tcx, cx.typing_env, cx.module, &|key| { cx.reveal_opaque_key(key)