From cc8dddbac9e04f125c7e81dbe9fb6a01990e8b25 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sun, 23 Oct 2022 17:32:40 -0500 Subject: [PATCH] Factor out conservative_is_privately_uninhabited --- compiler/rustc_borrowck/src/type_check/mod.rs | 5 +- compiler/rustc_middle/src/query/mod.rs | 11 ---- .../ty/inhabitedness/inhabited_predicate.rs | 7 +++ .../rustc_middle/src/ty/inhabitedness/mod.rs | 9 +++ .../src/build/matches/simplify.rs | 6 +- compiler/rustc_mir_transform/src/generator.rs | 2 +- compiler/rustc_ty_utils/src/layout.rs | 3 +- .../rustc_ty_utils/src/layout_sanity_check.rs | 2 +- compiler/rustc_ty_utils/src/ty.rs | 57 ------------------- ...m_env-1.rs => inhabited-assoc-ty-ice-1.rs} | 2 +- ...m_env-2.rs => inhabited-assoc-ty-ice-2.rs} | 2 +- 11 files changed, 25 insertions(+), 81 deletions(-) rename src/test/ui/const-generics/{conservative_is_privately_uninhabited_uses_correct_param_env-1.rs => inhabited-assoc-ty-ice-1.rs} (84%) rename src/test/ui/const-generics/{conservative_is_privately_uninhabited_uses_correct_param_env-2.rs => inhabited-assoc-ty-ice-2.rs} (82%) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 7d36a63943c..9b6c7d27c79 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1564,10 +1564,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } None => { - if !self - .tcx() - .conservative_is_privately_uninhabited(self.param_env.and(sig.output())) - { + if !sig.output().is_privately_uninhabited(self.tcx(), self.param_env) { span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig); } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 02772013437..21097b1fec6 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2078,17 +2078,6 @@ rustc_queries! { desc { "normalizing opaque types in `{:?}`", key } } - /// Checks whether a type is definitely uninhabited. This is - /// conservative: for some types that are uninhabited we return `false`, - /// but we only return `true` for types that are definitely uninhabited. - /// `ty.conservative_is_privately_uninhabited` implies that any value of type `ty` - /// will be `Abi::Uninhabited`. (Note that uninhabited types may have nonzero - /// size, to account for partial initialisation. See #49298 for details.) - query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - desc { "conservatively checking if `{}` is privately uninhabited", key.value } - remap_env_constness - } - query limits(key: ()) -> Limits { desc { "looking up limits" } } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index b7aa455727d..33f72729798 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -41,6 +41,13 @@ impl<'tcx> InhabitedPredicate<'tcx> { self.apply_inner(tcx, param_env, &|_| Err(())).ok() } + /// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is, + /// privately uninhabited types are considered always uninhabited. + pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> bool { + let Ok(result) = self.apply_inner::(tcx, param_env, &|_| Ok(true)); + result + } + fn apply_inner( self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index ce9ec5c2b69..ace81bc4f83 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -169,6 +169,15 @@ impl<'tcx> Ty<'tcx> { ) -> bool { self.inhabited_predicate(tcx).apply(tcx, param_env, module) } + + /// Returns true if the type is uninhabited without regard to visibility + pub fn is_privately_uninhabited( + self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> bool { + !self.inhabited_predicate(tcx).apply_ignore_module(tcx, param_env) + } } /// N.B. this query should only be called through `Ty::inhabited_predicate` diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 924d2f555b9..caf27eb39d7 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -264,10 +264,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| { i == variant_index || { self.tcx.features().exhaustive_patterns - && v.inhabited_predicate(self.tcx, adt_def) + && !v + .inhabited_predicate(self.tcx, adt_def) .subst(self.tcx, substs) - .apply_any_module(self.tcx, self.param_env) - != Some(true) + .apply_ignore_module(self.tcx, self.param_env) } }) && (adt_def.did().is_local() || !adt_def.is_variant_list_non_exhaustive()); diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index c833de3a8a7..fcd63b6cfa1 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1015,7 +1015,7 @@ fn insert_panic_block<'tcx>( fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { // Returning from a function with an uninhabited return type is undefined behavior. - if tcx.conservative_is_privately_uninhabited(param_env.and(body.return_ty())) { + if body.return_ty().is_privately_uninhabited(tcx, param_env) { return false; } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index b59be0a0ea7..92e8542795f 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -442,8 +442,7 @@ fn layout_of_uncached<'tcx>( let element = cx.layout_of(element)?; let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow(ty))?; - let abi = if count != 0 && tcx.conservative_is_privately_uninhabited(param_env.and(ty)) - { + let abi = if count != 0 && ty.is_privately_uninhabited(tcx, param_env) { Abi::Uninhabited } else { Abi::Aggregate { sized: true } diff --git a/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout_sanity_check.rs index 100926ad446..ee5e7bc2359 100644 --- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs +++ b/compiler/rustc_ty_utils/src/layout_sanity_check.rs @@ -12,7 +12,7 @@ pub(super) fn sanity_check_layout<'tcx>( layout: &TyAndLayout<'tcx>, ) { // Type-level uninhabitedness should always imply ABI uninhabitedness. - if cx.tcx.conservative_is_privately_uninhabited(cx.param_env.and(layout.ty)) { + if layout.ty.is_privately_uninhabited(cx.tcx, cx.param_env) { assert!(layout.abi.is_uninhabited()); } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 99d3bda6ebf..c60ade360df 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -416,62 +416,6 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness) } -/// Don't call this directly: use ``tcx.conservative_is_privately_uninhabited`` instead. -pub fn conservative_is_privately_uninhabited_raw<'tcx>( - tcx: TyCtxt<'tcx>, - param_env_and: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, -) -> bool { - let (param_env, ty) = param_env_and.into_parts(); - match ty.kind() { - ty::Never => { - debug!("ty::Never =>"); - true - } - ty::Adt(def, _) if def.is_union() => { - debug!("ty::Adt(def, _) if def.is_union() =>"); - // For now, `union`s are never considered uninhabited. - false - } - ty::Adt(def, substs) => { - debug!("ty::Adt(def, _) if def.is_not_union() =>"); - // Any ADT is uninhabited if either: - // (a) It has no variants (i.e. an empty `enum`); - // (b) Each of its variants (a single one in the case of a `struct`) has at least - // one uninhabited field. - def.variants().iter().all(|var| { - var.fields.iter().any(|field| { - let ty = tcx.bound_type_of(field.did).subst(tcx, substs); - tcx.conservative_is_privately_uninhabited(param_env.and(ty)) - }) - }) - } - ty::Tuple(fields) => { - debug!("ty::Tuple(..) =>"); - fields.iter().any(|ty| tcx.conservative_is_privately_uninhabited(param_env.and(ty))) - } - ty::Array(ty, len) => { - debug!("ty::Array(ty, len) =>"); - match len.try_eval_usize(tcx, param_env) { - Some(0) | None => false, - // If the array is definitely non-empty, it's uninhabited if - // the type of its elements is uninhabited. - Some(1..) => tcx.conservative_is_privately_uninhabited(param_env.and(*ty)), - } - } - ty::Ref(..) => { - debug!("ty::Ref(..) =>"); - // References to uninitialised memory is valid for any type, including - // uninhabited types, in unsafe code, so we treat all references as - // inhabited. - false - } - _ => { - debug!("_ =>"); - false - } - } -} - pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { asyncness, @@ -481,7 +425,6 @@ pub fn provide(providers: &mut ty::query::Providers) { instance_def_size_estimate, issue33140_self_ty, impl_defaultness, - conservative_is_privately_uninhabited: conservative_is_privately_uninhabited_raw, ..*providers }; } diff --git a/src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-1.rs b/src/test/ui/const-generics/inhabited-assoc-ty-ice-1.rs similarity index 84% rename from src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-1.rs rename to src/test/ui/const-generics/inhabited-assoc-ty-ice-1.rs index c9e26c302bf..b385406b020 100644 --- a/src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-1.rs +++ b/src/test/ui/const-generics/inhabited-assoc-ty-ice-1.rs @@ -2,7 +2,7 @@ #![feature(generic_const_exprs)] #![allow(incomplete_features)] -// This tests that the `conservative_is_privately_uninhabited` fn doesn't cause +// This tests that the inhabited check doesn't cause // ICEs by trying to evaluate `T::ASSOC` with an incorrect `ParamEnv`. trait Foo { diff --git a/src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-2.rs b/src/test/ui/const-generics/inhabited-assoc-ty-ice-2.rs similarity index 82% rename from src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-2.rs rename to src/test/ui/const-generics/inhabited-assoc-ty-ice-2.rs index 3017920fc98..216d29c7cd4 100644 --- a/src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-2.rs +++ b/src/test/ui/const-generics/inhabited-assoc-ty-ice-2.rs @@ -2,7 +2,7 @@ #![feature(generic_const_exprs)] #![allow(incomplete_features)] -// This tests that the `conservative_is_privately_uninhabited` fn doesn't cause +// This tests that the inhabited check doesn't cause // ICEs by trying to evaluate `T::ASSOC` with an incorrect `ParamEnv`. trait Foo {