mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 23:12:02 +00:00
Factor out conservative_is_privately_uninhabited
This commit is contained in:
parent
34cbe72780
commit
cc8dddbac9
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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" }
|
||||
}
|
||||
|
@ -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<E>(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
@ -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`
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 }
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
@ -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 {
|
@ -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 {
|
Loading…
Reference in New Issue
Block a user