]> git.proxmox.com Git - rustc.git/blame - src/librustc_middle/ty/inhabitedness/mod.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_middle / ty / inhabitedness / mod.rs
CommitLineData
e1599b0c
XL
1pub use self::def_id_forest::DefIdForest;
2
dfeec247 3use crate::ty;
9fa01778 4use crate::ty::context::TyCtxt;
9fa01778 5use crate::ty::TyKind::*;
dfeec247
XL
6use crate::ty::{AdtDef, FieldDef, Ty, TyS, VariantDef};
7use crate::ty::{AdtKind, Visibility};
8use crate::ty::{DefId, SubstsRef};
f9f354fc 9use rustc_data_structures::stack::ensure_sufficient_stack;
32a655c1 10
32a655c1
SL
11mod def_id_forest;
12
e1599b0c
XL
13// The methods in this module calculate `DefIdForest`s of modules in which a
14// `AdtDef`/`VariantDef`/`FieldDef` is visibly uninhabited.
32a655c1
SL
15//
16// # Example
17// ```rust
18// enum Void {}
19// mod a {
20// pub mod b {
21// pub struct SecretlyUninhabited {
22// _priv: !,
23// }
24// }
25// }
26//
27// mod c {
28// pub struct AlsoSecretlyUninhabited {
29// _priv: Void,
30// }
31// mod d {
32// }
33// }
34//
35// struct Foo {
36// x: a::b::SecretlyUninhabited,
37// y: c::AlsoSecretlyUninhabited,
38// }
39// ```
e1599b0c
XL
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
43// set {`b`, `c`}).
32a655c1 44//
e1599b0c
XL
45// We need this information for pattern-matching on `Foo` or types that contain
46// `Foo`.
32a655c1
SL
47//
48// # Example
49// ```rust
50// let foo_result: Result<T, Foo> = ... ;
51// let Ok(t) = foo_result;
52// ```
e1599b0c 53// This code should only compile in modules where the uninhabitedness of `Foo` is
32a655c1
SL
54// visible.
55
dc9dc135 56impl<'tcx> TyCtxt<'tcx> {
abe05a73 57 /// Checks whether a type is visibly uninhabited from a particular module.
e1599b0c 58 ///
abe05a73
XL
59 /// # Example
60 /// ```rust
61 /// enum Void {}
62 /// mod a {
63 /// pub mod b {
64 /// pub struct SecretlyUninhabited {
65 /// _priv: !,
66 /// }
67 /// }
68 /// }
69 ///
70 /// mod c {
71 /// pub struct AlsoSecretlyUninhabited {
72 /// _priv: Void,
73 /// }
74 /// mod d {
75 /// }
76 /// }
77 ///
78 /// struct Foo {
79 /// x: a::b::SecretlyUninhabited,
80 /// y: c::AlsoSecretlyUninhabited,
81 /// }
82 /// ```
83 /// In this code, the type `Foo` will only be visibly uninhabited inside the
84 /// modules b, c and d. This effects pattern-matching on `Foo` or types that
85 /// contain `Foo`.
86 ///
87 /// # Example
88 /// ```rust
89 /// let foo_result: Result<T, Foo> = ... ;
90 /// let Ok(t) = foo_result;
91 /// ```
92 /// This code should only compile in modules where the uninhabitedness of Foo is
93 /// visible.
ba9703b0
XL
94 pub fn is_ty_uninhabited_from(
95 self,
96 module: DefId,
97 ty: Ty<'tcx>,
98 param_env: ty::ParamEnv<'tcx>,
99 ) -> bool {
abe05a73 100 // To check whether this type is uninhabited at all (not just from the
e1599b0c 101 // given node), you could check whether the forest is empty.
abe05a73
XL
102 // ```
103 // forest.is_empty()
104 // ```
ba9703b0 105 ty.uninhabited_from(self, param_env).contains(self, module)
abe05a73
XL
106 }
107
ba9703b0
XL
108 pub fn is_ty_uninhabited_from_any_module(
109 self,
110 ty: Ty<'tcx>,
111 param_env: ty::ParamEnv<'tcx>,
112 ) -> bool {
113 !ty.uninhabited_from(self, param_env).is_empty()
abe05a73 114 }
abe05a73
XL
115}
116
dc9dc135 117impl<'tcx> AdtDef {
e1599b0c 118 /// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited.
ba9703b0
XL
119 fn uninhabited_from(
120 &self,
121 tcx: TyCtxt<'tcx>,
122 substs: SubstsRef<'tcx>,
123 param_env: ty::ParamEnv<'tcx>,
124 ) -> DefIdForest {
48663c56
XL
125 // Non-exhaustive ADTs from other crates are always considered inhabited.
126 if self.is_variant_list_non_exhaustive() && !self.did.is_local() {
127 DefIdForest::empty()
128 } else {
dfeec247
XL
129 DefIdForest::intersection(
130 tcx,
ba9703b0
XL
131 self.variants
132 .iter()
133 .map(|v| v.uninhabited_from(tcx, substs, self.adt_kind(), param_env)),
dfeec247 134 )
48663c56 135 }
32a655c1
SL
136 }
137}
138
dc9dc135 139impl<'tcx> VariantDef {
e1599b0c 140 /// Calculates the forest of `DefId`s from which this variant is visibly uninhabited.
532ac7d7 141 pub fn uninhabited_from(
abe05a73 142 &self,
dc9dc135 143 tcx: TyCtxt<'tcx>,
532ac7d7 144 substs: SubstsRef<'tcx>,
dc9dc135 145 adt_kind: AdtKind,
ba9703b0 146 param_env: ty::ParamEnv<'tcx>,
dc9dc135 147 ) -> DefIdForest {
a1dfa0c6
XL
148 let is_enum = match adt_kind {
149 // For now, `union`s are never considered uninhabited.
150 // The precise semantics of inhabitedness with respect to unions is currently undecided.
151 AdtKind::Union => return DefIdForest::empty(),
152 AdtKind::Enum => true,
153 AdtKind::Struct => false,
154 };
48663c56
XL
155 // Non-exhaustive variants from other crates are always considered inhabited.
156 if self.is_field_list_non_exhaustive() && !self.def_id.is_local() {
157 DefIdForest::empty()
158 } else {
dfeec247
XL
159 DefIdForest::union(
160 tcx,
ba9703b0 161 self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum, param_env)),
dfeec247 162 )
48663c56 163 }
32a655c1
SL
164 }
165}
166
dc9dc135 167impl<'tcx> FieldDef {
e1599b0c 168 /// Calculates the forest of `DefId`s from which this field is visibly uninhabited.
abe05a73
XL
169 fn uninhabited_from(
170 &self,
dc9dc135 171 tcx: TyCtxt<'tcx>,
532ac7d7 172 substs: SubstsRef<'tcx>,
a1dfa0c6 173 is_enum: bool,
ba9703b0 174 param_env: ty::ParamEnv<'tcx>,
a1dfa0c6 175 ) -> DefIdForest {
ba9703b0 176 let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx, param_env);
32a655c1 177 // FIXME(canndrew): Currently enum fields are (incorrectly) stored with
e1599b0c 178 // `Visibility::Invisible` so we need to override `self.vis` if we're
32a655c1
SL
179 // dealing with an enum.
180 if is_enum {
181 data_uninhabitedness()
182 } else {
183 match self.vis {
184 Visibility::Invisible => DefIdForest::empty(),
185 Visibility::Restricted(from) => {
186 let forest = DefIdForest::from_id(from);
187 let iter = Some(forest).into_iter().chain(Some(data_uninhabitedness()));
188 DefIdForest::intersection(tcx, iter)
dfeec247 189 }
32a655c1
SL
190 Visibility::Public => data_uninhabitedness(),
191 }
192 }
193 }
194}
195
dc9dc135 196impl<'tcx> TyS<'tcx> {
e1599b0c 197 /// Calculates the forest of `DefId`s from which this type is visibly uninhabited.
ba9703b0 198 fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> DefIdForest {
e74abb32 199 match self.kind {
f9f354fc
XL
200 Adt(def, substs) => {
201 ensure_sufficient_stack(|| def.uninhabited_from(tcx, substs, param_env))
202 }
32a655c1 203
b7449926 204 Never => DefIdForest::full(tcx),
a1dfa0c6 205
ba9703b0
XL
206 Tuple(ref tys) => DefIdForest::union(
207 tcx,
208 tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx, param_env)),
209 ),
a1dfa0c6 210
ba9703b0 211 Array(ty, len) => match len.try_eval_usize(tcx, param_env) {
532ac7d7
XL
212 // If the array is definitely non-empty, it's uninhabited if
213 // the type of its elements is uninhabited.
ba9703b0 214 Some(n) if n != 0 => ty.uninhabited_from(tcx, param_env),
dfeec247 215 _ => DefIdForest::empty(),
532ac7d7 216 },
a1dfa0c6
XL
217
218 // References to uninitialised memory is valid for any type, including
219 // uninhabited types, in unsafe code, so we treat all references as
220 // inhabited.
221 // The precise semantics of inhabitedness with respect to references is currently
222 // undecided.
223 Ref(..) => DefIdForest::empty(),
32a655c1
SL
224
225 _ => DefIdForest::empty(),
226 }
227 }
228}