1 pub use self::def_id_forest
::DefIdForest
;
4 use crate::ty
::context
::TyCtxt
;
5 use crate::ty
::{AdtDef, FieldDef, Ty, VariantDef}
;
6 use crate::ty
::{AdtKind, Visibility}
;
7 use crate::ty
::{DefId, SubstsRef}
;
9 use rustc_type_ir
::sty
::TyKind
::*;
13 // The methods in this module calculate `DefIdForest`s of modules in which an
14 // `AdtDef`/`VariantDef`/`FieldDef` is visibly uninhabited.
21 // pub struct SecretlyUninhabited {
28 // pub struct AlsoSecretlyUninhabited {
36 // x: a::b::SecretlyUninhabited,
37 // y: c::AlsoSecretlyUninhabited,
40 // In this code, the type `Foo` will only be visibly uninhabited inside the
41 // modules `b`, `c` and `d`. Calling `uninhabited_from` on `Foo` or its `AdtDef` will
42 // return the forest of modules {`b`, `c`->`d`} (represented in a `DefIdForest` by the
45 // We need this information for pattern-matching on `Foo` or types that contain
50 // let foo_result: Result<T, Foo> = ... ;
51 // let Ok(t) = foo_result;
53 // This code should only compile in modules where the uninhabitedness of `Foo` is
56 impl<'tcx
> TyCtxt
<'tcx
> {
57 /// Checks whether a type is visibly uninhabited from a particular module.
61 /// #![feature(never_type)]
66 /// pub struct SecretlyUninhabited {
74 /// pub struct AlsoSecretlyUninhabited {
82 /// x: a::b::SecretlyUninhabited,
83 /// y: c::AlsoSecretlyUninhabited,
86 /// In this code, the type `Foo` will only be visibly uninhabited inside the
87 /// modules b, c and d. This effects pattern-matching on `Foo` or types that
91 /// ```ignore (illustrative)
92 /// let foo_result: Result<T, Foo> = ... ;
93 /// let Ok(t) = foo_result;
95 /// This code should only compile in modules where the uninhabitedness of Foo is
97 pub fn is_ty_uninhabited_from(
101 param_env
: ty
::ParamEnv
<'tcx
>,
103 // To check whether this type is uninhabited at all (not just from the
104 // given node), you could check whether the forest is empty.
108 ty
.uninhabited_from(self, param_env
).contains(self, module
)
112 impl<'tcx
> AdtDef
<'tcx
> {
113 /// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited.
117 substs
: SubstsRef
<'tcx
>,
118 param_env
: ty
::ParamEnv
<'tcx
>,
119 ) -> DefIdForest
<'tcx
> {
120 // Non-exhaustive ADTs from other crates are always considered inhabited.
121 if self.is_variant_list_non_exhaustive() && !self.did().is_local() {
124 DefIdForest
::intersection(
128 .map(|v
| v
.uninhabited_from(tcx
, substs
, self.adt_kind(), param_env
)),
134 impl<'tcx
> VariantDef
{
135 /// Calculates the forest of `DefId`s from which this variant is visibly uninhabited.
136 pub fn uninhabited_from(
139 substs
: SubstsRef
<'tcx
>,
141 param_env
: ty
::ParamEnv
<'tcx
>,
142 ) -> DefIdForest
<'tcx
> {
143 let is_enum
= match adt_kind
{
144 // For now, `union`s are never considered uninhabited.
145 // The precise semantics of inhabitedness with respect to unions is currently undecided.
146 AdtKind
::Union
=> return DefIdForest
::empty(),
147 AdtKind
::Enum
=> true,
148 AdtKind
::Struct
=> false,
150 // Non-exhaustive variants from other crates are always considered inhabited.
151 if self.is_field_list_non_exhaustive() && !self.def_id
.is_local() {
156 self.fields
.iter().map(|f
| f
.uninhabited_from(tcx
, substs
, is_enum
, param_env
)),
162 impl<'tcx
> FieldDef
{
163 /// Calculates the forest of `DefId`s from which this field is visibly uninhabited.
167 substs
: SubstsRef
<'tcx
>,
169 param_env
: ty
::ParamEnv
<'tcx
>,
170 ) -> DefIdForest
<'tcx
> {
171 let data_uninhabitedness
= move || self.ty(tcx
, substs
).uninhabited_from(tcx
, param_env
);
172 // FIXME(canndrew): Currently enum fields are (incorrectly) stored with
173 // `Visibility::Invisible` so we need to override `self.vis` if we're
174 // dealing with an enum.
176 data_uninhabitedness()
179 Visibility
::Invisible
=> DefIdForest
::empty(),
180 Visibility
::Restricted(from
) => {
181 let forest
= DefIdForest
::from_id(from
);
182 let iter
= Some(forest
).into_iter().chain(Some(data_uninhabitedness()));
183 DefIdForest
::intersection(tcx
, iter
)
185 Visibility
::Public
=> data_uninhabitedness(),
191 impl<'tcx
> Ty
<'tcx
> {
192 /// Calculates the forest of `DefId`s from which this type is visibly uninhabited.
196 param_env
: ty
::ParamEnv
<'tcx
>,
197 ) -> DefIdForest
<'tcx
> {
198 tcx
.type_uninhabited_from(param_env
.and(self))
202 // Query provider for `type_uninhabited_from`.
203 pub(crate) fn type_uninhabited_from
<'tcx
>(
205 key
: ty
::ParamEnvAnd
<'tcx
, Ty
<'tcx
>>,
206 ) -> DefIdForest
<'tcx
> {
208 let param_env
= key
.param_env
;
210 Adt(def
, substs
) => def
.uninhabited_from(tcx
, substs
, param_env
),
212 Never
=> DefIdForest
::full(),
215 DefIdForest
::union(tcx
, tys
.iter().map(|ty
| ty
.uninhabited_from(tcx
, param_env
)))
218 Array(ty
, len
) => match len
.try_eval_usize(tcx
, param_env
) {
219 Some(0) | None
=> DefIdForest
::empty(),
220 // If the array is definitely non-empty, it's uninhabited if
221 // the type of its elements is uninhabited.
222 Some(1..) => ty
.uninhabited_from(tcx
, param_env
),
225 // References to uninitialised memory are valid for any type, including
226 // uninhabited types, in unsafe code, so we treat all references as
228 // The precise semantics of inhabitedness with respect to references is currently
230 Ref(..) => DefIdForest
::empty(),
232 _
=> DefIdForest
::empty(),