Skip to content

Commit

Permalink
Introduce InhabitedPredicate
Browse files Browse the repository at this point in the history
  • Loading branch information
camsteffen committed Oct 22, 2022
1 parent 0940040 commit 2928e9e
Show file tree
Hide file tree
Showing 8 changed files with 338 additions and 354 deletions.
46 changes: 5 additions & 41 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2467,42 +2467,6 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
None
}

/// Determines whether the given type is inhabited. `None` means that we don't know.
fn ty_inhabited<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<bool> {
use rustc_type_ir::sty::TyKind::*;
if !cx.tcx.type_uninhabited_from(cx.param_env.and(ty)).is_empty() {
// This is definitely uninhabited from some module.
return Some(false);
}
match ty.kind() {
Never => Some(false),
Int(_) | Uint(_) | Float(_) | Bool | Char | RawPtr(_) => Some(true),
// Fallback for more complicated types. (Note that `&!` might be considered
// uninhabited so references are "complicated", too.)
_ => None,
}
}
/// Determines whether a product type formed from a list of types is inhabited.
fn tys_inhabited<'tcx>(
cx: &LateContext<'tcx>,
tys: impl Iterator<Item = Ty<'tcx>>,
) -> Option<bool> {
let mut definitely_inhabited = true; // with no fields, we are definitely inhabited.
for ty in tys {
match ty_inhabited(cx, ty) {
// If any type is uninhabited, the product is uninhabited.
Some(false) => return Some(false),
// Otherwise go searching for a `None`.
None => {
// We don't know.
definitely_inhabited = false;
}
Some(true) => {}
}
}
if definitely_inhabited { Some(true) } else { None }
}

fn variant_find_init_error<'tcx>(
cx: &LateContext<'tcx>,
variant: &VariantDef,
Expand Down Expand Up @@ -2599,11 +2563,11 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
// And now, enums.
let span = cx.tcx.def_span(adt_def.did());
let mut potential_variants = adt_def.variants().iter().filter_map(|variant| {
let inhabited = tys_inhabited(
cx,
variant.fields.iter().map(|field| field.ty(cx.tcx, substs)),
);
let definitely_inhabited = match inhabited {
let definitely_inhabited = match variant
.inhabited_predicate(cx.tcx, *adt_def)
.subst(cx.tcx, substs)
.apply_any_module(cx.tcx, cx.param_env)
{
// Entirely skip uninhbaited variants.
Some(false) => return None,
// Forward the others, but remember which ones are definitely inhabited.
Expand Down
15 changes: 7 additions & 8 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1653,14 +1653,13 @@ rustc_queries! {
separate_provide_extern
}

/// Computes the set of modules from which this type is visibly uninhabited.
/// To check whether a type is uninhabited at all (not just from a given module), you could
/// check whether the forest is empty.
query type_uninhabited_from(
key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
) -> ty::inhabitedness::DefIdForest<'tcx> {
desc { "computing the inhabitedness of `{}`", key.value }
remap_env_constness
query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> {
desc { "computing the uninhabited predicate of `{:?}`", key }
}

/// Do not call this query directly: invoke `Ty::inhabited_predicate` instead.
query inhabited_predicate_type(key: Ty<'tcx>) -> ty::inhabitedness::InhabitedPredicate<'tcx> {
desc { "computing the uninhabited predicate of `{}`", key }
}

query dep_kind(_: CrateNum) -> CrateDepKind {
Expand Down
145 changes: 0 additions & 145 deletions compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs

This file was deleted.

Loading

0 comments on commit 2928e9e

Please sign in to comment.