diff options
| author | bors <bors@rust-lang.org> | 2021-02-24 21:54:52 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-02-24 21:54:52 +0000 |
| commit | 1fdadbf13aecd190b277ea2aa1b125d2ed986d55 (patch) | |
| tree | aeafe7efa86c189ea34cda3ef8d91720d51cd24d /compiler/rustc_ty_utils/src | |
| parent | a8486b64b0c87dabd045453b6c81500015d122d6 (diff) | |
| parent | 42cbfd63460a752ec5e57e88a180d7e3268521a9 (diff) | |
| download | rust-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.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/ty.rs | 58 |
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 }; } |
