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