summary refs log tree commit diff
path: root/compiler/rustc_ty_utils/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-02-24 21:54:52 +0000
committerbors <bors@rust-lang.org>2021-02-24 21:54:52 +0000
commit1fdadbf13aecd190b277ea2aa1b125d2ed986d55 (patch)
treeaeafe7efa86c189ea34cda3ef8d91720d51cd24d /compiler/rustc_ty_utils/src
parenta8486b64b0c87dabd045453b6c81500015d122d6 (diff)
parent42cbfd63460a752ec5e57e88a180d7e3268521a9 (diff)
downloadrust-1fdadbf13aecd190b277ea2aa1b125d2ed986d55.tar.gz
rust-1fdadbf13aecd190b277ea2aa1b125d2ed986d55.zip
Auto merge of #82159 - BoxyUwU:uwu, r=varkor
Use correct param_env in conservative_is_privately_uninhabited

cc `@lcnr`
r? `@varkor` since this is your FIXME that was removed ^^
Diffstat (limited to 'compiler/rustc_ty_utils/src')
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs2
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs58
2 files changed, 60 insertions, 0 deletions
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 904c0062a92..aa5d3388401 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -5,6 +5,8 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
 #![feature(nll)]
 #![recursion_limit = "256"]
 
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 76d27c29226..29f1761b84d 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -481,6 +481,63 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
     fn_like.asyncness()
 }
 
+/// Don't call this directly: use ``tcx.conservative_is_privately_uninhabited`` instead.
+#[instrument(level = "debug", skip(tcx))]
+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.type_of(field.did).subst(tcx, substs);
+                    tcx.conservative_is_privately_uninhabited(param_env.and(ty))
+                })
+            })
+        }
+        ty::Tuple(..) => {
+            debug!("ty::Tuple(..) =>");
+            ty.tuple_fields().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,
@@ -498,6 +555,7 @@ 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
     };
 }