]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
e9174d1e | 11 | pub use self::Variance::*; |
476ff2be | 12 | pub use self::AssociatedItemContainer::*; |
e9174d1e | 13 | pub use self::BorrowKind::*; |
e9174d1e | 14 | pub use self::IntVarValue::*; |
9cc50fc6 | 15 | pub use self::fold::TypeFoldable; |
e9174d1e | 16 | |
32a655c1 | 17 | use hir::{map as hir_map, FreevarMap, TraitMap}; |
476ff2be | 18 | use hir::def::{Def, CtorKind, ExportMap}; |
2c00a5a8 | 19 | use hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; |
abe05a73 | 20 | use hir::map::DefPathData; |
ff7c6d11 | 21 | use hir::svh::Svh; |
2c00a5a8 | 22 | use ich::Fingerprint; |
cc61c64b | 23 | use ich::StableHashingContext; |
8faf50e0 | 24 | use infer::canonical::Canonical; |
e9174d1e | 25 | use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; |
cc61c64b | 26 | use middle::privacy::AccessLevels; |
8bb4bdeb | 27 | use middle::resolve_lifetime::ObjectLifetimeDefault; |
c30ab7b3 | 28 | use mir::Mir; |
94b46f34 | 29 | use mir::interpret::GlobalId; |
ea8adc8c | 30 | use mir::GeneratorLayout; |
abe05a73 | 31 | use session::CrateDisambiguator; |
0531ce1d | 32 | use traits::{self, Reveal}; |
54a0048b | 33 | use ty; |
9e0c209e | 34 | use ty::subst::{Subst, Substs}; |
0531ce1d | 35 | use ty::util::{IntTypeExt, Discr}; |
54a0048b | 36 | use ty::walk::TypeWalker; |
0531ce1d XL |
37 | use util::captures::Captures; |
38 | use util::nodemap::{NodeSet, DefIdMap, FxHashMap}; | |
94b46f34 | 39 | use arena::SyncDroplessArena; |
e9174d1e | 40 | |
9e0c209e | 41 | use serialize::{self, Encodable, Encoder}; |
2c00a5a8 | 42 | use std::cell::RefCell; |
94b46f34 | 43 | use std::cmp::{self, Ordering}; |
7cac9316 | 44 | use std::fmt; |
e9174d1e | 45 | use std::hash::{Hash, Hasher}; |
9e0c209e | 46 | use std::ops::Deref; |
94b46f34 | 47 | use rustc_data_structures::sync::{self, Lrc, ParallelIterator, par_iter}; |
e9174d1e SL |
48 | use std::slice; |
49 | use std::vec::IntoIter; | |
8faf50e0 | 50 | use std::{mem, ptr}; |
7cac9316 | 51 | use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId}; |
9e0c209e | 52 | use syntax::attr; |
83c7162d XL |
53 | use syntax::ext::hygiene::Mark; |
54 | use syntax::symbol::{Symbol, LocalInternedString, InternedString}; | |
3157f602 | 55 | use syntax_pos::{DUMMY_SP, Span}; |
8bb4bdeb | 56 | |
476ff2be | 57 | use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter; |
cc61c64b XL |
58 | use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, |
59 | HashStable}; | |
54a0048b SL |
60 | |
61 | use hir; | |
e9174d1e | 62 | |
94b46f34 | 63 | pub use self::sty::{Binder, CanonicalVar, DebruijnIndex, INNERMOST}; |
ea8adc8c | 64 | pub use self::sty::{FnSig, GenSig, PolyFnSig, PolyGenSig}; |
8bb4bdeb | 65 | pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; |
94b46f34 | 66 | pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut}; |
e9174d1e | 67 | pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef}; |
9e0c209e | 68 | pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef}; |
ea8adc8c | 69 | pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const}; |
e9174d1e | 70 | pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region}; |
7cac9316 | 71 | pub use self::sty::RegionKind; |
83c7162d | 72 | pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid}; |
e9174d1e | 73 | pub use self::sty::BoundRegion::*; |
e9174d1e | 74 | pub use self::sty::InferTy::*; |
7cac9316 | 75 | pub use self::sty::RegionKind::*; |
e9174d1e SL |
76 | pub use self::sty::TypeVariants::*; |
77 | ||
3b2f2976 XL |
78 | pub use self::binding::BindingMode; |
79 | pub use self::binding::BindingMode::*; | |
80 | ||
ff7c6d11 | 81 | pub use self::context::{TyCtxt, GlobalArenas, AllArenas, tls, keep_local}; |
94b46f34 | 82 | pub use self::context::{Lift, TypeckTables}; |
e9174d1e | 83 | |
cc61c64b XL |
84 | pub use self::instance::{Instance, InstanceDef}; |
85 | ||
7cac9316 | 86 | pub use self::trait_def::TraitDef; |
9cc50fc6 | 87 | |
94b46f34 | 88 | pub use self::query::queries; |
8bb4bdeb | 89 | |
e9174d1e | 90 | pub mod adjustment; |
3b2f2976 | 91 | pub mod binding; |
e9174d1e | 92 | pub mod cast; |
abe05a73 XL |
93 | #[macro_use] |
94 | pub mod codec; | |
e9174d1e | 95 | pub mod error; |
abe05a73 | 96 | mod erase_regions; |
e9174d1e SL |
97 | pub mod fast_reject; |
98 | pub mod fold; | |
32a655c1 | 99 | pub mod inhabitedness; |
54a0048b SL |
100 | pub mod item_path; |
101 | pub mod layout; | |
e9174d1e SL |
102 | pub mod _match; |
103 | pub mod outlives; | |
94b46f34 | 104 | pub mod query; |
e9174d1e | 105 | pub mod relate; |
7cac9316 | 106 | pub mod steal; |
54a0048b | 107 | pub mod subst; |
9cc50fc6 | 108 | pub mod trait_def; |
e9174d1e SL |
109 | pub mod walk; |
110 | pub mod wf; | |
111 | pub mod util; | |
112 | ||
e9174d1e SL |
113 | mod context; |
114 | mod flags; | |
cc61c64b | 115 | mod instance; |
e9174d1e SL |
116 | mod structural_impls; |
117 | mod sty; | |
118 | ||
e9174d1e SL |
119 | // Data types |
120 | ||
121 | /// The complete set of all analyses described in this module. This is | |
94b46f34 | 122 | /// produced by the driver and fed to codegen and later passes. |
cc61c64b XL |
123 | /// |
124 | /// NB: These contents are being migrated into queries using the | |
125 | /// *on-demand* infrastructure. | |
a7813a04 | 126 | #[derive(Clone)] |
8bb4bdeb | 127 | pub struct CrateAnalysis { |
0531ce1d | 128 | pub access_levels: Lrc<AccessLevels>, |
476ff2be | 129 | pub name: String, |
54a0048b | 130 | pub glob_map: Option<hir::GlobMap>, |
e9174d1e SL |
131 | } |
132 | ||
32a655c1 SL |
133 | #[derive(Clone)] |
134 | pub struct Resolutions { | |
135 | pub freevars: FreevarMap, | |
136 | pub trait_map: TraitMap, | |
137 | pub maybe_unused_trait_imports: NodeSet, | |
3b2f2976 | 138 | pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, |
cc61c64b | 139 | pub export_map: ExportMap, |
e9174d1e SL |
140 | } |
141 | ||
142 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] | |
476ff2be | 143 | pub enum AssociatedItemContainer { |
e9174d1e SL |
144 | TraitContainer(DefId), |
145 | ImplContainer(DefId), | |
146 | } | |
147 | ||
476ff2be | 148 | impl AssociatedItemContainer { |
abe05a73 XL |
149 | /// Asserts that this is the def-id of an associated item declared |
150 | /// in a trait, and returns the trait def-id. | |
151 | pub fn assert_trait(&self) -> DefId { | |
152 | match *self { | |
153 | TraitContainer(id) => id, | |
154 | _ => bug!("associated item has wrong container type: {:?}", self) | |
155 | } | |
156 | } | |
157 | ||
e9174d1e SL |
158 | pub fn id(&self) -> DefId { |
159 | match *self { | |
160 | TraitContainer(id) => id, | |
161 | ImplContainer(id) => id, | |
162 | } | |
163 | } | |
164 | } | |
165 | ||
54a0048b SL |
166 | /// The "header" of an impl is everything outside the body: a Self type, a trait |
167 | /// ref (in the case of a trait impl), and a set of predicates (from the | |
168 | /// bounds/where clauses). | |
169 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | |
170 | pub struct ImplHeader<'tcx> { | |
171 | pub impl_def_id: DefId, | |
172 | pub self_ty: Ty<'tcx>, | |
173 | pub trait_ref: Option<TraitRef<'tcx>>, | |
174 | pub predicates: Vec<Predicate<'tcx>>, | |
175 | } | |
176 | ||
8faf50e0 | 177 | #[derive(Copy, Clone, Debug, PartialEq)] |
476ff2be SL |
178 | pub struct AssociatedItem { |
179 | pub def_id: DefId, | |
8faf50e0 | 180 | pub ident: Ident, |
476ff2be SL |
181 | pub kind: AssociatedKind, |
182 | pub vis: Visibility, | |
183 | pub defaultness: hir::Defaultness, | |
184 | pub container: AssociatedItemContainer, | |
e9174d1e | 185 | |
476ff2be SL |
186 | /// Whether this is a method with an explicit self |
187 | /// as its first argument, allowing method calls. | |
188 | pub method_has_self_argument: bool, | |
189 | } | |
e9174d1e | 190 | |
3b2f2976 | 191 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, RustcEncodable, RustcDecodable)] |
476ff2be SL |
192 | pub enum AssociatedKind { |
193 | Const, | |
194 | Method, | |
8faf50e0 | 195 | Existential, |
476ff2be SL |
196 | Type |
197 | } | |
e9174d1e | 198 | |
476ff2be SL |
199 | impl AssociatedItem { |
200 | pub fn def(&self) -> Def { | |
201 | match self.kind { | |
202 | AssociatedKind::Const => Def::AssociatedConst(self.def_id), | |
203 | AssociatedKind::Method => Def::Method(self.def_id), | |
204 | AssociatedKind::Type => Def::AssociatedTy(self.def_id), | |
8faf50e0 | 205 | AssociatedKind::Existential => Def::AssociatedExistential(self.def_id), |
e9174d1e SL |
206 | } |
207 | } | |
8bb4bdeb XL |
208 | |
209 | /// Tests whether the associated item admits a non-trivial implementation | |
210 | /// for ! | |
211 | pub fn relevant_for_never<'tcx>(&self) -> bool { | |
212 | match self.kind { | |
8faf50e0 XL |
213 | AssociatedKind::Existential | |
214 | AssociatedKind::Const | | |
8bb4bdeb XL |
215 | AssociatedKind::Type => true, |
216 | // FIXME(canndrew): Be more thorough here, check if any argument is uninhabited. | |
217 | AssociatedKind::Method => !self.method_has_self_argument, | |
218 | } | |
219 | } | |
7cac9316 XL |
220 | |
221 | pub fn signature<'a, 'tcx>(&self, tcx: &TyCtxt<'a, 'tcx, 'tcx>) -> String { | |
222 | match self.kind { | |
223 | ty::AssociatedKind::Method => { | |
224 | // We skip the binder here because the binder would deanonymize all | |
225 | // late-bound regions, and we don't want method signatures to show up | |
226 | // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound | |
227 | // regions just fine, showing `fn(&MyType)`. | |
8faf50e0 | 228 | tcx.fn_sig(self.def_id).skip_binder().to_string() |
7cac9316 | 229 | } |
8faf50e0 XL |
230 | ty::AssociatedKind::Type => format!("type {};", self.ident), |
231 | ty::AssociatedKind::Existential => format!("existential type {};", self.ident), | |
7cac9316 | 232 | ty::AssociatedKind::Const => { |
8faf50e0 | 233 | format!("const {}: {:?};", self.ident, tcx.type_of(self.def_id)) |
7cac9316 XL |
234 | } |
235 | } | |
236 | } | |
e9174d1e SL |
237 | } |
238 | ||
9e0c209e | 239 | #[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable)] |
54a0048b SL |
240 | pub enum Visibility { |
241 | /// Visible everywhere (including in other crates). | |
242 | Public, | |
243 | /// Visible only in the given crate-local module. | |
32a655c1 | 244 | Restricted(DefId), |
54a0048b | 245 | /// Not visible anywhere in the local crate. This is the visibility of private external items. |
32a655c1 | 246 | Invisible, |
54a0048b SL |
247 | } |
248 | ||
32a655c1 SL |
249 | pub trait DefIdTree: Copy { |
250 | fn parent(self, id: DefId) -> Option<DefId>; | |
a7813a04 | 251 | |
32a655c1 SL |
252 | fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool { |
253 | if descendant.krate != ancestor.krate { | |
254 | return false; | |
255 | } | |
256 | ||
257 | while descendant != ancestor { | |
258 | match self.parent(descendant) { | |
259 | Some(parent) => descendant = parent, | |
260 | None => return false, | |
a7813a04 | 261 | } |
a7813a04 XL |
262 | } |
263 | true | |
264 | } | |
265 | } | |
266 | ||
32a655c1 SL |
267 | impl<'a, 'gcx, 'tcx> DefIdTree for TyCtxt<'a, 'gcx, 'tcx> { |
268 | fn parent(self, id: DefId) -> Option<DefId> { | |
269 | self.def_key(id).parent.map(|index| DefId { index: index, ..id }) | |
270 | } | |
271 | } | |
272 | ||
54a0048b | 273 | impl Visibility { |
a7813a04 | 274 | pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt) -> Self { |
8faf50e0 XL |
275 | match visibility.node { |
276 | hir::VisibilityKind::Public => Visibility::Public, | |
277 | hir::VisibilityKind::Crate(_) => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)), | |
278 | hir::VisibilityKind::Restricted { ref path, .. } => match path.def { | |
a7813a04 XL |
279 | // If there is no resolution, `resolve` will have already reported an error, so |
280 | // assume that the visibility is public to avoid reporting more privacy errors. | |
3157f602 | 281 | Def::Err => Visibility::Public, |
32a655c1 | 282 | def => Visibility::Restricted(def.def_id()), |
a7813a04 | 283 | }, |
8faf50e0 | 284 | hir::VisibilityKind::Inherited => { |
7cac9316 | 285 | Visibility::Restricted(tcx.hir.get_module_parent(id)) |
32a655c1 | 286 | } |
54a0048b SL |
287 | } |
288 | } | |
289 | ||
290 | /// Returns true if an item with this visibility is accessible from the given block. | |
32a655c1 | 291 | pub fn is_accessible_from<T: DefIdTree>(self, module: DefId, tree: T) -> bool { |
54a0048b SL |
292 | let restriction = match self { |
293 | // Public items are visible everywhere. | |
294 | Visibility::Public => return true, | |
295 | // Private items from other crates are visible nowhere. | |
32a655c1 | 296 | Visibility::Invisible => return false, |
54a0048b | 297 | // Restricted items are visible in an arbitrary local module. |
32a655c1 | 298 | Visibility::Restricted(other) if other.krate != module.krate => return false, |
54a0048b SL |
299 | Visibility::Restricted(module) => module, |
300 | }; | |
301 | ||
32a655c1 | 302 | tree.is_descendant_of(module, restriction) |
54a0048b SL |
303 | } |
304 | ||
305 | /// Returns true if this visibility is at least as accessible as the given visibility | |
32a655c1 | 306 | pub fn is_at_least<T: DefIdTree>(self, vis: Visibility, tree: T) -> bool { |
54a0048b SL |
307 | let vis_restriction = match vis { |
308 | Visibility::Public => return self == Visibility::Public, | |
32a655c1 | 309 | Visibility::Invisible => return true, |
54a0048b SL |
310 | Visibility::Restricted(module) => module, |
311 | }; | |
312 | ||
a7813a04 | 313 | self.is_accessible_from(vis_restriction, tree) |
54a0048b | 314 | } |
ff7c6d11 XL |
315 | |
316 | // Returns true if this item is visible anywhere in the local crate. | |
317 | pub fn is_visible_locally(self) -> bool { | |
318 | match self { | |
319 | Visibility::Public => true, | |
320 | Visibility::Restricted(def_id) => def_id.is_local(), | |
321 | Visibility::Invisible => false, | |
322 | } | |
323 | } | |
54a0048b SL |
324 | } |
325 | ||
e9174d1e SL |
326 | #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)] |
327 | pub enum Variance { | |
328 | Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type | |
329 | Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell | |
330 | Contravariant, // T<A> <: T<B> iff B <: A -- e.g., function param type | |
331 | Bivariant, // T<A> <: T<B> -- e.g., unused type parameter | |
332 | } | |
333 | ||
7cac9316 XL |
334 | /// The crate variances map is computed during typeck and contains the |
335 | /// variance of every item in the local crate. You should not use it | |
336 | /// directly, because to do so will make your pass dependent on the | |
337 | /// HIR of every item in the local crate. Instead, use | |
338 | /// `tcx.variances_of()` to get the variance for a *particular* | |
339 | /// item. | |
340 | pub struct CrateVariancesMap { | |
7cac9316 XL |
341 | /// For each item with generics, maps to a vector of the variance |
342 | /// of its generics. If an item has no generics, it will have no | |
343 | /// entry. | |
0531ce1d | 344 | pub variances: FxHashMap<DefId, Lrc<Vec<ty::Variance>>>, |
7cac9316 XL |
345 | |
346 | /// An empty vector, useful for cloning. | |
0531ce1d | 347 | pub empty_variance: Lrc<Vec<ty::Variance>>, |
7cac9316 XL |
348 | } |
349 | ||
cc61c64b XL |
350 | impl Variance { |
351 | /// `a.xform(b)` combines the variance of a context with the | |
352 | /// variance of a type with the following meaning. If we are in a | |
353 | /// context with variance `a`, and we encounter a type argument in | |
354 | /// a position with variance `b`, then `a.xform(b)` is the new | |
355 | /// variance with which the argument appears. | |
356 | /// | |
357 | /// Example 1: | |
358 | /// | |
359 | /// *mut Vec<i32> | |
360 | /// | |
361 | /// Here, the "ambient" variance starts as covariant. `*mut T` is | |
362 | /// invariant with respect to `T`, so the variance in which the | |
363 | /// `Vec<i32>` appears is `Covariant.xform(Invariant)`, which | |
364 | /// yields `Invariant`. Now, the type `Vec<T>` is covariant with | |
365 | /// respect to its type argument `T`, and hence the variance of | |
366 | /// the `i32` here is `Invariant.xform(Covariant)`, which results | |
367 | /// (again) in `Invariant`. | |
368 | /// | |
369 | /// Example 2: | |
370 | /// | |
371 | /// fn(*const Vec<i32>, *mut Vec<i32) | |
372 | /// | |
373 | /// The ambient variance is covariant. A `fn` type is | |
374 | /// contravariant with respect to its parameters, so the variance | |
375 | /// within which both pointer types appear is | |
376 | /// `Covariant.xform(Contravariant)`, or `Contravariant`. `*const | |
377 | /// T` is covariant with respect to `T`, so the variance within | |
378 | /// which the first `Vec<i32>` appears is | |
379 | /// `Contravariant.xform(Covariant)` or `Contravariant`. The same | |
380 | /// is true for its `i32` argument. In the `*mut T` case, the | |
381 | /// variance of `Vec<i32>` is `Contravariant.xform(Invariant)`, | |
382 | /// and hence the outermost type is `Invariant` with respect to | |
383 | /// `Vec<i32>` (and its `i32` argument). | |
384 | /// | |
385 | /// Source: Figure 1 of "Taming the Wildcards: | |
386 | /// Combining Definition- and Use-Site Variance" published in PLDI'11. | |
387 | pub fn xform(self, v: ty::Variance) -> ty::Variance { | |
388 | match (self, v) { | |
389 | // Figure 1, column 1. | |
390 | (ty::Covariant, ty::Covariant) => ty::Covariant, | |
391 | (ty::Covariant, ty::Contravariant) => ty::Contravariant, | |
392 | (ty::Covariant, ty::Invariant) => ty::Invariant, | |
393 | (ty::Covariant, ty::Bivariant) => ty::Bivariant, | |
394 | ||
395 | // Figure 1, column 2. | |
396 | (ty::Contravariant, ty::Covariant) => ty::Contravariant, | |
397 | (ty::Contravariant, ty::Contravariant) => ty::Covariant, | |
398 | (ty::Contravariant, ty::Invariant) => ty::Invariant, | |
399 | (ty::Contravariant, ty::Bivariant) => ty::Bivariant, | |
400 | ||
401 | // Figure 1, column 3. | |
402 | (ty::Invariant, _) => ty::Invariant, | |
403 | ||
404 | // Figure 1, column 4. | |
405 | (ty::Bivariant, _) => ty::Bivariant, | |
406 | } | |
407 | } | |
408 | } | |
409 | ||
e9174d1e SL |
410 | // Contains information needed to resolve types and (in the future) look up |
411 | // the types of AST nodes. | |
412 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
413 | pub struct CReaderCacheKey { | |
414 | pub cnum: CrateNum, | |
415 | pub pos: usize, | |
e9174d1e SL |
416 | } |
417 | ||
e9174d1e SL |
418 | // Flags that we track on types. These flags are propagated upwards |
419 | // through the type during type construction, so that we can quickly | |
420 | // check whether the type has various kinds of types in it without | |
421 | // recursing over the type itself. | |
422 | bitflags! { | |
ea8adc8c XL |
423 | pub struct TypeFlags: u32 { |
424 | const HAS_PARAMS = 1 << 0; | |
425 | const HAS_SELF = 1 << 1; | |
426 | const HAS_TY_INFER = 1 << 2; | |
427 | const HAS_RE_INFER = 1 << 3; | |
428 | const HAS_RE_SKOL = 1 << 4; | |
ff7c6d11 XL |
429 | |
430 | /// Does this have any `ReEarlyBound` regions? Used to | |
431 | /// determine whether substitition is required, since those | |
432 | /// represent regions that are bound in a `ty::Generics` and | |
433 | /// hence may be substituted. | |
ea8adc8c | 434 | const HAS_RE_EARLY_BOUND = 1 << 5; |
ff7c6d11 XL |
435 | |
436 | /// Does this have any region that "appears free" in the type? | |
437 | /// Basically anything but `ReLateBound` and `ReErased`. | |
ea8adc8c | 438 | const HAS_FREE_REGIONS = 1 << 6; |
ff7c6d11 XL |
439 | |
440 | /// Is an error type reachable? | |
ea8adc8c XL |
441 | const HAS_TY_ERR = 1 << 7; |
442 | const HAS_PROJECTION = 1 << 8; | |
443 | ||
444 | // FIXME: Rename this to the actual property since it's used for generators too | |
445 | const HAS_TY_CLOSURE = 1 << 9; | |
e9174d1e SL |
446 | |
447 | // true if there are "names" of types and regions and so forth | |
448 | // that are local to a particular fn | |
94b46f34 | 449 | const HAS_FREE_LOCAL_NAMES = 1 << 10; |
e9174d1e | 450 | |
a7813a04 XL |
451 | // Present if the type belongs in a local type context. |
452 | // Only set for TyInfer other than Fresh. | |
ea8adc8c | 453 | const KEEP_IN_LOCAL_TCX = 1 << 11; |
a7813a04 | 454 | |
1bb2cb6e SL |
455 | // Is there a projection that does not involve a bound region? |
456 | // Currently we can't normalize projections w/ bound regions. | |
ea8adc8c | 457 | const HAS_NORMALIZABLE_PROJECTION = 1 << 12; |
1bb2cb6e | 458 | |
0531ce1d XL |
459 | // Set if this includes a "canonical" type or region var -- |
460 | // ought to be true only for the results of canonicalization. | |
461 | const HAS_CANONICAL_VARS = 1 << 13; | |
462 | ||
94b46f34 XL |
463 | /// Does this have any `ReLateBound` regions? Used to check |
464 | /// if a global bound is safe to evaluate. | |
465 | const HAS_RE_LATE_BOUND = 1 << 14; | |
466 | ||
e9174d1e SL |
467 | const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | |
468 | TypeFlags::HAS_SELF.bits | | |
ea8adc8c | 469 | TypeFlags::HAS_RE_EARLY_BOUND.bits; |
e9174d1e SL |
470 | |
471 | // Flags representing the nominal content of a type, | |
472 | // computed by FlagsComputation. If you add a new nominal | |
473 | // flag, it should be added here too. | |
474 | const NOMINAL_FLAGS = TypeFlags::HAS_PARAMS.bits | | |
475 | TypeFlags::HAS_SELF.bits | | |
476 | TypeFlags::HAS_TY_INFER.bits | | |
477 | TypeFlags::HAS_RE_INFER.bits | | |
c30ab7b3 | 478 | TypeFlags::HAS_RE_SKOL.bits | |
e9174d1e SL |
479 | TypeFlags::HAS_RE_EARLY_BOUND.bits | |
480 | TypeFlags::HAS_FREE_REGIONS.bits | | |
481 | TypeFlags::HAS_TY_ERR.bits | | |
482 | TypeFlags::HAS_PROJECTION.bits | | |
483 | TypeFlags::HAS_TY_CLOSURE.bits | | |
94b46f34 | 484 | TypeFlags::HAS_FREE_LOCAL_NAMES.bits | |
0531ce1d | 485 | TypeFlags::KEEP_IN_LOCAL_TCX.bits | |
94b46f34 XL |
486 | TypeFlags::HAS_CANONICAL_VARS.bits | |
487 | TypeFlags::HAS_RE_LATE_BOUND.bits; | |
e9174d1e SL |
488 | } |
489 | } | |
490 | ||
491 | pub struct TyS<'tcx> { | |
492 | pub sty: TypeVariants<'tcx>, | |
7cac9316 | 493 | pub flags: TypeFlags, |
e9174d1e | 494 | |
94b46f34 XL |
495 | /// This is a kind of confusing thing: it stores the smallest |
496 | /// binder such that | |
497 | /// | |
498 | /// (a) the binder itself captures nothing but | |
499 | /// (b) all the late-bound things within the type are captured | |
500 | /// by some sub-binder. | |
501 | /// | |
502 | /// So, for a type without any late-bound things, like `u32`, this | |
503 | /// will be INNERMOST, because that is the innermost binder that | |
504 | /// captures nothing. But for a type `&'D u32`, where `'D` is a | |
505 | /// late-bound region with debruijn index D, this would be D+1 -- | |
506 | /// the binder itself does not capture D, but D is captured by an | |
507 | /// inner binder. | |
508 | /// | |
509 | /// We call this concept an "exclusive" binder D (because all | |
510 | /// debruijn indices within the type are contained within `0..D` | |
511 | /// (exclusive)). | |
512 | outer_exclusive_binder: ty::DebruijnIndex, | |
513 | } | |
514 | ||
515 | impl<'tcx> Ord for TyS<'tcx> { | |
516 | fn cmp(&self, other: &TyS<'tcx>) -> Ordering { | |
517 | self.sty.cmp(&other.sty) | |
518 | } | |
519 | } | |
520 | ||
521 | impl<'tcx> PartialOrd for TyS<'tcx> { | |
522 | fn partial_cmp(&self, other: &TyS<'tcx>) -> Option<Ordering> { | |
523 | Some(self.sty.cmp(&other.sty)) | |
524 | } | |
e9174d1e SL |
525 | } |
526 | ||
527 | impl<'tcx> PartialEq for TyS<'tcx> { | |
528 | #[inline] | |
529 | fn eq(&self, other: &TyS<'tcx>) -> bool { | |
8faf50e0 | 530 | ptr::eq(self, other) |
e9174d1e SL |
531 | } |
532 | } | |
533 | impl<'tcx> Eq for TyS<'tcx> {} | |
534 | ||
535 | impl<'tcx> Hash for TyS<'tcx> { | |
536 | fn hash<H: Hasher>(&self, s: &mut H) { | |
537 | (self as *const TyS).hash(s) | |
538 | } | |
539 | } | |
540 | ||
041b39d2 XL |
541 | impl<'tcx> TyS<'tcx> { |
542 | pub fn is_primitive_ty(&self) -> bool { | |
543 | match self.sty { | |
544 | TypeVariants::TyBool | | |
545 | TypeVariants::TyChar | | |
546 | TypeVariants::TyInt(_) | | |
547 | TypeVariants::TyUint(_) | | |
548 | TypeVariants::TyFloat(_) | | |
549 | TypeVariants::TyInfer(InferTy::IntVar(_)) | | |
550 | TypeVariants::TyInfer(InferTy::FloatVar(_)) | | |
551 | TypeVariants::TyInfer(InferTy::FreshIntTy(_)) | | |
552 | TypeVariants::TyInfer(InferTy::FreshFloatTy(_)) => true, | |
94b46f34 | 553 | TypeVariants::TyRef(_, x, _) => x.is_primitive_ty(), |
041b39d2 XL |
554 | _ => false, |
555 | } | |
556 | } | |
557 | ||
558 | pub fn is_suggestable(&self) -> bool { | |
559 | match self.sty { | |
560 | TypeVariants::TyAnon(..) | | |
561 | TypeVariants::TyFnDef(..) | | |
562 | TypeVariants::TyFnPtr(..) | | |
563 | TypeVariants::TyDynamic(..) | | |
564 | TypeVariants::TyClosure(..) | | |
3b2f2976 | 565 | TypeVariants::TyInfer(..) | |
041b39d2 XL |
566 | TypeVariants::TyProjection(..) => false, |
567 | _ => true, | |
568 | } | |
569 | } | |
570 | } | |
571 | ||
0531ce1d | 572 | impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::TyS<'gcx> { |
cc61c64b | 573 | fn hash_stable<W: StableHasherResult>(&self, |
0531ce1d | 574 | hcx: &mut StableHashingContext<'a>, |
cc61c64b XL |
575 | hasher: &mut StableHasher<W>) { |
576 | let ty::TyS { | |
577 | ref sty, | |
578 | ||
579 | // The other fields just provide fast access to information that is | |
580 | // also contained in `sty`, so no need to hash them. | |
581 | flags: _, | |
94b46f34 XL |
582 | |
583 | outer_exclusive_binder: _, | |
cc61c64b XL |
584 | } = *self; |
585 | ||
586 | sty.hash_stable(hcx, hasher); | |
587 | } | |
588 | } | |
589 | ||
e9174d1e SL |
590 | pub type Ty<'tcx> = &'tcx TyS<'tcx>; |
591 | ||
9e0c209e SL |
592 | impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {} |
593 | impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {} | |
594 | ||
0531ce1d XL |
595 | pub type CanonicalTy<'gcx> = Canonical<'gcx, Ty<'gcx>>; |
596 | ||
94b46f34 XL |
597 | extern { |
598 | /// A dummy type used to force Slice to by unsized without requiring fat pointers | |
599 | type OpaqueSliceContents; | |
600 | } | |
601 | ||
c30ab7b3 | 602 | /// A wrapper for slices with the additional invariant |
9e0c209e SL |
603 | /// that the slice is interned and no other slice with |
604 | /// the same contents can exist in the same context. | |
94b46f34 | 605 | /// This means we can use pointer for both |
9e0c209e | 606 | /// equality comparisons and hashing. |
94b46f34 XL |
607 | #[repr(C)] |
608 | pub struct Slice<T> { | |
609 | len: usize, | |
610 | data: [T; 0], | |
611 | opaque: OpaqueSliceContents, | |
612 | } | |
613 | ||
614 | unsafe impl<T: Sync> Sync for Slice<T> {} | |
9e0c209e | 615 | |
94b46f34 XL |
616 | impl<T: Copy> Slice<T> { |
617 | #[inline] | |
618 | fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx Slice<T> { | |
619 | assert!(!mem::needs_drop::<T>()); | |
620 | assert!(mem::size_of::<T>() != 0); | |
621 | assert!(slice.len() != 0); | |
622 | ||
623 | // Align up the size of the len (usize) field | |
624 | let align = mem::align_of::<T>(); | |
625 | let align_mask = align - 1; | |
626 | let offset = mem::size_of::<usize>(); | |
627 | let offset = (offset + align_mask) & !align_mask; | |
628 | ||
629 | let size = offset + slice.len() * mem::size_of::<T>(); | |
630 | ||
631 | let mem = arena.alloc_raw( | |
632 | size, | |
633 | cmp::max(mem::align_of::<T>(), mem::align_of::<usize>())); | |
634 | unsafe { | |
635 | let result = &mut *(mem.as_mut_ptr() as *mut Slice<T>); | |
636 | // Write the length | |
637 | result.len = slice.len(); | |
638 | ||
639 | // Write the elements | |
640 | let arena_slice = slice::from_raw_parts_mut(result.data.as_mut_ptr(), result.len); | |
641 | arena_slice.copy_from_slice(slice); | |
642 | ||
643 | result | |
644 | } | |
645 | } | |
646 | } | |
647 | ||
648 | impl<T: fmt::Debug> fmt::Debug for Slice<T> { | |
649 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
650 | (**self).fmt(f) | |
651 | } | |
652 | } | |
653 | ||
654 | impl<T: Encodable> Encodable for Slice<T> { | |
655 | #[inline] | |
656 | fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { | |
657 | (**self).encode(s) | |
658 | } | |
659 | } | |
660 | ||
661 | impl<T> Ord for Slice<T> where T: Ord { | |
662 | fn cmp(&self, other: &Slice<T>) -> Ordering { | |
663 | if self == other { Ordering::Equal } else { | |
664 | <[T] as Ord>::cmp(&**self, &**other) | |
665 | } | |
666 | } | |
667 | } | |
668 | ||
669 | impl<T> PartialOrd for Slice<T> where T: PartialOrd { | |
670 | fn partial_cmp(&self, other: &Slice<T>) -> Option<Ordering> { | |
671 | if self == other { Some(Ordering::Equal) } else { | |
672 | <[T] as PartialOrd>::partial_cmp(&**self, &**other) | |
673 | } | |
674 | } | |
675 | } | |
676 | ||
677 | impl<T: PartialEq> PartialEq for Slice<T> { | |
9e0c209e SL |
678 | #[inline] |
679 | fn eq(&self, other: &Slice<T>) -> bool { | |
8faf50e0 | 680 | ptr::eq(self, other) |
9cc50fc6 SL |
681 | } |
682 | } | |
94b46f34 | 683 | impl<T: Eq> Eq for Slice<T> {} |
9cc50fc6 | 684 | |
9e0c209e | 685 | impl<T> Hash for Slice<T> { |
94b46f34 | 686 | #[inline] |
9e0c209e | 687 | fn hash<H: Hasher>(&self, s: &mut H) { |
94b46f34 | 688 | (self as *const Slice<T>).hash(s) |
9e0c209e SL |
689 | } |
690 | } | |
691 | ||
692 | impl<T> Deref for Slice<T> { | |
693 | type Target = [T]; | |
94b46f34 | 694 | #[inline(always)] |
9e0c209e | 695 | fn deref(&self) -> &[T] { |
94b46f34 XL |
696 | unsafe { |
697 | slice::from_raw_parts(self.data.as_ptr(), self.len) | |
698 | } | |
9e0c209e SL |
699 | } |
700 | } | |
701 | ||
702 | impl<'a, T> IntoIterator for &'a Slice<T> { | |
703 | type Item = &'a T; | |
704 | type IntoIter = <&'a [T] as IntoIterator>::IntoIter; | |
94b46f34 | 705 | #[inline(always)] |
9e0c209e SL |
706 | fn into_iter(self) -> Self::IntoIter { |
707 | self[..].iter() | |
9cc50fc6 SL |
708 | } |
709 | } | |
710 | ||
9e0c209e | 711 | impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice<Ty<'tcx>> {} |
9cc50fc6 | 712 | |
c30ab7b3 | 713 | impl<T> Slice<T> { |
94b46f34 | 714 | #[inline(always)] |
c30ab7b3 | 715 | pub fn empty<'a>() -> &'a Slice<T> { |
94b46f34 XL |
716 | #[repr(align(64), C)] |
717 | struct EmptySlice([u8; 64]); | |
718 | static EMPTY_SLICE: EmptySlice = EmptySlice([0; 64]); | |
719 | assert!(mem::align_of::<T>() <= 64); | |
c30ab7b3 | 720 | unsafe { |
94b46f34 | 721 | &*(&EMPTY_SLICE as *const _ as *const Slice<T>) |
c30ab7b3 SL |
722 | } |
723 | } | |
724 | } | |
725 | ||
e9174d1e SL |
726 | /// Upvars do not get their own node-id. Instead, we use the pair of |
727 | /// the original var id (that is, the root variable that is referenced | |
728 | /// by the upvar) and the id of the closure expression. | |
32a655c1 | 729 | #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e | 730 | pub struct UpvarId { |
ea8adc8c | 731 | pub var_id: hir::HirId, |
abe05a73 | 732 | pub closure_expr_id: LocalDefId, |
e9174d1e SL |
733 | } |
734 | ||
735 | #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, Copy)] | |
736 | pub enum BorrowKind { | |
737 | /// Data must be immutable and is aliasable. | |
738 | ImmBorrow, | |
739 | ||
740 | /// Data must be immutable but not aliasable. This kind of borrow | |
741 | /// cannot currently be expressed by the user and is used only in | |
32a655c1 | 742 | /// implicit closure bindings. It is needed when the closure |
e9174d1e SL |
743 | /// is borrowing or mutating a mutable referent, e.g.: |
744 | /// | |
745 | /// let x: &mut isize = ...; | |
746 | /// let y = || *x += 5; | |
747 | /// | |
748 | /// If we were to try to translate this closure into a more explicit | |
749 | /// form, we'd encounter an error with the code as written: | |
750 | /// | |
751 | /// struct Env { x: & &mut isize } | |
752 | /// let x: &mut isize = ...; | |
753 | /// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn | |
754 | /// fn fn_ptr(env: &mut Env) { **env.x += 5; } | |
755 | /// | |
756 | /// This is then illegal because you cannot mutate a `&mut` found | |
757 | /// in an aliasable location. To solve, you'd have to translate with | |
758 | /// an `&mut` borrow: | |
759 | /// | |
760 | /// struct Env { x: & &mut isize } | |
761 | /// let x: &mut isize = ...; | |
762 | /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x | |
763 | /// fn fn_ptr(env: &mut Env) { **env.x += 5; } | |
764 | /// | |
765 | /// Now the assignment to `**env.x` is legal, but creating a | |
766 | /// mutable pointer to `x` is not because `x` is not mutable. We | |
767 | /// could fix this by declaring `x` as `let mut x`. This is ok in | |
768 | /// user code, if awkward, but extra weird for closures, since the | |
769 | /// borrow is hidden. | |
770 | /// | |
771 | /// So we introduce a "unique imm" borrow -- the referent is | |
772 | /// immutable, but not aliasable. This solves the problem. For | |
773 | /// simplicity, we don't give users the way to express this | |
774 | /// borrow, it's just used when translating closures. | |
775 | UniqueImmBorrow, | |
776 | ||
777 | /// Data is mutable and not aliasable. | |
778 | MutBorrow | |
779 | } | |
780 | ||
781 | /// Information describing the capture of an upvar. This is computed | |
782 | /// during `typeck`, specifically by `regionck`. | |
9e0c209e SL |
783 | #[derive(PartialEq, Clone, Debug, Copy, RustcEncodable, RustcDecodable)] |
784 | pub enum UpvarCapture<'tcx> { | |
e9174d1e SL |
785 | /// Upvar is captured by value. This is always true when the |
786 | /// closure is labeled `move`, but can also be true in other cases | |
787 | /// depending on inference. | |
788 | ByValue, | |
789 | ||
790 | /// Upvar is captured by reference. | |
9e0c209e | 791 | ByRef(UpvarBorrow<'tcx>), |
e9174d1e SL |
792 | } |
793 | ||
9e0c209e SL |
794 | #[derive(PartialEq, Clone, Copy, RustcEncodable, RustcDecodable)] |
795 | pub struct UpvarBorrow<'tcx> { | |
e9174d1e SL |
796 | /// The kind of borrow: by-ref upvars have access to shared |
797 | /// immutable borrows, which are not part of the normal language | |
798 | /// syntax. | |
799 | pub kind: BorrowKind, | |
800 | ||
801 | /// Region of the resulting reference. | |
7cac9316 | 802 | pub region: ty::Region<'tcx>, |
e9174d1e SL |
803 | } |
804 | ||
476ff2be | 805 | pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>; |
e9174d1e SL |
806 | |
807 | #[derive(Copy, Clone)] | |
808 | pub struct ClosureUpvar<'tcx> { | |
7453a54e | 809 | pub def: Def, |
e9174d1e SL |
810 | pub span: Span, |
811 | pub ty: Ty<'tcx>, | |
812 | } | |
813 | ||
0531ce1d | 814 | #[derive(Clone, Copy, PartialEq, Eq)] |
e9174d1e | 815 | pub enum IntVarValue { |
b039eaaf SL |
816 | IntType(ast::IntTy), |
817 | UintType(ast::UintTy), | |
e9174d1e SL |
818 | } |
819 | ||
0531ce1d XL |
820 | #[derive(Clone, Copy, PartialEq, Eq)] |
821 | pub struct FloatVarValue(pub ast::FloatTy); | |
822 | ||
94b46f34 XL |
823 | impl ty::EarlyBoundRegion { |
824 | pub fn to_bound_region(&self) -> ty::BoundRegion { | |
825 | ty::BoundRegion::BrNamed(self.def_id, self.name) | |
826 | } | |
827 | } | |
ea8adc8c | 828 | |
94b46f34 XL |
829 | #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] |
830 | pub enum GenericParamDefKind { | |
831 | Lifetime, | |
832 | Type { | |
833 | has_default: bool, | |
834 | object_lifetime_default: ObjectLifetimeDefault, | |
835 | synthetic: Option<hir::SyntheticTyParamKind>, | |
836 | } | |
e9174d1e SL |
837 | } |
838 | ||
94b46f34 XL |
839 | #[derive(Clone, RustcEncodable, RustcDecodable)] |
840 | pub struct GenericParamDef { | |
83c7162d | 841 | pub name: InternedString, |
e9174d1e | 842 | pub def_id: DefId, |
e9174d1e | 843 | pub index: u32, |
c30ab7b3 SL |
844 | |
845 | /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute | |
94b46f34 XL |
846 | /// on generic parameter `'a`/`T`, asserts data behind the parameter |
847 | /// `'a`/`T` won't be accessed during the parent type's `Drop` impl. | |
c30ab7b3 | 848 | pub pure_wrt_drop: bool, |
94b46f34 XL |
849 | |
850 | pub kind: GenericParamDefKind, | |
e9174d1e SL |
851 | } |
852 | ||
94b46f34 | 853 | impl GenericParamDef { |
9e0c209e | 854 | pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion { |
94b46f34 XL |
855 | match self.kind { |
856 | GenericParamDefKind::Lifetime => { | |
857 | ty::EarlyBoundRegion { | |
858 | def_id: self.def_id, | |
859 | index: self.index, | |
860 | name: self.name, | |
861 | } | |
862 | } | |
863 | _ => bug!("cannot convert a non-lifetime parameter def to an early bound region") | |
9e0c209e | 864 | } |
e9174d1e | 865 | } |
9e0c209e | 866 | |
7cac9316 | 867 | pub fn to_bound_region(&self) -> ty::BoundRegion { |
94b46f34 XL |
868 | match self.kind { |
869 | GenericParamDefKind::Lifetime => { | |
870 | self.to_early_bound_region_data().to_bound_region() | |
871 | } | |
872 | _ => bug!("cannot convert a non-lifetime parameter def to an early bound region") | |
873 | } | |
7cac9316 XL |
874 | } |
875 | } | |
876 | ||
94b46f34 XL |
877 | pub struct GenericParamCount { |
878 | pub lifetimes: usize, | |
879 | pub types: usize, | |
e9174d1e SL |
880 | } |
881 | ||
882 | /// Information about the formal type/lifetime parameters associated | |
883 | /// with an item or method. Analogous to hir::Generics. | |
ea8adc8c | 884 | /// |
94b46f34 XL |
885 | /// The ordering of parameters is the same as in Subst (excluding child generics): |
886 | /// Self (optionally), Lifetime params..., Type params... | |
9e0c209e | 887 | #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] |
8bb4bdeb | 888 | pub struct Generics { |
9e0c209e | 889 | pub parent: Option<DefId>, |
94b46f34 XL |
890 | pub parent_count: usize, |
891 | pub params: Vec<GenericParamDef>, | |
8bb4bdeb | 892 | |
94b46f34 XL |
893 | /// Reverse map to the `index` field of each `GenericParamDef` |
894 | pub param_def_id_to_index: FxHashMap<DefId, u32>, | |
8bb4bdeb | 895 | |
9e0c209e | 896 | pub has_self: bool, |
3b2f2976 | 897 | pub has_late_bound_regions: Option<Span>, |
e9174d1e SL |
898 | } |
899 | ||
ea8adc8c | 900 | impl<'a, 'gcx, 'tcx> Generics { |
94b46f34 XL |
901 | pub fn count(&self) -> usize { |
902 | self.parent_count + self.params.len() | |
e9174d1e SL |
903 | } |
904 | ||
94b46f34 XL |
905 | pub fn own_counts(&self) -> GenericParamCount { |
906 | // We could cache this as a property of `GenericParamCount`, but | |
907 | // the aim is to refactor this away entirely eventually and the | |
908 | // presence of this method will be a constant reminder. | |
909 | let mut own_counts = GenericParamCount { | |
910 | lifetimes: 0, | |
911 | types: 0, | |
912 | }; | |
913 | ||
914 | for param in &self.params { | |
915 | match param.kind { | |
916 | GenericParamDefKind::Lifetime => own_counts.lifetimes += 1, | |
917 | GenericParamDefKind::Type {..} => own_counts.types += 1, | |
918 | }; | |
919 | } | |
920 | ||
921 | own_counts | |
e9174d1e SL |
922 | } |
923 | ||
94b46f34 XL |
924 | pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { |
925 | for param in &self.params { | |
926 | match param.kind { | |
927 | GenericParamDefKind::Type {..} => return true, | |
928 | GenericParamDefKind::Lifetime => {} | |
929 | } | |
930 | } | |
931 | if let Some(parent_def_id) = self.parent { | |
932 | let parent = tcx.generics_of(parent_def_id); | |
933 | parent.requires_monomorphization(tcx) | |
934 | } else { | |
935 | false | |
936 | } | |
e9174d1e | 937 | } |
c30ab7b3 | 938 | |
ea8adc8c XL |
939 | pub fn region_param(&'tcx self, |
940 | param: &EarlyBoundRegion, | |
941 | tcx: TyCtxt<'a, 'gcx, 'tcx>) | |
94b46f34 | 942 | -> &'tcx GenericParamDef |
ea8adc8c | 943 | { |
94b46f34 XL |
944 | if let Some(index) = param.index.checked_sub(self.parent_count as u32) { |
945 | let param = &self.params[index as usize]; | |
946 | match param.kind { | |
947 | ty::GenericParamDefKind::Lifetime => param, | |
948 | _ => bug!("expected lifetime parameter, but found another generic parameter") | |
949 | } | |
ea8adc8c XL |
950 | } else { |
951 | tcx.generics_of(self.parent.expect("parent_count>0 but no parent?")) | |
952 | .region_param(param, tcx) | |
953 | } | |
954 | } | |
955 | ||
94b46f34 | 956 | /// Returns the `GenericParamDef` associated with this `ParamTy`. |
ea8adc8c XL |
957 | pub fn type_param(&'tcx self, |
958 | param: &ParamTy, | |
959 | tcx: TyCtxt<'a, 'gcx, 'tcx>) | |
94b46f34 XL |
960 | -> &'tcx GenericParamDef { |
961 | if let Some(index) = param.idx.checked_sub(self.parent_count as u32) { | |
962 | let param = &self.params[index as usize]; | |
963 | match param.kind { | |
964 | ty::GenericParamDefKind::Type {..} => param, | |
965 | _ => bug!("expected type parameter, but found another generic parameter") | |
ea8adc8c XL |
966 | } |
967 | } else { | |
968 | tcx.generics_of(self.parent.expect("parent_count>0 but no parent?")) | |
969 | .type_param(param, tcx) | |
970 | } | |
c30ab7b3 | 971 | } |
e9174d1e SL |
972 | } |
973 | ||
974 | /// Bounds on generics. | |
8bb4bdeb | 975 | #[derive(Clone, Default)] |
e9174d1e | 976 | pub struct GenericPredicates<'tcx> { |
9e0c209e SL |
977 | pub parent: Option<DefId>, |
978 | pub predicates: Vec<Predicate<'tcx>>, | |
e9174d1e SL |
979 | } |
980 | ||
9e0c209e SL |
981 | impl<'tcx> serialize::UseSpecializedEncodable for GenericPredicates<'tcx> {} |
982 | impl<'tcx> serialize::UseSpecializedDecodable for GenericPredicates<'tcx> {} | |
e9174d1e | 983 | |
9e0c209e | 984 | impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { |
a7813a04 | 985 | pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>) |
e9174d1e | 986 | -> InstantiatedPredicates<'tcx> { |
9e0c209e SL |
987 | let mut instantiated = InstantiatedPredicates::empty(); |
988 | self.instantiate_into(tcx, &mut instantiated, substs); | |
989 | instantiated | |
990 | } | |
991 | pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>) | |
992 | -> InstantiatedPredicates<'tcx> { | |
e9174d1e | 993 | InstantiatedPredicates { |
9e0c209e | 994 | predicates: self.predicates.subst(tcx, substs) |
e9174d1e SL |
995 | } |
996 | } | |
997 | ||
9e0c209e SL |
998 | fn instantiate_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, |
999 | instantiated: &mut InstantiatedPredicates<'tcx>, | |
1000 | substs: &Substs<'tcx>) { | |
1001 | if let Some(def_id) = self.parent { | |
7cac9316 | 1002 | tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs); |
9e0c209e SL |
1003 | } |
1004 | instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs))) | |
1005 | } | |
1006 | ||
7cac9316 XL |
1007 | pub fn instantiate_identity(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) |
1008 | -> InstantiatedPredicates<'tcx> { | |
1009 | let mut instantiated = InstantiatedPredicates::empty(); | |
1010 | self.instantiate_identity_into(tcx, &mut instantiated); | |
1011 | instantiated | |
1012 | } | |
1013 | ||
1014 | fn instantiate_identity_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, | |
1015 | instantiated: &mut InstantiatedPredicates<'tcx>) { | |
1016 | if let Some(def_id) = self.parent { | |
1017 | tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated); | |
1018 | } | |
1019 | instantiated.predicates.extend(&self.predicates) | |
1020 | } | |
1021 | ||
a7813a04 | 1022 | pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, |
e9174d1e SL |
1023 | poly_trait_ref: &ty::PolyTraitRef<'tcx>) |
1024 | -> InstantiatedPredicates<'tcx> | |
1025 | { | |
9e0c209e | 1026 | assert_eq!(self.parent, None); |
e9174d1e | 1027 | InstantiatedPredicates { |
9e0c209e | 1028 | predicates: self.predicates.iter().map(|pred| { |
a7813a04 | 1029 | pred.subst_supertrait(tcx, poly_trait_ref) |
9e0c209e | 1030 | }).collect() |
e9174d1e SL |
1031 | } |
1032 | } | |
1033 | } | |
1034 | ||
7cac9316 | 1035 | #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
1036 | pub enum Predicate<'tcx> { |
1037 | /// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be | |
1038 | /// the `Self` type of the trait reference and `A`, `B`, and `C` | |
9e0c209e | 1039 | /// would be the type parameters. |
e9174d1e SL |
1040 | Trait(PolyTraitPredicate<'tcx>), |
1041 | ||
e9174d1e | 1042 | /// where 'a : 'b |
9e0c209e | 1043 | RegionOutlives(PolyRegionOutlivesPredicate<'tcx>), |
e9174d1e SL |
1044 | |
1045 | /// where T : 'a | |
1046 | TypeOutlives(PolyTypeOutlivesPredicate<'tcx>), | |
1047 | ||
1048 | /// where <T as TraitRef>::Name == X, approximately. | |
1049 | /// See `ProjectionPredicate` struct for details. | |
1050 | Projection(PolyProjectionPredicate<'tcx>), | |
1051 | ||
1052 | /// no syntax: T WF | |
1053 | WellFormed(Ty<'tcx>), | |
1054 | ||
1055 | /// trait must be object-safe | |
1056 | ObjectSafe(DefId), | |
a7813a04 | 1057 | |
9e0c209e SL |
1058 | /// No direct syntax. May be thought of as `where T : FnFoo<...>` |
1059 | /// for some substitutions `...` and T being a closure type. | |
1060 | /// Satisfied (or refuted) once we know the closure's kind. | |
ff7c6d11 | 1061 | ClosureKind(DefId, ClosureSubsts<'tcx>, ClosureKind), |
cc61c64b XL |
1062 | |
1063 | /// `T1 <: T2` | |
1064 | Subtype(PolySubtypePredicate<'tcx>), | |
ea8adc8c XL |
1065 | |
1066 | /// Constant initializer must evaluate successfully. | |
1067 | ConstEvaluatable(DefId, &'tcx Substs<'tcx>), | |
e9174d1e SL |
1068 | } |
1069 | ||
83c7162d XL |
1070 | /// The crate outlives map is computed during typeck and contains the |
1071 | /// outlives of every item in the local crate. You should not use it | |
1072 | /// directly, because to do so will make your pass dependent on the | |
1073 | /// HIR of every item in the local crate. Instead, use | |
1074 | /// `tcx.inferred_outlives_of()` to get the outlives for a *particular* | |
1075 | /// item. | |
1076 | pub struct CratePredicatesMap<'tcx> { | |
1077 | /// For each struct with outlive bounds, maps to a vector of the | |
1078 | /// predicate of its outlive bounds. If an item has no outlives | |
1079 | /// bounds, it will have no entry. | |
1080 | pub predicates: FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>, | |
1081 | ||
1082 | /// An empty vector, useful for cloning. | |
1083 | pub empty_predicate: Lrc<Vec<ty::Predicate<'tcx>>>, | |
1084 | } | |
1085 | ||
abe05a73 XL |
1086 | impl<'tcx> AsRef<Predicate<'tcx>> for Predicate<'tcx> { |
1087 | fn as_ref(&self) -> &Predicate<'tcx> { | |
1088 | self | |
1089 | } | |
1090 | } | |
1091 | ||
a7813a04 | 1092 | impl<'a, 'gcx, 'tcx> Predicate<'tcx> { |
e9174d1e SL |
1093 | /// Performs a substitution suitable for going from a |
1094 | /// poly-trait-ref to supertraits that must hold if that | |
1095 | /// poly-trait-ref holds. This is slightly different from a normal | |
1096 | /// substitution in terms of what happens with bound regions. See | |
1097 | /// lengthy comment below for details. | |
a7813a04 | 1098 | pub fn subst_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, |
e9174d1e SL |
1099 | trait_ref: &ty::PolyTraitRef<'tcx>) |
1100 | -> ty::Predicate<'tcx> | |
1101 | { | |
1102 | // The interaction between HRTB and supertraits is not entirely | |
1103 | // obvious. Let me walk you (and myself) through an example. | |
1104 | // | |
1105 | // Let's start with an easy case. Consider two traits: | |
1106 | // | |
1107 | // trait Foo<'a> : Bar<'a,'a> { } | |
1108 | // trait Bar<'b,'c> { } | |
1109 | // | |
1110 | // Now, if we have a trait reference `for<'x> T : Foo<'x>`, then | |
1111 | // we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we | |
1112 | // knew that `Foo<'x>` (for any 'x) then we also know that | |
1113 | // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from | |
1114 | // normal substitution. | |
1115 | // | |
1116 | // In terms of why this is sound, the idea is that whenever there | |
1117 | // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` | |
1118 | // holds. So if there is an impl of `T:Foo<'a>` that applies to | |
1119 | // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all | |
1120 | // `'a`. | |
1121 | // | |
1122 | // Another example to be careful of is this: | |
1123 | // | |
1124 | // trait Foo1<'a> : for<'b> Bar1<'a,'b> { } | |
1125 | // trait Bar1<'b,'c> { } | |
1126 | // | |
1127 | // Here, if we have `for<'x> T : Foo1<'x>`, then what do we know? | |
1128 | // The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The | |
1129 | // reason is similar to the previous example: any impl of | |
1130 | // `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`. So | |
1131 | // basically we would want to collapse the bound lifetimes from | |
1132 | // the input (`trait_ref`) and the supertraits. | |
1133 | // | |
1134 | // To achieve this in practice is fairly straightforward. Let's | |
1135 | // consider the more complicated scenario: | |
1136 | // | |
1137 | // - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x` | |
1138 | // has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`, | |
1139 | // where both `'x` and `'b` would have a DB index of 1. | |
1140 | // The substitution from the input trait-ref is therefore going to be | |
1141 | // `'a => 'x` (where `'x` has a DB index of 1). | |
1142 | // - The super-trait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an | |
1143 | // early-bound parameter and `'b' is a late-bound parameter with a | |
1144 | // DB index of 1. | |
1145 | // - If we replace `'a` with `'x` from the input, it too will have | |
1146 | // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` | |
1147 | // just as we wanted. | |
1148 | // | |
1149 | // There is only one catch. If we just apply the substitution `'a | |
1150 | // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will | |
1151 | // adjust the DB index because we substituting into a binder (it | |
1152 | // tries to be so smart...) resulting in `for<'x> for<'b> | |
1153 | // Bar1<'x,'b>` (we have no syntax for this, so use your | |
1154 | // imagination). Basically the 'x will have DB index of 2 and 'b | |
1155 | // will have DB index of 1. Not quite what we want. So we apply | |
1156 | // the substitution to the *contents* of the trait reference, | |
1157 | // rather than the trait reference itself (put another way, the | |
1158 | // substitution code expects equal binding levels in the values | |
1159 | // from the substitution and the value being substituted into, and | |
1160 | // this trick achieves that). | |
1161 | ||
83c7162d | 1162 | let substs = &trait_ref.skip_binder().substs; |
e9174d1e | 1163 | match *self { |
83c7162d XL |
1164 | Predicate::Trait(ref binder) => |
1165 | Predicate::Trait(binder.map_bound(|data| data.subst(tcx, substs))), | |
1166 | Predicate::Subtype(ref binder) => | |
1167 | Predicate::Subtype(binder.map_bound(|data| data.subst(tcx, substs))), | |
1168 | Predicate::RegionOutlives(ref binder) => | |
1169 | Predicate::RegionOutlives(binder.map_bound(|data| data.subst(tcx, substs))), | |
1170 | Predicate::TypeOutlives(ref binder) => | |
1171 | Predicate::TypeOutlives(binder.map_bound(|data| data.subst(tcx, substs))), | |
1172 | Predicate::Projection(ref binder) => | |
1173 | Predicate::Projection(binder.map_bound(|data| data.subst(tcx, substs))), | |
e9174d1e SL |
1174 | Predicate::WellFormed(data) => |
1175 | Predicate::WellFormed(data.subst(tcx, substs)), | |
1176 | Predicate::ObjectSafe(trait_def_id) => | |
1177 | Predicate::ObjectSafe(trait_def_id), | |
ff7c6d11 XL |
1178 | Predicate::ClosureKind(closure_def_id, closure_substs, kind) => |
1179 | Predicate::ClosureKind(closure_def_id, closure_substs.subst(tcx, substs), kind), | |
ea8adc8c XL |
1180 | Predicate::ConstEvaluatable(def_id, const_substs) => |
1181 | Predicate::ConstEvaluatable(def_id, const_substs.subst(tcx, substs)), | |
e9174d1e SL |
1182 | } |
1183 | } | |
1184 | } | |
1185 | ||
7cac9316 | 1186 | #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
1187 | pub struct TraitPredicate<'tcx> { |
1188 | pub trait_ref: TraitRef<'tcx> | |
1189 | } | |
1190 | pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>; | |
1191 | ||
1192 | impl<'tcx> TraitPredicate<'tcx> { | |
1193 | pub fn def_id(&self) -> DefId { | |
1194 | self.trait_ref.def_id | |
1195 | } | |
1196 | ||
9e0c209e SL |
1197 | pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a { |
1198 | self.trait_ref.input_types() | |
e9174d1e SL |
1199 | } |
1200 | ||
1201 | pub fn self_ty(&self) -> Ty<'tcx> { | |
1202 | self.trait_ref.self_ty() | |
1203 | } | |
1204 | } | |
1205 | ||
1206 | impl<'tcx> PolyTraitPredicate<'tcx> { | |
1207 | pub fn def_id(&self) -> DefId { | |
7453a54e | 1208 | // ok to skip binder since trait def-id does not care about regions |
83c7162d | 1209 | self.skip_binder().def_id() |
e9174d1e SL |
1210 | } |
1211 | } | |
1212 | ||
94b46f34 | 1213 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
1214 | pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B` |
1215 | pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>; | |
0531ce1d XL |
1216 | pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, |
1217 | ty::Region<'tcx>>; | |
1218 | pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, | |
1219 | ty::Region<'tcx>>; | |
1220 | pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<RegionOutlivesPredicate<'tcx>>; | |
1221 | pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<TypeOutlivesPredicate<'tcx>>; | |
e9174d1e | 1222 | |
7cac9316 | 1223 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] |
cc61c64b XL |
1224 | pub struct SubtypePredicate<'tcx> { |
1225 | pub a_is_expected: bool, | |
1226 | pub a: Ty<'tcx>, | |
1227 | pub b: Ty<'tcx> | |
1228 | } | |
1229 | pub type PolySubtypePredicate<'tcx> = ty::Binder<SubtypePredicate<'tcx>>; | |
1230 | ||
e9174d1e SL |
1231 | /// This kind of predicate has no *direct* correspondent in the |
1232 | /// syntax, but it roughly corresponds to the syntactic forms: | |
1233 | /// | |
1234 | /// 1. `T : TraitRef<..., Item=Type>` | |
1235 | /// 2. `<T as TraitRef<...>>::Item == Type` (NYI) | |
1236 | /// | |
1237 | /// In particular, form #1 is "desugared" to the combination of a | |
1238 | /// normal trait predicate (`T : TraitRef<...>`) and one of these | |
1239 | /// predicates. Form #2 is a broader form in that it also permits | |
ff7c6d11 XL |
1240 | /// equality between arbitrary types. Processing an instance of |
1241 | /// Form #2 eventually yields one of these `ProjectionPredicate` | |
e9174d1e | 1242 | /// instances to normalize the LHS. |
0531ce1d | 1243 | #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
1244 | pub struct ProjectionPredicate<'tcx> { |
1245 | pub projection_ty: ProjectionTy<'tcx>, | |
1246 | pub ty: Ty<'tcx>, | |
1247 | } | |
1248 | ||
1249 | pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>; | |
1250 | ||
1251 | impl<'tcx> PolyProjectionPredicate<'tcx> { | |
83c7162d XL |
1252 | /// Returns the def-id of the associated item being projected. |
1253 | pub fn item_def_id(&self) -> DefId { | |
1254 | self.skip_binder().projection_ty.item_def_id | |
1255 | } | |
1256 | ||
041b39d2 XL |
1257 | pub fn to_poly_trait_ref(&self, tcx: TyCtxt) -> PolyTraitRef<'tcx> { |
1258 | // Note: unlike with TraitRef::to_poly_trait_ref(), | |
1259 | // self.0.trait_ref is permitted to have escaping regions. | |
1260 | // This is because here `self` has a `Binder` and so does our | |
1261 | // return value, so we are preserving the number of binding | |
1262 | // levels. | |
83c7162d | 1263 | self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) |
e9174d1e | 1264 | } |
3b2f2976 XL |
1265 | |
1266 | pub fn ty(&self) -> Binder<Ty<'tcx>> { | |
83c7162d XL |
1267 | self.map_bound(|predicate| predicate.ty) |
1268 | } | |
1269 | ||
1270 | /// The DefId of the TraitItem for the associated type. | |
1271 | /// | |
1272 | /// Note that this is not the DefId of the TraitRef containing this | |
1273 | /// associated type, which is in tcx.associated_item(projection_def_id()).container. | |
1274 | pub fn projection_def_id(&self) -> DefId { | |
1275 | // ok to skip binder since trait def-id does not care about regions | |
1276 | self.skip_binder().projection_ty.item_def_id | |
3b2f2976 | 1277 | } |
e9174d1e SL |
1278 | } |
1279 | ||
1280 | pub trait ToPolyTraitRef<'tcx> { | |
1281 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; | |
1282 | } | |
1283 | ||
1284 | impl<'tcx> ToPolyTraitRef<'tcx> for TraitRef<'tcx> { | |
1285 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { | |
83c7162d | 1286 | ty::Binder::dummy(self.clone()) |
e9174d1e SL |
1287 | } |
1288 | } | |
1289 | ||
1290 | impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { | |
1291 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { | |
7453a54e | 1292 | self.map_bound_ref(|trait_pred| trait_pred.trait_ref) |
e9174d1e SL |
1293 | } |
1294 | } | |
1295 | ||
e9174d1e SL |
1296 | pub trait ToPredicate<'tcx> { |
1297 | fn to_predicate(&self) -> Predicate<'tcx>; | |
1298 | } | |
1299 | ||
1300 | impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { | |
1301 | fn to_predicate(&self) -> Predicate<'tcx> { | |
83c7162d | 1302 | ty::Predicate::Trait(ty::Binder::dummy(ty::TraitPredicate { |
e9174d1e SL |
1303 | trait_ref: self.clone() |
1304 | })) | |
1305 | } | |
1306 | } | |
1307 | ||
1308 | impl<'tcx> ToPredicate<'tcx> for PolyTraitRef<'tcx> { | |
1309 | fn to_predicate(&self) -> Predicate<'tcx> { | |
1310 | ty::Predicate::Trait(self.to_poly_trait_predicate()) | |
1311 | } | |
1312 | } | |
1313 | ||
9e0c209e | 1314 | impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { |
e9174d1e SL |
1315 | fn to_predicate(&self) -> Predicate<'tcx> { |
1316 | Predicate::RegionOutlives(self.clone()) | |
1317 | } | |
1318 | } | |
1319 | ||
1320 | impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { | |
1321 | fn to_predicate(&self) -> Predicate<'tcx> { | |
1322 | Predicate::TypeOutlives(self.clone()) | |
1323 | } | |
1324 | } | |
1325 | ||
1326 | impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { | |
1327 | fn to_predicate(&self) -> Predicate<'tcx> { | |
1328 | Predicate::Projection(self.clone()) | |
1329 | } | |
1330 | } | |
1331 | ||
1332 | impl<'tcx> Predicate<'tcx> { | |
1333 | /// Iterates over the types in this predicate. Note that in all | |
1334 | /// cases this is skipping over a binder, so late-bound regions | |
1335 | /// with depth 0 are bound by the predicate. | |
1336 | pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> { | |
1337 | let vec: Vec<_> = match *self { | |
1338 | ty::Predicate::Trait(ref data) => { | |
9e0c209e | 1339 | data.skip_binder().input_types().collect() |
a7813a04 | 1340 | } |
83c7162d XL |
1341 | ty::Predicate::Subtype(binder) => { |
1342 | let SubtypePredicate { a, b, a_is_expected: _ } = binder.skip_binder(); | |
cc61c64b XL |
1343 | vec![a, b] |
1344 | } | |
83c7162d XL |
1345 | ty::Predicate::TypeOutlives(binder) => { |
1346 | vec![binder.skip_binder().0] | |
e9174d1e SL |
1347 | } |
1348 | ty::Predicate::RegionOutlives(..) => { | |
1349 | vec![] | |
1350 | } | |
1351 | ty::Predicate::Projection(ref data) => { | |
83c7162d XL |
1352 | let inner = data.skip_binder(); |
1353 | inner.projection_ty.substs.types().chain(Some(inner.ty)).collect() | |
e9174d1e SL |
1354 | } |
1355 | ty::Predicate::WellFormed(data) => { | |
1356 | vec![data] | |
1357 | } | |
1358 | ty::Predicate::ObjectSafe(_trait_def_id) => { | |
1359 | vec![] | |
1360 | } | |
ff7c6d11 XL |
1361 | ty::Predicate::ClosureKind(_closure_def_id, closure_substs, _kind) => { |
1362 | closure_substs.substs.types().collect() | |
a7813a04 | 1363 | } |
ea8adc8c XL |
1364 | ty::Predicate::ConstEvaluatable(_, substs) => { |
1365 | substs.types().collect() | |
1366 | } | |
e9174d1e SL |
1367 | }; |
1368 | ||
1369 | // The only reason to collect into a vector here is that I was | |
1370 | // too lazy to make the full (somewhat complicated) iterator | |
1371 | // type that would be needed here. But I wanted this fn to | |
1372 | // return an iterator conceptually, rather than a `Vec`, so as | |
1373 | // to be closer to `Ty::walk`. | |
1374 | vec.into_iter() | |
1375 | } | |
1376 | ||
1377 | pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> { | |
1378 | match *self { | |
1379 | Predicate::Trait(ref t) => { | |
1380 | Some(t.to_poly_trait_ref()) | |
1381 | } | |
1382 | Predicate::Projection(..) | | |
cc61c64b | 1383 | Predicate::Subtype(..) | |
e9174d1e SL |
1384 | Predicate::RegionOutlives(..) | |
1385 | Predicate::WellFormed(..) | | |
1386 | Predicate::ObjectSafe(..) | | |
a7813a04 | 1387 | Predicate::ClosureKind(..) | |
ea8adc8c XL |
1388 | Predicate::TypeOutlives(..) | |
1389 | Predicate::ConstEvaluatable(..) => { | |
e9174d1e SL |
1390 | None |
1391 | } | |
1392 | } | |
1393 | } | |
abe05a73 XL |
1394 | |
1395 | pub fn to_opt_type_outlives(&self) -> Option<PolyTypeOutlivesPredicate<'tcx>> { | |
1396 | match *self { | |
1397 | Predicate::TypeOutlives(data) => { | |
1398 | Some(data) | |
1399 | } | |
1400 | Predicate::Trait(..) | | |
1401 | Predicate::Projection(..) | | |
abe05a73 XL |
1402 | Predicate::Subtype(..) | |
1403 | Predicate::RegionOutlives(..) | | |
1404 | Predicate::WellFormed(..) | | |
1405 | Predicate::ObjectSafe(..) | | |
1406 | Predicate::ClosureKind(..) | | |
1407 | Predicate::ConstEvaluatable(..) => { | |
1408 | None | |
1409 | } | |
1410 | } | |
1411 | } | |
e9174d1e SL |
1412 | } |
1413 | ||
1414 | /// Represents the bounds declared on a particular set of type | |
1415 | /// parameters. Should eventually be generalized into a flag list of | |
1416 | /// where clauses. You can obtain a `InstantiatedPredicates` list from a | |
1417 | /// `GenericPredicates` by using the `instantiate` method. Note that this method | |
1418 | /// reflects an important semantic invariant of `InstantiatedPredicates`: while | |
1419 | /// the `GenericPredicates` are expressed in terms of the bound type | |
1420 | /// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance | |
1421 | /// represented a set of bounds for some particular instantiation, | |
1422 | /// meaning that the generic parameters have been substituted with | |
1423 | /// their values. | |
1424 | /// | |
1425 | /// Example: | |
1426 | /// | |
1427 | /// struct Foo<T,U:Bar<T>> { ... } | |
1428 | /// | |
1429 | /// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like | |
1430 | /// `[[], [U:Bar<T>]]`. Now if there were some particular reference | |
1431 | /// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[], | |
1432 | /// [usize:Bar<isize>]]`. | |
1433 | #[derive(Clone)] | |
1434 | pub struct InstantiatedPredicates<'tcx> { | |
9e0c209e | 1435 | pub predicates: Vec<Predicate<'tcx>>, |
e9174d1e SL |
1436 | } |
1437 | ||
1438 | impl<'tcx> InstantiatedPredicates<'tcx> { | |
1439 | pub fn empty() -> InstantiatedPredicates<'tcx> { | |
9e0c209e | 1440 | InstantiatedPredicates { predicates: vec![] } |
e9174d1e SL |
1441 | } |
1442 | ||
1443 | pub fn is_empty(&self) -> bool { | |
1444 | self.predicates.is_empty() | |
1445 | } | |
1446 | } | |
1447 | ||
0531ce1d XL |
1448 | /// "Universes" are used during type- and trait-checking in the |
1449 | /// presence of `for<..>` binders to control what sets of names are | |
1450 | /// visible. Universes are arranged into a tree: the root universe | |
1451 | /// contains names that are always visible. But when you enter into | |
1452 | /// some subuniverse, then it may add names that are only visible | |
1453 | /// within that subtree (but it can still name the names of its | |
1454 | /// ancestor universes). | |
1455 | /// | |
1456 | /// To make this more concrete, consider this program: | |
1457 | /// | |
1458 | /// ``` | |
1459 | /// struct Foo { } | |
1460 | /// fn bar<T>(x: T) { | |
1461 | /// let y: for<'a> fn(&'a u8, Foo) = ...; | |
1462 | /// } | |
1463 | /// ``` | |
1464 | /// | |
1465 | /// The struct name `Foo` is in the root universe U0. But the type | |
1466 | /// parameter `T`, introduced on `bar`, is in a subuniverse U1 -- | |
1467 | /// i.e., within `bar`, we can name both `T` and `Foo`, but outside of | |
1468 | /// `bar`, we cannot name `T`. Then, within the type of `y`, the | |
1469 | /// region `'a` is in a subuniverse U2 of U1, because we can name it | |
1470 | /// inside the fn type but not outside. | |
1471 | /// | |
1472 | /// Universes are related to **skolemization** -- which is a way of | |
1473 | /// doing type- and trait-checking around these "forall" binders (also | |
1474 | /// called **universal quantification**). The idea is that when, in | |
1475 | /// the body of `bar`, we refer to `T` as a type, we aren't referring | |
1476 | /// to any type in particular, but rather a kind of "fresh" type that | |
1477 | /// is distinct from all other types we have actually declared. This | |
1478 | /// is called a **skolemized** type, and we use universes to talk | |
1479 | /// about this. In other words, a type name in universe 0 always | |
1480 | /// corresponds to some "ground" type that the user declared, but a | |
1481 | /// type name in a non-zero universe is a skolemized type -- an | |
1482 | /// idealized representative of "types in general" that we use for | |
1483 | /// checking generic functions. | |
8faf50e0 | 1484 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] |
0531ce1d XL |
1485 | pub struct UniverseIndex(u32); |
1486 | ||
1487 | impl UniverseIndex { | |
1488 | /// The root universe, where things that the user defined are | |
1489 | /// visible. | |
83c7162d | 1490 | pub const ROOT: Self = UniverseIndex(0); |
0531ce1d | 1491 | |
8faf50e0 XL |
1492 | /// The "max universe" -- this isn't really a valid universe, but |
1493 | /// it's useful sometimes as a "starting value" when you are | |
1494 | /// taking the minimum of a (non-empty!) set of universes. | |
1495 | pub const MAX: Self = UniverseIndex(::std::u32::MAX); | |
1496 | ||
1497 | /// Creates a universe index from the given integer. Not to be | |
1498 | /// used lightly lest you pick a bad value. But sometimes we | |
1499 | /// convert universe indicies into integers and back for various | |
1500 | /// reasons. | |
1501 | pub fn from_u32(index: u32) -> Self { | |
1502 | UniverseIndex(index) | |
1503 | } | |
1504 | ||
0531ce1d XL |
1505 | /// A "subuniverse" corresponds to being inside a `forall` quantifier. |
1506 | /// So, for example, suppose we have this type in universe `U`: | |
1507 | /// | |
1508 | /// ``` | |
1509 | /// for<'a> fn(&'a u32) | |
1510 | /// ``` | |
1511 | /// | |
1512 | /// Once we "enter" into this `for<'a>` quantifier, we are in a | |
1513 | /// subuniverse of `U` -- in this new universe, we can name the | |
1514 | /// region `'a`, but that region was not nameable from `U` because | |
1515 | /// it was not in scope there. | |
1516 | pub fn subuniverse(self) -> UniverseIndex { | |
83c7162d XL |
1517 | UniverseIndex(self.0.checked_add(1).unwrap()) |
1518 | } | |
1519 | ||
8faf50e0 XL |
1520 | /// True if the names in this universe are a subset of the names in `other`. |
1521 | pub fn is_subset_of(self, other: UniverseIndex) -> bool { | |
1522 | self.0 <= other.0 | |
1523 | } | |
1524 | ||
83c7162d XL |
1525 | pub fn as_u32(&self) -> u32 { |
1526 | self.0 | |
1527 | } | |
1528 | ||
1529 | pub fn as_usize(&self) -> usize { | |
1530 | self.0 as usize | |
1531 | } | |
1532 | } | |
1533 | ||
8faf50e0 XL |
1534 | impl fmt::Debug for UniverseIndex { |
1535 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
1536 | write!(fmt, "U{}", self.as_u32()) | |
1537 | } | |
1538 | } | |
1539 | ||
83c7162d XL |
1540 | impl From<u32> for UniverseIndex { |
1541 | fn from(index: u32) -> Self { | |
1542 | UniverseIndex(index) | |
0531ce1d XL |
1543 | } |
1544 | } | |
1545 | ||
7cac9316 XL |
1546 | /// When type checking, we use the `ParamEnv` to track |
1547 | /// details about the set of where-clauses that are in scope at this | |
1548 | /// particular point. | |
1549 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] | |
1550 | pub struct ParamEnv<'tcx> { | |
e9174d1e SL |
1551 | /// Obligations that the caller must satisfy. This is basically |
1552 | /// the set of bounds on the in-scope type parameters, translated | |
1553 | /// into Obligations, and elaborated and normalized. | |
7cac9316 XL |
1554 | pub caller_bounds: &'tcx Slice<ty::Predicate<'tcx>>, |
1555 | ||
94b46f34 | 1556 | /// Typically, this is `Reveal::UserFacing`, but during codegen we |
7cac9316 XL |
1557 | /// want `Reveal::All` -- note that this is always paired with an |
1558 | /// empty environment. To get that, use `ParamEnv::reveal()`. | |
1559 | pub reveal: traits::Reveal, | |
1560 | } | |
1561 | ||
1562 | impl<'tcx> ParamEnv<'tcx> { | |
0531ce1d XL |
1563 | /// Construct a trait environment suitable for contexts where |
1564 | /// there are no where clauses in scope. Hidden types (like `impl | |
1565 | /// Trait`) are left hidden, so this is suitable for ordinary | |
1566 | /// type-checking. | |
1567 | pub fn empty() -> Self { | |
1568 | Self::new(ty::Slice::empty(), Reveal::UserFacing) | |
1569 | } | |
1570 | ||
1571 | /// Construct a trait environment with no where clauses in scope | |
1572 | /// where the values of all `impl Trait` and other hidden types | |
1573 | /// are revealed. This is suitable for monomorphized, post-typeck | |
94b46f34 | 1574 | /// environments like codegen or doing optimizations. |
0531ce1d XL |
1575 | /// |
1576 | /// NB. If you want to have predicates in scope, use `ParamEnv::new`, | |
1577 | /// or invoke `param_env.with_reveal_all()`. | |
1578 | pub fn reveal_all() -> Self { | |
1579 | Self::new(ty::Slice::empty(), Reveal::All) | |
1580 | } | |
1581 | ||
1582 | /// Construct a trait environment with the given set of predicates. | |
1583 | pub fn new(caller_bounds: &'tcx ty::Slice<ty::Predicate<'tcx>>, | |
1584 | reveal: Reveal) | |
1585 | -> Self { | |
1586 | ty::ParamEnv { caller_bounds, reveal } | |
1587 | } | |
1588 | ||
1589 | /// Returns a new parameter environment with the same clauses, but | |
1590 | /// which "reveals" the true results of projections in all cases | |
1591 | /// (even for associated types that are specializable). This is | |
94b46f34 | 1592 | /// the desired behavior during codegen and certain other special |
0531ce1d XL |
1593 | /// contexts; normally though we want to use `Reveal::UserFacing`, |
1594 | /// which is the default. | |
1595 | pub fn with_reveal_all(self) -> Self { | |
1596 | ty::ParamEnv { reveal: Reveal::All, ..self } | |
1597 | } | |
1598 | ||
1599 | /// Returns this same environment but with no caller bounds. | |
1600 | pub fn without_caller_bounds(self) -> Self { | |
1601 | ty::ParamEnv { caller_bounds: ty::Slice::empty(), ..self } | |
1602 | } | |
1603 | ||
7cac9316 | 1604 | /// Creates a suitable environment in which to perform trait |
0531ce1d XL |
1605 | /// queries on the given value. When type-checking, this is simply |
1606 | /// the pair of the environment plus value. But when reveal is set to | |
1607 | /// All, then if `value` does not reference any type parameters, we will | |
1608 | /// pair it with the empty environment. This improves caching and is generally | |
1609 | /// invisible. | |
e9174d1e | 1610 | /// |
0531ce1d XL |
1611 | /// NB: We preserve the environment when type-checking because it |
1612 | /// is possible for the user to have wacky where-clauses like | |
7cac9316 | 1613 | /// `where Box<u32>: Copy`, which are clearly never |
0531ce1d XL |
1614 | /// satisfiable. We generally want to behave as if they were true, |
1615 | /// although the surrounding function is never reachable. | |
7cac9316 | 1616 | pub fn and<T: TypeFoldable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> { |
0531ce1d XL |
1617 | match self.reveal { |
1618 | Reveal::UserFacing => { | |
1619 | ParamEnvAnd { | |
1620 | param_env: self, | |
1621 | value, | |
1622 | } | |
e9174d1e | 1623 | } |
0531ce1d XL |
1624 | |
1625 | Reveal::All => { | |
83c7162d XL |
1626 | if value.has_skol() |
1627 | || value.needs_infer() | |
1628 | || value.has_param_types() | |
1629 | || value.has_self_ty() | |
1630 | { | |
0531ce1d XL |
1631 | ParamEnvAnd { |
1632 | param_env: self, | |
1633 | value, | |
1634 | } | |
1635 | } else { | |
1636 | ParamEnvAnd { | |
1637 | param_env: self.without_caller_bounds(), | |
1638 | value, | |
1639 | } | |
1640 | } | |
e9174d1e SL |
1641 | } |
1642 | } | |
1643 | } | |
1644 | } | |
1645 | ||
7cac9316 XL |
1646 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] |
1647 | pub struct ParamEnvAnd<'tcx, T> { | |
1648 | pub param_env: ParamEnv<'tcx>, | |
1649 | pub value: T, | |
1650 | } | |
1651 | ||
1652 | impl<'tcx, T> ParamEnvAnd<'tcx, T> { | |
1653 | pub fn into_parts(self) -> (ParamEnv<'tcx>, T) { | |
1654 | (self.param_env, self.value) | |
1655 | } | |
1656 | } | |
1657 | ||
0531ce1d XL |
1658 | impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>> for ParamEnvAnd<'gcx, T> |
1659 | where T: HashStable<StableHashingContext<'a>> | |
ea8adc8c XL |
1660 | { |
1661 | fn hash_stable<W: StableHasherResult>(&self, | |
0531ce1d | 1662 | hcx: &mut StableHashingContext<'a>, |
ea8adc8c XL |
1663 | hasher: &mut StableHasher<W>) { |
1664 | let ParamEnvAnd { | |
1665 | ref param_env, | |
1666 | ref value | |
1667 | } = *self; | |
1668 | ||
1669 | param_env.hash_stable(hcx, hasher); | |
1670 | value.hash_stable(hcx, hasher); | |
1671 | } | |
1672 | } | |
1673 | ||
8bb4bdeb XL |
1674 | #[derive(Copy, Clone, Debug)] |
1675 | pub struct Destructor { | |
1676 | /// The def-id of the destructor method | |
1677 | pub did: DefId, | |
8bb4bdeb XL |
1678 | } |
1679 | ||
e9174d1e | 1680 | bitflags! { |
ea8adc8c XL |
1681 | pub struct AdtFlags: u32 { |
1682 | const NO_ADT_FLAGS = 0; | |
1683 | const IS_ENUM = 1 << 0; | |
1684 | const IS_PHANTOM_DATA = 1 << 1; | |
1685 | const IS_FUNDAMENTAL = 1 << 2; | |
1686 | const IS_UNION = 1 << 3; | |
1687 | const IS_BOX = 1 << 4; | |
abe05a73 XL |
1688 | /// Indicates whether this abstract data type will be expanded on in future (new |
1689 | /// fields/variants) and as such, whether downstream crates must match exhaustively on the | |
1690 | /// fields/variants of this data type. | |
1691 | /// | |
ff7c6d11 | 1692 | /// See RFC 2008 (<https://github.com/rust-lang/rfcs/pull/2008>). |
abe05a73 | 1693 | const IS_NON_EXHAUSTIVE = 1 << 5; |
e9174d1e SL |
1694 | } |
1695 | } | |
1696 | ||
32a655c1 | 1697 | #[derive(Debug)] |
476ff2be | 1698 | pub struct VariantDef { |
b039eaaf SL |
1699 | /// The variant's DefId. If this is a tuple-like struct, |
1700 | /// this is the DefId of the struct's ctor. | |
e9174d1e SL |
1701 | pub did: DefId, |
1702 | pub name: Name, // struct's name if this is a struct | |
8bb4bdeb | 1703 | pub discr: VariantDiscr, |
476ff2be | 1704 | pub fields: Vec<FieldDef>, |
c30ab7b3 | 1705 | pub ctor_kind: CtorKind, |
e9174d1e SL |
1706 | } |
1707 | ||
8bb4bdeb XL |
1708 | #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] |
1709 | pub enum VariantDiscr { | |
1710 | /// Explicit value for this variant, i.e. `X = 123`. | |
1711 | /// The `DefId` corresponds to the embedded constant. | |
1712 | Explicit(DefId), | |
1713 | ||
1714 | /// The previous variant's discriminant plus one. | |
1715 | /// For efficiency reasons, the distance from the | |
1716 | /// last `Explicit` discriminant is being stored, | |
1717 | /// or `0` for the first variant, if it has none. | |
1718 | Relative(usize), | |
1719 | } | |
1720 | ||
32a655c1 | 1721 | #[derive(Debug)] |
476ff2be | 1722 | pub struct FieldDef { |
e9174d1e | 1723 | pub did: DefId, |
94b46f34 | 1724 | pub ident: Ident, |
54a0048b | 1725 | pub vis: Visibility, |
e9174d1e SL |
1726 | } |
1727 | ||
1728 | /// The definition of an abstract data type - a struct or enum. | |
1729 | /// | |
1730 | /// These are all interned (by intern_adt_def) into the adt_defs | |
1731 | /// table. | |
476ff2be | 1732 | pub struct AdtDef { |
e9174d1e | 1733 | pub did: DefId, |
476ff2be | 1734 | pub variants: Vec<VariantDef>, |
8bb4bdeb XL |
1735 | flags: AdtFlags, |
1736 | pub repr: ReprOptions, | |
e9174d1e SL |
1737 | } |
1738 | ||
94b46f34 XL |
1739 | impl PartialOrd for AdtDef { |
1740 | fn partial_cmp(&self, other: &AdtDef) -> Option<Ordering> { | |
1741 | Some(self.cmp(&other)) | |
1742 | } | |
1743 | } | |
1744 | ||
1745 | /// There should be only one AdtDef for each `did`, therefore | |
1746 | /// it is fine to implement `Ord` only based on `did`. | |
1747 | impl Ord for AdtDef { | |
1748 | fn cmp(&self, other: &AdtDef) -> Ordering { | |
1749 | self.did.cmp(&other.did) | |
1750 | } | |
1751 | } | |
1752 | ||
476ff2be SL |
1753 | impl PartialEq for AdtDef { |
1754 | // AdtDef are always interned and this is part of TyS equality | |
e9174d1e | 1755 | #[inline] |
8faf50e0 | 1756 | fn eq(&self, other: &Self) -> bool { ptr::eq(self, other) } |
e9174d1e SL |
1757 | } |
1758 | ||
476ff2be | 1759 | impl Eq for AdtDef {} |
e9174d1e | 1760 | |
476ff2be | 1761 | impl Hash for AdtDef { |
e9174d1e SL |
1762 | #[inline] |
1763 | fn hash<H: Hasher>(&self, s: &mut H) { | |
476ff2be | 1764 | (self as *const AdtDef).hash(s) |
e9174d1e SL |
1765 | } |
1766 | } | |
1767 | ||
476ff2be | 1768 | impl<'tcx> serialize::UseSpecializedEncodable for &'tcx AdtDef { |
9e0c209e | 1769 | fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { |
9cc50fc6 SL |
1770 | self.did.encode(s) |
1771 | } | |
1772 | } | |
1773 | ||
476ff2be | 1774 | impl<'tcx> serialize::UseSpecializedDecodable for &'tcx AdtDef {} |
e9174d1e | 1775 | |
cc61c64b | 1776 | |
0531ce1d | 1777 | impl<'a> HashStable<StableHashingContext<'a>> for AdtDef { |
cc61c64b | 1778 | fn hash_stable<W: StableHasherResult>(&self, |
0531ce1d | 1779 | hcx: &mut StableHashingContext<'a>, |
cc61c64b | 1780 | hasher: &mut StableHasher<W>) { |
2c00a5a8 XL |
1781 | thread_local! { |
1782 | static CACHE: RefCell<FxHashMap<usize, Fingerprint>> = | |
1783 | RefCell::new(FxHashMap()); | |
1784 | } | |
1785 | ||
1786 | let hash: Fingerprint = CACHE.with(|cache| { | |
1787 | let addr = self as *const AdtDef as usize; | |
1788 | *cache.borrow_mut().entry(addr).or_insert_with(|| { | |
1789 | let ty::AdtDef { | |
1790 | did, | |
1791 | ref variants, | |
1792 | ref flags, | |
1793 | ref repr, | |
1794 | } = *self; | |
cc61c64b | 1795 | |
2c00a5a8 XL |
1796 | let mut hasher = StableHasher::new(); |
1797 | did.hash_stable(hcx, &mut hasher); | |
1798 | variants.hash_stable(hcx, &mut hasher); | |
1799 | flags.hash_stable(hcx, &mut hasher); | |
1800 | repr.hash_stable(hcx, &mut hasher); | |
1801 | ||
1802 | hasher.finish() | |
1803 | }) | |
1804 | }); | |
1805 | ||
1806 | hash.hash_stable(hcx, hasher); | |
cc61c64b XL |
1807 | } |
1808 | } | |
1809 | ||
0531ce1d | 1810 | #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] |
9e0c209e | 1811 | pub enum AdtKind { Struct, Union, Enum } |
e9174d1e | 1812 | |
cc61c64b XL |
1813 | bitflags! { |
1814 | #[derive(RustcEncodable, RustcDecodable, Default)] | |
ea8adc8c XL |
1815 | pub struct ReprFlags: u8 { |
1816 | const IS_C = 1 << 0; | |
83c7162d XL |
1817 | const IS_SIMD = 1 << 1; |
1818 | const IS_TRANSPARENT = 1 << 2; | |
cc61c64b | 1819 | // Internal only for now. If true, don't reorder fields. |
83c7162d | 1820 | const IS_LINEAR = 1 << 3; |
cc61c64b XL |
1821 | |
1822 | // Any of these flags being set prevent field reordering optimisation. | |
1823 | const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits | | |
cc61c64b | 1824 | ReprFlags::IS_SIMD.bits | |
ea8adc8c | 1825 | ReprFlags::IS_LINEAR.bits; |
cc61c64b XL |
1826 | } |
1827 | } | |
1828 | ||
1829 | impl_stable_hash_for!(struct ReprFlags { | |
1830 | bits | |
1831 | }); | |
1832 | ||
1833 | ||
1834 | ||
8bb4bdeb XL |
1835 | /// Represents the repr options provided by the user, |
1836 | #[derive(Copy, Clone, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)] | |
1837 | pub struct ReprOptions { | |
8bb4bdeb | 1838 | pub int: Option<attr::IntType>, |
041b39d2 | 1839 | pub align: u32, |
83c7162d | 1840 | pub pack: u32, |
cc61c64b | 1841 | pub flags: ReprFlags, |
8bb4bdeb XL |
1842 | } |
1843 | ||
cc61c64b XL |
1844 | impl_stable_hash_for!(struct ReprOptions { |
1845 | align, | |
83c7162d | 1846 | pack, |
cc61c64b XL |
1847 | int, |
1848 | flags | |
1849 | }); | |
1850 | ||
8bb4bdeb XL |
1851 | impl ReprOptions { |
1852 | pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions { | |
cc61c64b XL |
1853 | let mut flags = ReprFlags::empty(); |
1854 | let mut size = None; | |
1855 | let mut max_align = 0; | |
83c7162d | 1856 | let mut min_pack = 0; |
8bb4bdeb XL |
1857 | for attr in tcx.get_attrs(did).iter() { |
1858 | for r in attr::find_repr_attrs(tcx.sess.diagnostic(), attr) { | |
cc61c64b | 1859 | flags.insert(match r { |
2c00a5a8 | 1860 | attr::ReprC => ReprFlags::IS_C, |
83c7162d XL |
1861 | attr::ReprPacked(pack) => { |
1862 | min_pack = if min_pack > 0 { | |
1863 | cmp::min(pack, min_pack) | |
1864 | } else { | |
1865 | pack | |
1866 | }; | |
1867 | ReprFlags::empty() | |
1868 | }, | |
2c00a5a8 | 1869 | attr::ReprTransparent => ReprFlags::IS_TRANSPARENT, |
cc61c64b XL |
1870 | attr::ReprSimd => ReprFlags::IS_SIMD, |
1871 | attr::ReprInt(i) => { | |
1872 | size = Some(i); | |
1873 | ReprFlags::empty() | |
1874 | }, | |
1875 | attr::ReprAlign(align) => { | |
1876 | max_align = cmp::max(align, max_align); | |
1877 | ReprFlags::empty() | |
1878 | }, | |
1879 | }); | |
8bb4bdeb XL |
1880 | } |
1881 | } | |
1882 | ||
cc61c64b XL |
1883 | // This is here instead of layout because the choice must make it into metadata. |
1884 | if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.item_path_str(did))) { | |
1885 | flags.insert(ReprFlags::IS_LINEAR); | |
1886 | } | |
83c7162d | 1887 | ReprOptions { int: size, align: max_align, pack: min_pack, flags: flags } |
8bb4bdeb XL |
1888 | } |
1889 | ||
cc61c64b XL |
1890 | #[inline] |
1891 | pub fn simd(&self) -> bool { self.flags.contains(ReprFlags::IS_SIMD) } | |
1892 | #[inline] | |
1893 | pub fn c(&self) -> bool { self.flags.contains(ReprFlags::IS_C) } | |
1894 | #[inline] | |
83c7162d | 1895 | pub fn packed(&self) -> bool { self.pack > 0 } |
cc61c64b | 1896 | #[inline] |
2c00a5a8 XL |
1897 | pub fn transparent(&self) -> bool { self.flags.contains(ReprFlags::IS_TRANSPARENT) } |
1898 | #[inline] | |
cc61c64b XL |
1899 | pub fn linear(&self) -> bool { self.flags.contains(ReprFlags::IS_LINEAR) } |
1900 | ||
8bb4bdeb | 1901 | pub fn discr_type(&self) -> attr::IntType { |
2c00a5a8 | 1902 | self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize)) |
8bb4bdeb XL |
1903 | } |
1904 | ||
1905 | /// Returns true if this `#[repr()]` should inhabit "smart enum | |
1906 | /// layout" optimizations, such as representing `Foo<&T>` as a | |
1907 | /// single pointer. | |
1908 | pub fn inhibit_enum_layout_opt(&self) -> bool { | |
cc61c64b | 1909 | self.c() || self.int.is_some() |
8bb4bdeb | 1910 | } |
83c7162d XL |
1911 | |
1912 | /// Returns true if this `#[repr()]` should inhibit struct field reordering | |
1913 | /// optimizations, such as with repr(C) or repr(packed(1)). | |
1914 | pub fn inhibit_struct_field_reordering_opt(&self) -> bool { | |
1915 | !(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1) | |
1916 | } | |
8bb4bdeb XL |
1917 | } |
1918 | ||
476ff2be | 1919 | impl<'a, 'gcx, 'tcx> AdtDef { |
8bb4bdeb | 1920 | fn new(tcx: TyCtxt, |
e9174d1e SL |
1921 | did: DefId, |
1922 | kind: AdtKind, | |
8bb4bdeb XL |
1923 | variants: Vec<VariantDef>, |
1924 | repr: ReprOptions) -> Self { | |
e9174d1e SL |
1925 | let mut flags = AdtFlags::NO_ADT_FLAGS; |
1926 | let attrs = tcx.get_attrs(did); | |
1927 | if attr::contains_name(&attrs, "fundamental") { | |
1928 | flags = flags | AdtFlags::IS_FUNDAMENTAL; | |
1929 | } | |
ea8adc8c | 1930 | if Some(did) == tcx.lang_items().phantom_data() { |
e9174d1e SL |
1931 | flags = flags | AdtFlags::IS_PHANTOM_DATA; |
1932 | } | |
ea8adc8c | 1933 | if Some(did) == tcx.lang_items().owned_box() { |
32a655c1 SL |
1934 | flags = flags | AdtFlags::IS_BOX; |
1935 | } | |
abe05a73 XL |
1936 | if tcx.has_attr(did, "non_exhaustive") { |
1937 | flags = flags | AdtFlags::IS_NON_EXHAUSTIVE; | |
1938 | } | |
9e0c209e SL |
1939 | match kind { |
1940 | AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM, | |
1941 | AdtKind::Union => flags = flags | AdtFlags::IS_UNION, | |
1942 | AdtKind::Struct => {} | |
e9174d1e | 1943 | } |
476ff2be | 1944 | AdtDef { |
041b39d2 XL |
1945 | did, |
1946 | variants, | |
1947 | flags, | |
1948 | repr, | |
e9174d1e SL |
1949 | } |
1950 | } | |
1951 | ||
9e0c209e SL |
1952 | #[inline] |
1953 | pub fn is_struct(&self) -> bool { | |
1954 | !self.is_union() && !self.is_enum() | |
1955 | } | |
1956 | ||
1957 | #[inline] | |
1958 | pub fn is_union(&self) -> bool { | |
8bb4bdeb | 1959 | self.flags.intersects(AdtFlags::IS_UNION) |
9e0c209e SL |
1960 | } |
1961 | ||
1962 | #[inline] | |
1963 | pub fn is_enum(&self) -> bool { | |
8bb4bdeb | 1964 | self.flags.intersects(AdtFlags::IS_ENUM) |
9e0c209e SL |
1965 | } |
1966 | ||
abe05a73 XL |
1967 | #[inline] |
1968 | pub fn is_non_exhaustive(&self) -> bool { | |
1969 | self.flags.intersects(AdtFlags::IS_NON_EXHAUSTIVE) | |
1970 | } | |
1971 | ||
e9174d1e SL |
1972 | /// Returns the kind of the ADT - Struct or Enum. |
1973 | #[inline] | |
1974 | pub fn adt_kind(&self) -> AdtKind { | |
9e0c209e | 1975 | if self.is_enum() { |
e9174d1e | 1976 | AdtKind::Enum |
9e0c209e SL |
1977 | } else if self.is_union() { |
1978 | AdtKind::Union | |
e9174d1e SL |
1979 | } else { |
1980 | AdtKind::Struct | |
1981 | } | |
1982 | } | |
1983 | ||
9e0c209e SL |
1984 | pub fn descr(&self) -> &'static str { |
1985 | match self.adt_kind() { | |
1986 | AdtKind::Struct => "struct", | |
1987 | AdtKind::Union => "union", | |
1988 | AdtKind::Enum => "enum", | |
1989 | } | |
1990 | } | |
1991 | ||
1992 | pub fn variant_descr(&self) -> &'static str { | |
1993 | match self.adt_kind() { | |
1994 | AdtKind::Struct => "struct", | |
1995 | AdtKind::Union => "union", | |
1996 | AdtKind::Enum => "variant", | |
1997 | } | |
1998 | } | |
1999 | ||
e9174d1e SL |
2000 | /// Returns whether this type is #[fundamental] for the purposes |
2001 | /// of coherence checking. | |
2002 | #[inline] | |
2003 | pub fn is_fundamental(&self) -> bool { | |
8bb4bdeb | 2004 | self.flags.intersects(AdtFlags::IS_FUNDAMENTAL) |
e9174d1e SL |
2005 | } |
2006 | ||
2007 | /// Returns true if this is PhantomData<T>. | |
2008 | #[inline] | |
2009 | pub fn is_phantom_data(&self) -> bool { | |
8bb4bdeb | 2010 | self.flags.intersects(AdtFlags::IS_PHANTOM_DATA) |
e9174d1e SL |
2011 | } |
2012 | ||
32a655c1 SL |
2013 | /// Returns true if this is Box<T>. |
2014 | #[inline] | |
2015 | pub fn is_box(&self) -> bool { | |
8bb4bdeb | 2016 | self.flags.intersects(AdtFlags::IS_BOX) |
32a655c1 SL |
2017 | } |
2018 | ||
e9174d1e | 2019 | /// Returns whether this type has a destructor. |
8bb4bdeb XL |
2020 | pub fn has_dtor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { |
2021 | self.destructor(tcx).is_some() | |
e9174d1e SL |
2022 | } |
2023 | ||
2c00a5a8 XL |
2024 | /// Asserts this is a struct or union and returns its unique variant. |
2025 | pub fn non_enum_variant(&self) -> &VariantDef { | |
2026 | assert!(self.is_struct() || self.is_union()); | |
e9174d1e SL |
2027 | &self.variants[0] |
2028 | } | |
2029 | ||
e9174d1e | 2030 | #[inline] |
a7813a04 | 2031 | pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> GenericPredicates<'gcx> { |
7cac9316 | 2032 | tcx.predicates_of(self.did) |
e9174d1e SL |
2033 | } |
2034 | ||
2035 | /// Returns an iterator over all fields contained | |
2036 | /// by this ADT. | |
2037 | #[inline] | |
476ff2be SL |
2038 | pub fn all_fields<'s>(&'s self) -> impl Iterator<Item = &'s FieldDef> { |
2039 | self.variants.iter().flat_map(|v| v.fields.iter()) | |
e9174d1e SL |
2040 | } |
2041 | ||
e9174d1e SL |
2042 | pub fn is_payloadfree(&self) -> bool { |
2043 | !self.variants.is_empty() && | |
2044 | self.variants.iter().all(|v| v.fields.is_empty()) | |
2045 | } | |
2046 | ||
476ff2be | 2047 | pub fn variant_with_id(&self, vid: DefId) -> &VariantDef { |
e9174d1e SL |
2048 | self.variants |
2049 | .iter() | |
2050 | .find(|v| v.did == vid) | |
2051 | .expect("variant_with_id: unknown variant") | |
2052 | } | |
2053 | ||
2054 | pub fn variant_index_with_id(&self, vid: DefId) -> usize { | |
2055 | self.variants | |
2056 | .iter() | |
2057 | .position(|v| v.did == vid) | |
2058 | .expect("variant_index_with_id: unknown variant") | |
2059 | } | |
2060 | ||
476ff2be | 2061 | pub fn variant_of_def(&self, def: Def) -> &VariantDef { |
e9174d1e | 2062 | match def { |
c30ab7b3 SL |
2063 | Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid), |
2064 | Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) | | |
2c00a5a8 | 2065 | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => self.non_enum_variant(), |
54a0048b | 2066 | _ => bug!("unexpected def {:?} in variant_of_def", def) |
e9174d1e SL |
2067 | } |
2068 | } | |
2069 | ||
cc61c64b | 2070 | #[inline] |
0531ce1d XL |
2071 | pub fn eval_explicit_discr( |
2072 | &self, | |
2073 | tcx: TyCtxt<'a, 'gcx, 'tcx>, | |
2074 | expr_did: DefId, | |
2075 | ) -> Option<Discr<'tcx>> { | |
2076 | let param_env = ParamEnv::empty(); | |
2077 | let repr_type = self.repr.discr_type(); | |
2078 | let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did); | |
2079 | let instance = ty::Instance::new(expr_did, substs); | |
2080 | let cid = GlobalId { | |
2081 | instance, | |
2082 | promoted: None | |
2083 | }; | |
2084 | match tcx.const_eval(param_env.and(cid)) { | |
94b46f34 XL |
2085 | Ok(val) => { |
2086 | // FIXME: Find the right type and use it instead of `val.ty` here | |
2087 | if let Some(b) = val.assert_bits(tcx.global_tcx(), param_env.and(val.ty)) { | |
2088 | trace!("discriminants: {} ({:?})", b, repr_type); | |
2089 | Some(Discr { | |
2090 | val: b, | |
2091 | ty: val.ty, | |
2092 | }) | |
2093 | } else { | |
2094 | info!("invalid enum discriminant: {:#?}", val); | |
8faf50e0 | 2095 | ::mir::interpret::struct_error( |
94b46f34 XL |
2096 | tcx.at(tcx.def_span(expr_did)), |
2097 | "constant evaluation of enum discriminant resulted in non-integer", | |
2098 | ).emit(); | |
2099 | None | |
2100 | } | |
0531ce1d XL |
2101 | } |
2102 | Err(err) => { | |
94b46f34 XL |
2103 | err.report_as_error( |
2104 | tcx.at(tcx.def_span(expr_did)), | |
2105 | "could not evaluate enum discriminant", | |
2106 | ); | |
0531ce1d XL |
2107 | if !expr_did.is_local() { |
2108 | span_bug!(tcx.def_span(expr_did), | |
2109 | "variant discriminant evaluation succeeded \ | |
2110 | in its crate but failed locally"); | |
2111 | } | |
2112 | None | |
2113 | } | |
0531ce1d XL |
2114 | } |
2115 | } | |
2116 | ||
2117 | #[inline] | |
2118 | pub fn discriminants( | |
2119 | &'a self, | |
2120 | tcx: TyCtxt<'a, 'gcx, 'tcx>, | |
2121 | ) -> impl Iterator<Item=Discr<'tcx>> + Captures<'gcx> + 'a { | |
8bb4bdeb XL |
2122 | let repr_type = self.repr.discr_type(); |
2123 | let initial = repr_type.initial_discriminant(tcx.global_tcx()); | |
0531ce1d | 2124 | let mut prev_discr = None::<Discr<'tcx>>; |
8bb4bdeb | 2125 | self.variants.iter().map(move |v| { |
0531ce1d | 2126 | let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx)); |
8bb4bdeb | 2127 | if let VariantDiscr::Explicit(expr_did) = v.discr { |
0531ce1d XL |
2128 | if let Some(new_discr) = self.eval_explicit_discr(tcx, expr_did) { |
2129 | discr = new_discr; | |
8bb4bdeb XL |
2130 | } |
2131 | } | |
2132 | prev_discr = Some(discr); | |
2133 | ||
2134 | discr | |
2135 | }) | |
e9174d1e SL |
2136 | } |
2137 | ||
cc61c64b XL |
2138 | /// Compute the discriminant value used by a specific variant. |
2139 | /// Unlike `discriminants`, this is (amortized) constant-time, | |
2140 | /// only doing at most one query for evaluating an explicit | |
2141 | /// discriminant (the last one before the requested variant), | |
2142 | /// assuming there are no constant-evaluation errors there. | |
2143 | pub fn discriminant_for_variant(&self, | |
2144 | tcx: TyCtxt<'a, 'gcx, 'tcx>, | |
2145 | variant_index: usize) | |
0531ce1d XL |
2146 | -> Discr<'tcx> { |
2147 | let (val, offset) = self.discriminant_def_for_variant(variant_index); | |
2148 | let explicit_value = val | |
2149 | .and_then(|expr_did| self.eval_explicit_discr(tcx, expr_did)) | |
2150 | .unwrap_or_else(|| self.repr.discr_type().initial_discriminant(tcx.global_tcx())); | |
2151 | explicit_value.checked_add(tcx, offset as u128).0 | |
2152 | } | |
2153 | ||
2154 | /// Yields a DefId for the discriminant and an offset to add to it | |
2155 | /// Alternatively, if there is no explicit discriminant, returns the | |
2156 | /// inferred discriminant directly | |
2157 | pub fn discriminant_def_for_variant( | |
2158 | &self, | |
2159 | variant_index: usize, | |
2160 | ) -> (Option<DefId>, usize) { | |
cc61c64b | 2161 | let mut explicit_index = variant_index; |
0531ce1d | 2162 | let expr_did; |
cc61c64b XL |
2163 | loop { |
2164 | match self.variants[explicit_index].discr { | |
0531ce1d XL |
2165 | ty::VariantDiscr::Relative(0) => { |
2166 | expr_did = None; | |
2167 | break; | |
2168 | }, | |
cc61c64b XL |
2169 | ty::VariantDiscr::Relative(distance) => { |
2170 | explicit_index -= distance; | |
2171 | } | |
0531ce1d XL |
2172 | ty::VariantDiscr::Explicit(did) => { |
2173 | expr_did = Some(did); | |
2174 | break; | |
cc61c64b XL |
2175 | } |
2176 | } | |
2177 | } | |
0531ce1d | 2178 | (expr_did, variant_index - explicit_index) |
cc61c64b XL |
2179 | } |
2180 | ||
8bb4bdeb | 2181 | pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Destructor> { |
7cac9316 | 2182 | tcx.adt_destructor(self.did) |
e9174d1e SL |
2183 | } |
2184 | ||
cc61c64b | 2185 | /// Returns a list of types such that `Self: Sized` if and only |
a7813a04 XL |
2186 | /// if that type is Sized, or `TyErr` if this type is recursive. |
2187 | /// | |
a7813a04 XL |
2188 | /// Oddly enough, checking that the sized-constraint is Sized is |
2189 | /// actually more expressive than checking all members: | |
2190 | /// the Sized trait is inductive, so an associated type that references | |
2191 | /// Self would prevent its containing ADT from being Sized. | |
2192 | /// | |
2193 | /// Due to normalization being eager, this applies even if | |
2194 | /// the associated type is behind a pointer, e.g. issue #31299. | |
cc61c64b | 2195 | pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx [Ty<'tcx>] { |
94b46f34 | 2196 | match tcx.try_adt_sized_constraint(DUMMY_SP, self.did) { |
cc61c64b | 2197 | Ok(tys) => tys, |
3b2f2976 | 2198 | Err(mut bug) => { |
cc61c64b XL |
2199 | debug!("adt_sized_constraint: {:?} is recursive", self); |
2200 | // This should be reported as an error by `check_representable`. | |
2201 | // | |
2202 | // Consider the type as Sized in the meanwhile to avoid | |
3b2f2976 XL |
2203 | // further errors. Delay our `bug` diagnostic here to get |
2204 | // emitted later as well in case we accidentally otherwise don't | |
2205 | // emit an error. | |
2206 | bug.delay_as_bug(); | |
cc61c64b | 2207 | tcx.intern_type_list(&[tcx.types.err]) |
a7813a04 XL |
2208 | } |
2209 | } | |
2210 | } | |
2211 | ||
476ff2be SL |
2212 | fn sized_constraint_for_ty(&self, |
2213 | tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
476ff2be SL |
2214 | ty: Ty<'tcx>) |
2215 | -> Vec<Ty<'tcx>> { | |
a7813a04 XL |
2216 | let result = match ty.sty { |
2217 | TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | | |
32a655c1 | 2218 | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) | |
ea8adc8c | 2219 | TyArray(..) | TyClosure(..) | TyGenerator(..) | TyNever => { |
a7813a04 XL |
2220 | vec![] |
2221 | } | |
2222 | ||
2c00a5a8 XL |
2223 | TyStr | |
2224 | TyDynamic(..) | | |
2225 | TySlice(_) | | |
2226 | TyForeign(..) | | |
2227 | TyError | | |
2228 | TyGeneratorWitness(..) => { | |
a7813a04 XL |
2229 | // these are never sized - return the target type |
2230 | vec![ty] | |
2231 | } | |
2232 | ||
0531ce1d | 2233 | TyTuple(ref tys) => { |
9e0c209e SL |
2234 | match tys.last() { |
2235 | None => vec![], | |
cc61c64b | 2236 | Some(ty) => self.sized_constraint_for_ty(tcx, ty) |
9e0c209e | 2237 | } |
a7813a04 XL |
2238 | } |
2239 | ||
9e0c209e | 2240 | TyAdt(adt, substs) => { |
a7813a04 | 2241 | // recursive case |
cc61c64b | 2242 | let adt_tys = adt.sized_constraint(tcx); |
a7813a04 | 2243 | debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", |
cc61c64b XL |
2244 | ty, adt_tys); |
2245 | adt_tys.iter() | |
2246 | .map(|ty| ty.subst(tcx, substs)) | |
2247 | .flat_map(|ty| self.sized_constraint_for_ty(tcx, ty)) | |
2248 | .collect() | |
a7813a04 XL |
2249 | } |
2250 | ||
5bcae85e | 2251 | TyProjection(..) | TyAnon(..) => { |
a7813a04 XL |
2252 | // must calculate explicitly. |
2253 | // FIXME: consider special-casing always-Sized projections | |
2254 | vec![ty] | |
2255 | } | |
2256 | ||
2257 | TyParam(..) => { | |
2258 | // perf hack: if there is a `T: Sized` bound, then | |
2259 | // we know that `T` is Sized and do not need to check | |
2260 | // it on the impl. | |
2261 | ||
ea8adc8c | 2262 | let sized_trait = match tcx.lang_items().sized_trait() { |
a7813a04 XL |
2263 | Some(x) => x, |
2264 | _ => return vec![ty] | |
2265 | }; | |
83c7162d | 2266 | let sized_predicate = Binder::dummy(TraitRef { |
a7813a04 | 2267 | def_id: sized_trait, |
c30ab7b3 | 2268 | substs: tcx.mk_substs_trait(ty, &[]) |
a7813a04 | 2269 | }).to_predicate(); |
7cac9316 | 2270 | let predicates = tcx.predicates_of(self.did).predicates; |
a7813a04 XL |
2271 | if predicates.into_iter().any(|p| p == sized_predicate) { |
2272 | vec![] | |
2273 | } else { | |
2274 | vec![ty] | |
2275 | } | |
2276 | } | |
2277 | ||
2278 | TyInfer(..) => { | |
2279 | bug!("unexpected type `{:?}` in sized_constraint_for_ty", | |
2280 | ty) | |
2281 | } | |
2282 | }; | |
2283 | debug!("sized_constraint_for_ty({:?}) = {:?}", ty, result); | |
2284 | result | |
2285 | } | |
2286 | } | |
2287 | ||
476ff2be | 2288 | impl<'a, 'gcx, 'tcx> FieldDef { |
a7813a04 | 2289 | pub fn ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, subst: &Substs<'tcx>) -> Ty<'tcx> { |
7cac9316 | 2290 | tcx.type_of(self.did).subst(tcx, subst) |
e9174d1e | 2291 | } |
e9174d1e SL |
2292 | } |
2293 | ||
ff7c6d11 XL |
2294 | /// Represents the various closure traits in the Rust language. This |
2295 | /// will determine the type of the environment (`self`, in the | |
2296 | /// desuaring) argument that the closure expects. | |
2297 | /// | |
2298 | /// You can get the environment type of a closure using | |
2299 | /// `tcx.closure_env_ty()`. | |
a7813a04 | 2300 | #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
2301 | pub enum ClosureKind { |
2302 | // Warning: Ordering is significant here! The ordering is chosen | |
2303 | // because the trait Fn is a subtrait of FnMut and so in turn, and | |
2304 | // hence we order it so that Fn < FnMut < FnOnce. | |
54a0048b SL |
2305 | Fn, |
2306 | FnMut, | |
2307 | FnOnce, | |
e9174d1e SL |
2308 | } |
2309 | ||
a7813a04 | 2310 | impl<'a, 'tcx> ClosureKind { |
ff7c6d11 XL |
2311 | // This is the initial value used when doing upvar inference. |
2312 | pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn; | |
2313 | ||
a7813a04 | 2314 | pub fn trait_did(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefId { |
476ff2be SL |
2315 | match *self { |
2316 | ClosureKind::Fn => tcx.require_lang_item(FnTraitLangItem), | |
54a0048b | 2317 | ClosureKind::FnMut => { |
476ff2be | 2318 | tcx.require_lang_item(FnMutTraitLangItem) |
e9174d1e | 2319 | } |
54a0048b | 2320 | ClosureKind::FnOnce => { |
476ff2be | 2321 | tcx.require_lang_item(FnOnceTraitLangItem) |
e9174d1e | 2322 | } |
e9174d1e SL |
2323 | } |
2324 | } | |
2325 | ||
2326 | /// True if this a type that impls this closure kind | |
2327 | /// must also implement `other`. | |
2328 | pub fn extends(self, other: ty::ClosureKind) -> bool { | |
2329 | match (self, other) { | |
54a0048b SL |
2330 | (ClosureKind::Fn, ClosureKind::Fn) => true, |
2331 | (ClosureKind::Fn, ClosureKind::FnMut) => true, | |
2332 | (ClosureKind::Fn, ClosureKind::FnOnce) => true, | |
2333 | (ClosureKind::FnMut, ClosureKind::FnMut) => true, | |
2334 | (ClosureKind::FnMut, ClosureKind::FnOnce) => true, | |
2335 | (ClosureKind::FnOnce, ClosureKind::FnOnce) => true, | |
e9174d1e SL |
2336 | _ => false, |
2337 | } | |
2338 | } | |
ff7c6d11 XL |
2339 | |
2340 | /// Returns the representative scalar type for this closure kind. | |
2341 | /// See `TyS::to_opt_closure_kind` for more details. | |
2342 | pub fn to_ty(self, tcx: TyCtxt<'_, '_, 'tcx>) -> Ty<'tcx> { | |
2343 | match self { | |
2344 | ty::ClosureKind::Fn => tcx.types.i8, | |
2345 | ty::ClosureKind::FnMut => tcx.types.i16, | |
2346 | ty::ClosureKind::FnOnce => tcx.types.i32, | |
2347 | } | |
2348 | } | |
e9174d1e SL |
2349 | } |
2350 | ||
2351 | impl<'tcx> TyS<'tcx> { | |
2352 | /// Iterator that walks `self` and any types reachable from | |
2353 | /// `self`, in depth-first order. Note that just walks the types | |
2354 | /// that appear in `self`, it does not descend into the fields of | |
2355 | /// structs or variants. For example: | |
2356 | /// | |
2357 | /// ```notrust | |
2358 | /// isize => { isize } | |
2359 | /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize } | |
2360 | /// [isize] => { [isize], isize } | |
2361 | /// ``` | |
2362 | pub fn walk(&'tcx self) -> TypeWalker<'tcx> { | |
2363 | TypeWalker::new(self) | |
2364 | } | |
2365 | ||
2366 | /// Iterator that walks the immediate children of `self`. Hence | |
2367 | /// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]` | |
2368 | /// (but not `i32`, like `walk`). | |
476ff2be | 2369 | pub fn walk_shallow(&'tcx self) -> AccIntoIter<walk::TypeWalkerArray<'tcx>> { |
e9174d1e SL |
2370 | walk::walk_shallow(self) |
2371 | } | |
2372 | ||
2373 | /// Walks `ty` and any types appearing within `ty`, invoking the | |
2374 | /// callback `f` on each type. If the callback returns false, then the | |
2375 | /// children of the current type are ignored. | |
2376 | /// | |
2377 | /// Note: prefer `ty.walk()` where possible. | |
2378 | pub fn maybe_walk<F>(&'tcx self, mut f: F) | |
2379 | where F : FnMut(Ty<'tcx>) -> bool | |
2380 | { | |
2381 | let mut walker = self.walk(); | |
2382 | while let Some(ty) = walker.next() { | |
2383 | if !f(ty) { | |
2384 | walker.skip_current_subtree(); | |
2385 | } | |
2386 | } | |
2387 | } | |
2388 | } | |
2389 | ||
e9174d1e SL |
2390 | impl BorrowKind { |
2391 | pub fn from_mutbl(m: hir::Mutability) -> BorrowKind { | |
2392 | match m { | |
2393 | hir::MutMutable => MutBorrow, | |
2394 | hir::MutImmutable => ImmBorrow, | |
2395 | } | |
2396 | } | |
2397 | ||
2398 | /// Returns a mutability `m` such that an `&m T` pointer could be used to obtain this borrow | |
2399 | /// kind. Because borrow kinds are richer than mutabilities, we sometimes have to pick a | |
2400 | /// mutability that is stronger than necessary so that it at least *would permit* the borrow in | |
2401 | /// question. | |
2402 | pub fn to_mutbl_lossy(self) -> hir::Mutability { | |
2403 | match self { | |
2404 | MutBorrow => hir::MutMutable, | |
2405 | ImmBorrow => hir::MutImmutable, | |
2406 | ||
2407 | // We have no type corresponding to a unique imm borrow, so | |
2408 | // use `&mut`. It gives all the capabilities of an `&uniq` | |
2409 | // and hence is a safe "over approximation". | |
2410 | UniqueImmBorrow => hir::MutMutable, | |
2411 | } | |
2412 | } | |
2413 | ||
2414 | pub fn to_user_str(&self) -> &'static str { | |
2415 | match *self { | |
2416 | MutBorrow => "mutable", | |
2417 | ImmBorrow => "immutable", | |
2418 | UniqueImmBorrow => "uniquely immutable", | |
2419 | } | |
2420 | } | |
2421 | } | |
2422 | ||
cc61c64b XL |
2423 | #[derive(Debug, Clone)] |
2424 | pub enum Attributes<'gcx> { | |
0531ce1d | 2425 | Owned(Lrc<[ast::Attribute]>), |
cc61c64b XL |
2426 | Borrowed(&'gcx [ast::Attribute]) |
2427 | } | |
2428 | ||
2429 | impl<'gcx> ::std::ops::Deref for Attributes<'gcx> { | |
2430 | type Target = [ast::Attribute]; | |
2431 | ||
2432 | fn deref(&self) -> &[ast::Attribute] { | |
2433 | match self { | |
2434 | &Attributes::Owned(ref data) => &data, | |
2435 | &Attributes::Borrowed(data) => data | |
2436 | } | |
2437 | } | |
2438 | } | |
2439 | ||
a7813a04 | 2440 | impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { |
32a655c1 | 2441 | pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> { |
7cac9316 | 2442 | self.typeck_tables_of(self.hir.body_owner_def_id(body)) |
32a655c1 SL |
2443 | } |
2444 | ||
7cac9316 XL |
2445 | /// Returns an iterator of the def-ids for all body-owners in this |
2446 | /// crate. If you would prefer to iterate over the bodies | |
2447 | /// themselves, you can do `self.hir.krate().body_ids.iter()`. | |
0531ce1d XL |
2448 | pub fn body_owners( |
2449 | self, | |
2450 | ) -> impl Iterator<Item = DefId> + Captures<'tcx> + Captures<'gcx> + 'a { | |
7cac9316 XL |
2451 | self.hir.krate() |
2452 | .body_ids | |
2453 | .iter() | |
2454 | .map(move |&body_id| self.hir.body_owner_def_id(body_id)) | |
7453a54e SL |
2455 | } |
2456 | ||
94b46f34 XL |
2457 | pub fn par_body_owners<F: Fn(DefId) + sync::Sync + sync::Send>(self, f: F) { |
2458 | par_iter(&self.hir.krate().body_ids).for_each(|&body_id| { | |
2459 | f(self.hir.body_owner_def_id(body_id)) | |
2460 | }); | |
2461 | } | |
2462 | ||
a7813a04 | 2463 | pub fn expr_span(self, id: NodeId) -> Span { |
32a655c1 SL |
2464 | match self.hir.find(id) { |
2465 | Some(hir_map::NodeExpr(e)) => { | |
e9174d1e SL |
2466 | e.span |
2467 | } | |
2468 | Some(f) => { | |
54a0048b | 2469 | bug!("Node id {} is not an expr: {:?}", id, f); |
e9174d1e SL |
2470 | } |
2471 | None => { | |
54a0048b | 2472 | bug!("Node id {} is not present in the node map", id); |
e9174d1e SL |
2473 | } |
2474 | } | |
2475 | } | |
2476 | ||
476ff2be SL |
2477 | pub fn provided_trait_methods(self, id: DefId) -> Vec<AssociatedItem> { |
2478 | self.associated_items(id) | |
2479 | .filter(|item| item.kind == AssociatedKind::Method && item.defaultness.has_value()) | |
2480 | .collect() | |
e9174d1e SL |
2481 | } |
2482 | ||
8bb4bdeb XL |
2483 | pub fn trait_relevant_for_never(self, did: DefId) -> bool { |
2484 | self.associated_items(did).any(|item| { | |
2485 | item.relevant_for_never() | |
e9174d1e SL |
2486 | }) |
2487 | } | |
2488 | ||
7cac9316 XL |
2489 | pub fn opt_associated_item(self, def_id: DefId) -> Option<AssociatedItem> { |
2490 | let is_associated_item = if let Some(node_id) = self.hir.as_local_node_id(def_id) { | |
2491 | match self.hir.get(node_id) { | |
2492 | hir_map::NodeTraitItem(_) | hir_map::NodeImplItem(_) => true, | |
2493 | _ => false, | |
2494 | } | |
2495 | } else { | |
2496 | match self.describe_def(def_id).expect("no def for def-id") { | |
2497 | Def::AssociatedConst(_) | Def::Method(_) | Def::AssociatedTy(_) => true, | |
2498 | _ => false, | |
2499 | } | |
2500 | }; | |
8bb4bdeb | 2501 | |
7cac9316 XL |
2502 | if is_associated_item { |
2503 | Some(self.associated_item(def_id)) | |
2504 | } else { | |
2505 | None | |
2506 | } | |
e9174d1e SL |
2507 | } |
2508 | ||
476ff2be SL |
2509 | fn associated_item_from_trait_item_ref(self, |
2510 | parent_def_id: DefId, | |
7cac9316 | 2511 | parent_vis: &hir::Visibility, |
32a655c1 | 2512 | trait_item_ref: &hir::TraitItemRef) |
476ff2be | 2513 | -> AssociatedItem { |
32a655c1 SL |
2514 | let def_id = self.hir.local_def_id(trait_item_ref.id.node_id); |
2515 | let (kind, has_self) = match trait_item_ref.kind { | |
2516 | hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false), | |
2517 | hir::AssociatedItemKind::Method { has_self } => { | |
2518 | (ty::AssociatedKind::Method, has_self) | |
476ff2be | 2519 | } |
32a655c1 | 2520 | hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false), |
8faf50e0 | 2521 | hir::AssociatedItemKind::Existential => bug!("only impls can have existentials"), |
476ff2be SL |
2522 | }; |
2523 | ||
2524 | AssociatedItem { | |
8faf50e0 | 2525 | ident: trait_item_ref.ident, |
041b39d2 | 2526 | kind, |
7cac9316 XL |
2527 | // Visibility of trait items is inherited from their traits. |
2528 | vis: Visibility::from_hir(parent_vis, trait_item_ref.id.node_id, self), | |
32a655c1 | 2529 | defaultness: trait_item_ref.defaultness, |
041b39d2 | 2530 | def_id, |
476ff2be SL |
2531 | container: TraitContainer(parent_def_id), |
2532 | method_has_self_argument: has_self | |
2533 | } | |
2534 | } | |
2535 | ||
2536 | fn associated_item_from_impl_item_ref(self, | |
2537 | parent_def_id: DefId, | |
476ff2be SL |
2538 | impl_item_ref: &hir::ImplItemRef) |
2539 | -> AssociatedItem { | |
32a655c1 | 2540 | let def_id = self.hir.local_def_id(impl_item_ref.id.node_id); |
476ff2be SL |
2541 | let (kind, has_self) = match impl_item_ref.kind { |
2542 | hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false), | |
2543 | hir::AssociatedItemKind::Method { has_self } => { | |
2544 | (ty::AssociatedKind::Method, has_self) | |
2545 | } | |
2546 | hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false), | |
8faf50e0 | 2547 | hir::AssociatedItemKind::Existential => (ty::AssociatedKind::Existential, false), |
476ff2be SL |
2548 | }; |
2549 | ||
8faf50e0 XL |
2550 | AssociatedItem { |
2551 | ident: impl_item_ref.ident, | |
041b39d2 | 2552 | kind, |
7cac9316 XL |
2553 | // Visibility of trait impl items doesn't matter. |
2554 | vis: ty::Visibility::from_hir(&impl_item_ref.vis, impl_item_ref.id.node_id, self), | |
476ff2be | 2555 | defaultness: impl_item_ref.defaultness, |
041b39d2 | 2556 | def_id, |
476ff2be SL |
2557 | container: ImplContainer(parent_def_id), |
2558 | method_has_self_argument: has_self | |
2559 | } | |
2560 | } | |
2561 | ||
83c7162d XL |
2562 | pub fn field_index(self, node_id: NodeId, tables: &TypeckTables) -> usize { |
2563 | let hir_id = self.hir.node_to_hir_id(node_id); | |
2564 | tables.field_indices().get(hir_id).cloned().expect("no index for a field") | |
2565 | } | |
2566 | ||
2567 | pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> { | |
2568 | variant.fields.iter().position(|field| { | |
94b46f34 | 2569 | self.adjust_ident(ident, variant.did, DUMMY_NODE_ID).0 == field.ident.modern() |
83c7162d XL |
2570 | }) |
2571 | } | |
2572 | ||
0531ce1d XL |
2573 | pub fn associated_items( |
2574 | self, | |
2575 | def_id: DefId, | |
8faf50e0 | 2576 | ) -> impl Iterator<Item = AssociatedItem> + 'a { |
476ff2be | 2577 | let def_ids = self.associated_item_def_ids(def_id); |
0531ce1d | 2578 | Box::new((0..def_ids.len()).map(move |i| self.associated_item(def_ids[i]))) |
8faf50e0 | 2579 | as Box<dyn Iterator<Item = AssociatedItem> + 'a> |
e9174d1e SL |
2580 | } |
2581 | ||
cc61c64b XL |
2582 | /// Returns true if the impls are the same polarity and are implementing |
2583 | /// a trait which contains no items | |
2584 | pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool { | |
0531ce1d | 2585 | if !self.features().overlapping_marker_traits { |
cc61c64b XL |
2586 | return false; |
2587 | } | |
2588 | let trait1_is_empty = self.impl_trait_ref(def_id1) | |
2589 | .map_or(false, |trait_ref| { | |
2590 | self.associated_item_def_ids(trait_ref.def_id).is_empty() | |
2591 | }); | |
2592 | let trait2_is_empty = self.impl_trait_ref(def_id2) | |
2593 | .map_or(false, |trait_ref| { | |
2594 | self.associated_item_def_ids(trait_ref.def_id).is_empty() | |
2595 | }); | |
7cac9316 | 2596 | self.impl_polarity(def_id1) == self.impl_polarity(def_id2) |
cc61c64b XL |
2597 | && trait1_is_empty |
2598 | && trait2_is_empty | |
2599 | } | |
2600 | ||
5bcae85e SL |
2601 | // Returns `ty::VariantDef` if `def` refers to a struct, |
2602 | // or variant or their constructors, panics otherwise. | |
476ff2be | 2603 | pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef { |
5bcae85e | 2604 | match def { |
c30ab7b3 | 2605 | Def::Variant(did) | Def::VariantCtor(did, ..) => { |
9e0c209e | 2606 | let enum_did = self.parent_def_id(did).unwrap(); |
7cac9316 | 2607 | self.adt_def(enum_did).variant_with_id(did) |
5bcae85e | 2608 | } |
9e0c209e | 2609 | Def::Struct(did) | Def::Union(did) => { |
2c00a5a8 | 2610 | self.adt_def(did).non_enum_variant() |
5bcae85e | 2611 | } |
c30ab7b3 SL |
2612 | Def::StructCtor(ctor_did, ..) => { |
2613 | let did = self.parent_def_id(ctor_did).expect("struct ctor has no parent"); | |
2c00a5a8 | 2614 | self.adt_def(did).non_enum_variant() |
c30ab7b3 | 2615 | } |
5bcae85e SL |
2616 | _ => bug!("expect_variant_def used with unexpected def {:?}", def) |
2617 | } | |
2618 | } | |
2619 | ||
abe05a73 XL |
2620 | /// Given a `VariantDef`, returns the def-id of the `AdtDef` of which it is a part. |
2621 | pub fn adt_def_id_of_variant(self, variant_def: &'tcx VariantDef) -> DefId { | |
2622 | let def_key = self.def_key(variant_def.did); | |
2623 | match def_key.disambiguated_data.data { | |
2624 | // for enum variants and tuple structs, the def-id of the ADT itself | |
2625 | // is the *parent* of the variant | |
2626 | DefPathData::EnumVariant(..) | DefPathData::StructCtor => | |
2627 | DefId { krate: variant_def.did.krate, index: def_key.parent.unwrap() }, | |
2628 | ||
2629 | // otherwise, for structs and unions, they share a def-id | |
2630 | _ => variant_def.did, | |
2631 | } | |
2632 | } | |
2633 | ||
ea8adc8c | 2634 | pub fn item_name(self, id: DefId) -> InternedString { |
ff7c6d11 | 2635 | if id.index == CRATE_DEF_INDEX { |
83c7162d | 2636 | self.original_crate_name(id.krate).as_interned_str() |
e9174d1e | 2637 | } else { |
ea8adc8c | 2638 | let def_key = self.def_key(id); |
9e0c209e | 2639 | // The name of a StructCtor is that of its struct parent. |
32a655c1 | 2640 | if let hir_map::DefPathData::StructCtor = def_key.disambiguated_data.data { |
9e0c209e SL |
2641 | self.item_name(DefId { |
2642 | krate: id.krate, | |
2643 | index: def_key.parent.unwrap() | |
2644 | }) | |
2645 | } else { | |
2646 | def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| { | |
2647 | bug!("item_name: no name for {:?}", self.def_path(id)); | |
2648 | }) | |
2649 | } | |
e9174d1e SL |
2650 | } |
2651 | } | |
2652 | ||
cc61c64b XL |
2653 | /// Return the possibly-auto-generated MIR of a (DefId, Subst) pair. |
2654 | pub fn instance_mir(self, instance: ty::InstanceDef<'gcx>) | |
7cac9316 | 2655 | -> &'gcx Mir<'gcx> |
cc61c64b XL |
2656 | { |
2657 | match instance { | |
7cac9316 XL |
2658 | ty::InstanceDef::Item(did) => { |
2659 | self.optimized_mir(did) | |
2660 | } | |
2661 | ty::InstanceDef::Intrinsic(..) | | |
2662 | ty::InstanceDef::FnPtrShim(..) | | |
2663 | ty::InstanceDef::Virtual(..) | | |
2664 | ty::InstanceDef::ClosureOnceShim { .. } | | |
3b2f2976 XL |
2665 | ty::InstanceDef::DropGlue(..) | |
2666 | ty::InstanceDef::CloneShim(..) => { | |
7cac9316 XL |
2667 | self.mir_shims(instance) |
2668 | } | |
cc61c64b XL |
2669 | } |
2670 | } | |
2671 | ||
8bb4bdeb XL |
2672 | /// Given the DefId of an item, returns its MIR, borrowed immutably. |
2673 | /// Returns None if there is no MIR for the DefId | |
7cac9316 XL |
2674 | pub fn maybe_optimized_mir(self, did: DefId) -> Option<&'gcx Mir<'gcx>> { |
2675 | if self.is_mir_available(did) { | |
2676 | Some(self.optimized_mir(did)) | |
2677 | } else { | |
2678 | None | |
8bb4bdeb | 2679 | } |
c30ab7b3 SL |
2680 | } |
2681 | ||
e9174d1e | 2682 | /// Get the attributes of a definition. |
cc61c64b | 2683 | pub fn get_attrs(self, did: DefId) -> Attributes<'gcx> { |
32a655c1 | 2684 | if let Some(id) = self.hir.as_local_node_id(did) { |
cc61c64b | 2685 | Attributes::Borrowed(self.hir.attrs(id)) |
e9174d1e | 2686 | } else { |
7cac9316 | 2687 | Attributes::Owned(self.item_attrs(did)) |
e9174d1e SL |
2688 | } |
2689 | } | |
2690 | ||
2691 | /// Determine whether an item is annotated with an attribute | |
a7813a04 | 2692 | pub fn has_attr(self, did: DefId, attr: &str) -> bool { |
ff7c6d11 | 2693 | attr::contains_name(&self.get_attrs(did), attr) |
e9174d1e SL |
2694 | } |
2695 | ||
abe05a73 | 2696 | /// Returns true if this is an `auto trait`. |
abe05a73 XL |
2697 | pub fn trait_is_auto(self, trait_def_id: DefId) -> bool { |
2698 | self.trait_def(trait_def_id).has_auto_impl | |
b039eaaf SL |
2699 | } |
2700 | ||
ea8adc8c XL |
2701 | pub fn generator_layout(self, def_id: DefId) -> &'tcx GeneratorLayout<'tcx> { |
2702 | self.optimized_mir(def_id).generator_layout.as_ref().unwrap() | |
2703 | } | |
2704 | ||
e9174d1e SL |
2705 | /// Given the def_id of an impl, return the def_id of the trait it implements. |
2706 | /// If it implements no trait, return `None`. | |
a7813a04 | 2707 | pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> { |
e9174d1e SL |
2708 | self.impl_trait_ref(def_id).map(|tr| tr.def_id) |
2709 | } | |
2710 | ||
2711 | /// If the given def ID describes a method belonging to an impl, return the | |
2712 | /// ID of the impl that the method belongs to. Otherwise, return `None`. | |
a7813a04 | 2713 | pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> { |
8bb4bdeb | 2714 | let item = if def_id.krate != LOCAL_CRATE { |
7cac9316 | 2715 | if let Some(Def::Method(_)) = self.describe_def(def_id) { |
8bb4bdeb XL |
2716 | Some(self.associated_item(def_id)) |
2717 | } else { | |
2718 | None | |
2719 | } | |
2720 | } else { | |
7cac9316 | 2721 | self.opt_associated_item(def_id) |
8bb4bdeb XL |
2722 | }; |
2723 | ||
8faf50e0 XL |
2724 | item.and_then(|trait_item| |
2725 | match trait_item.container { | |
2726 | TraitContainer(_) => None, | |
2727 | ImplContainer(def_id) => Some(def_id), | |
e9174d1e | 2728 | } |
8faf50e0 | 2729 | ) |
e9174d1e SL |
2730 | } |
2731 | ||
54a0048b SL |
2732 | /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err` |
2733 | /// with the name of the crate containing the impl. | |
476ff2be | 2734 | pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> { |
54a0048b | 2735 | if impl_did.is_local() { |
32a655c1 SL |
2736 | let node_id = self.hir.as_local_node_id(impl_did).unwrap(); |
2737 | Ok(self.hir.span(node_id)) | |
54a0048b | 2738 | } else { |
ea8adc8c | 2739 | Err(self.crate_name(impl_did.krate)) |
54a0048b SL |
2740 | } |
2741 | } | |
7cac9316 | 2742 | |
ea8adc8c XL |
2743 | // Hygienically compare a use-site name (`use_name`) for a field or an associated item with its |
2744 | // supposed definition name (`def_name`). The method also needs `DefId` of the supposed | |
2745 | // definition's parent/scope to perform comparison. | |
8faf50e0 XL |
2746 | pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool { |
2747 | self.adjust_ident(use_name, def_parent_def_id, DUMMY_NODE_ID).0 == def_name.modern() | |
7cac9316 XL |
2748 | } |
2749 | ||
2750 | pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ident, DefId) { | |
8faf50e0 XL |
2751 | ident = ident.modern(); |
2752 | let target_expansion = match scope.krate { | |
2753 | LOCAL_CRATE => self.hir.definitions().expansion_that_defined(scope.index), | |
7cac9316 XL |
2754 | _ => Mark::root(), |
2755 | }; | |
8faf50e0 XL |
2756 | let scope = match ident.span.adjust(target_expansion) { |
2757 | Some(actual_expansion) => | |
2758 | self.hir.definitions().parent_module_of_macro_def(actual_expansion), | |
ea8adc8c | 2759 | None if block == DUMMY_NODE_ID => DefId::local(CRATE_DEF_INDEX), // Dummy DefId |
7cac9316 XL |
2760 | None => self.hir.get_module_parent(block), |
2761 | }; | |
2762 | (ident, scope) | |
2763 | } | |
e9174d1e SL |
2764 | } |
2765 | ||
a7813a04 XL |
2766 | impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { |
2767 | pub fn with_freevars<T, F>(self, fid: NodeId, f: F) -> T where | |
54a0048b | 2768 | F: FnOnce(&[hir::Freevar]) -> T, |
e9174d1e | 2769 | { |
ea8adc8c XL |
2770 | let def_id = self.hir.local_def_id(fid); |
2771 | match self.freevars(def_id) { | |
e9174d1e | 2772 | None => f(&[]), |
ea8adc8c | 2773 | Some(d) => f(&d), |
e9174d1e SL |
2774 | } |
2775 | } | |
e9174d1e | 2776 | } |
cc61c64b XL |
2777 | |
2778 | fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) | |
2779 | -> AssociatedItem | |
2780 | { | |
2781 | let id = tcx.hir.as_local_node_id(def_id).unwrap(); | |
2782 | let parent_id = tcx.hir.get_parent(id); | |
2783 | let parent_def_id = tcx.hir.local_def_id(parent_id); | |
2784 | let parent_item = tcx.hir.expect_item(parent_id); | |
2785 | match parent_item.node { | |
8faf50e0 | 2786 | hir::ItemKind::Impl(.., ref impl_item_refs) => { |
cc61c64b | 2787 | if let Some(impl_item_ref) = impl_item_refs.iter().find(|i| i.id.node_id == id) { |
7cac9316 XL |
2788 | let assoc_item = tcx.associated_item_from_impl_item_ref(parent_def_id, |
2789 | impl_item_ref); | |
cc61c64b XL |
2790 | debug_assert_eq!(assoc_item.def_id, def_id); |
2791 | return assoc_item; | |
2792 | } | |
2793 | } | |
2794 | ||
8faf50e0 | 2795 | hir::ItemKind::Trait(.., ref trait_item_refs) => { |
cc61c64b | 2796 | if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.node_id == id) { |
7cac9316 XL |
2797 | let assoc_item = tcx.associated_item_from_trait_item_ref(parent_def_id, |
2798 | &parent_item.vis, | |
2799 | trait_item_ref); | |
cc61c64b XL |
2800 | debug_assert_eq!(assoc_item.def_id, def_id); |
2801 | return assoc_item; | |
2802 | } | |
2803 | } | |
2804 | ||
7cac9316 | 2805 | _ => { } |
cc61c64b | 2806 | } |
7cac9316 XL |
2807 | |
2808 | span_bug!(parent_item.span, | |
2809 | "unexpected parent of trait or impl item or item not found: {:?}", | |
2810 | parent_item.node) | |
cc61c64b XL |
2811 | } |
2812 | ||
2813 | /// Calculates the Sized-constraint. | |
2814 | /// | |
2815 | /// In fact, there are only a few options for the types in the constraint: | |
2816 | /// - an obviously-unsized type | |
2817 | /// - a type parameter or projection whose Sizedness can't be known | |
2818 | /// - a tuple of type parameters or projections, if there are multiple | |
2819 | /// such. | |
2820 | /// - a TyError, if a type contained itself. The representability | |
2821 | /// check should catch this case. | |
2822 | fn adt_sized_constraint<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
2823 | def_id: DefId) | |
2824 | -> &'tcx [Ty<'tcx>] { | |
7cac9316 | 2825 | let def = tcx.adt_def(def_id); |
cc61c64b | 2826 | |
94b46f34 | 2827 | let result = tcx.mk_type_list(def.variants.iter().flat_map(|v| { |
cc61c64b XL |
2828 | v.fields.last() |
2829 | }).flat_map(|f| { | |
7cac9316 | 2830 | def.sized_constraint_for_ty(tcx, tcx.type_of(f.did)) |
94b46f34 | 2831 | })); |
cc61c64b XL |
2832 | |
2833 | debug!("adt_sized_constraint: {:?} => {:?}", def, result); | |
2834 | ||
2835 | result | |
2836 | } | |
2837 | ||
cc61c64b XL |
2838 | fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
2839 | def_id: DefId) | |
0531ce1d | 2840 | -> Lrc<Vec<DefId>> { |
cc61c64b XL |
2841 | let id = tcx.hir.as_local_node_id(def_id).unwrap(); |
2842 | let item = tcx.hir.expect_item(id); | |
2843 | let vec: Vec<_> = match item.node { | |
8faf50e0 | 2844 | hir::ItemKind::Trait(.., ref trait_item_refs) => { |
cc61c64b XL |
2845 | trait_item_refs.iter() |
2846 | .map(|trait_item_ref| trait_item_ref.id) | |
2847 | .map(|id| tcx.hir.local_def_id(id.node_id)) | |
2848 | .collect() | |
2849 | } | |
8faf50e0 | 2850 | hir::ItemKind::Impl(.., ref impl_item_refs) => { |
cc61c64b XL |
2851 | impl_item_refs.iter() |
2852 | .map(|impl_item_ref| impl_item_ref.id) | |
2853 | .map(|id| tcx.hir.local_def_id(id.node_id)) | |
2854 | .collect() | |
2855 | } | |
8faf50e0 | 2856 | hir::ItemKind::TraitAlias(..) => vec![], |
cc61c64b XL |
2857 | _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait") |
2858 | }; | |
0531ce1d | 2859 | Lrc::new(vec) |
cc61c64b XL |
2860 | } |
2861 | ||
7cac9316 XL |
2862 | fn def_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Span { |
2863 | tcx.hir.span_if_local(def_id).unwrap() | |
2864 | } | |
2865 | ||
2866 | /// If the given def ID describes an item belonging to a trait, | |
2867 | /// return the ID of the trait that the trait item belongs to. | |
2868 | /// Otherwise, return `None`. | |
2869 | fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option<DefId> { | |
2870 | tcx.opt_associated_item(def_id) | |
2871 | .and_then(|associated_item| { | |
2872 | match associated_item.container { | |
2873 | TraitContainer(def_id) => Some(def_id), | |
2874 | ImplContainer(_) => None | |
2875 | } | |
2876 | }) | |
2877 | } | |
2878 | ||
8faf50e0 XL |
2879 | /// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition |
2880 | pub fn is_impl_trait_defn(tcx: TyCtxt, def_id: DefId) -> Option<DefId> { | |
2881 | if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { | |
2882 | if let hir::map::NodeItem(item) = tcx.hir.get(node_id) { | |
2883 | if let hir::ItemKind::Existential(ref exist_ty) = item.node { | |
2884 | return exist_ty.impl_trait_fn; | |
2885 | } | |
2886 | } | |
2887 | } | |
2888 | None | |
2889 | } | |
2890 | ||
7cac9316 XL |
2891 | /// See `ParamEnv` struct def'n for details. |
2892 | fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
2893 | def_id: DefId) | |
2894 | -> ParamEnv<'tcx> { | |
94b46f34 | 2895 | |
8faf50e0 XL |
2896 | // The param_env of an impl Trait type is its defining function's param_env |
2897 | if let Some(parent) = is_impl_trait_defn(tcx, def_id) { | |
94b46f34 XL |
2898 | return param_env(tcx, parent); |
2899 | } | |
7cac9316 XL |
2900 | // Compute the bounds on Self and the type parameters. |
2901 | ||
8faf50e0 XL |
2902 | let InstantiatedPredicates { predicates } = |
2903 | tcx.predicates_of(def_id).instantiate_identity(tcx); | |
7cac9316 XL |
2904 | |
2905 | // Finally, we have to normalize the bounds in the environment, in | |
2906 | // case they contain any associated type projections. This process | |
2907 | // can yield errors if the put in illegal associated types, like | |
2908 | // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We | |
2909 | // report these errors right here; this doesn't actually feel | |
2910 | // right to me, because constructing the environment feels like a | |
2911 | // kind of a "idempotent" action, but I'm not sure where would be | |
2912 | // a better place. In practice, we construct environments for | |
2913 | // every fn once during type checking, and we'll abort if there | |
2914 | // are any errors at that point, so after type checking you can be | |
2915 | // sure that this will succeed without errors anyway. | |
2916 | ||
2917 | let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates), | |
2918 | traits::Reveal::UserFacing); | |
2919 | ||
2920 | let body_id = tcx.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| { | |
2921 | tcx.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id) | |
2922 | }); | |
2923 | let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id); | |
2924 | traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause) | |
2925 | } | |
2926 | ||
ea8adc8c | 2927 | fn crate_disambiguator<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
abe05a73 | 2928 | crate_num: CrateNum) -> CrateDisambiguator { |
ea8adc8c XL |
2929 | assert_eq!(crate_num, LOCAL_CRATE); |
2930 | tcx.sess.local_crate_disambiguator() | |
2931 | } | |
2932 | ||
2933 | fn original_crate_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
2934 | crate_num: CrateNum) -> Symbol { | |
2935 | assert_eq!(crate_num, LOCAL_CRATE); | |
2936 | tcx.crate_name.clone() | |
2937 | } | |
2938 | ||
ff7c6d11 XL |
2939 | fn crate_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
2940 | crate_num: CrateNum) | |
2941 | -> Svh { | |
2942 | assert_eq!(crate_num, LOCAL_CRATE); | |
2943 | tcx.hir.crate_hash | |
2944 | } | |
2945 | ||
2c00a5a8 XL |
2946 | fn instance_def_size_estimate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |
2947 | instance_def: InstanceDef<'tcx>) | |
2948 | -> usize { | |
2949 | match instance_def { | |
2950 | InstanceDef::Item(..) | | |
2951 | InstanceDef::DropGlue(..) => { | |
2952 | let mir = tcx.instance_mir(instance_def); | |
2953 | mir.basic_blocks().iter().map(|bb| bb.statements.len()).sum() | |
2954 | }, | |
2955 | // Estimate the size of other compiler-generated shims to be 1. | |
2956 | _ => 1 | |
2957 | } | |
2958 | } | |
2959 | ||
94b46f34 | 2960 | pub fn provide(providers: &mut ty::query::Providers) { |
ea8adc8c | 2961 | context::provide(providers); |
abe05a73 | 2962 | erase_regions::provide(providers); |
ff7c6d11 XL |
2963 | layout::provide(providers); |
2964 | util::provide(providers); | |
94b46f34 | 2965 | *providers = ty::query::Providers { |
cc61c64b XL |
2966 | associated_item, |
2967 | associated_item_def_ids, | |
2968 | adt_sized_constraint, | |
7cac9316 XL |
2969 | def_span, |
2970 | param_env, | |
2971 | trait_of_item, | |
ea8adc8c XL |
2972 | crate_disambiguator, |
2973 | original_crate_name, | |
ff7c6d11 | 2974 | crate_hash, |
7cac9316 | 2975 | trait_impls_of: trait_def::trait_impls_of_provider, |
2c00a5a8 | 2976 | instance_def_size_estimate, |
cc61c64b XL |
2977 | ..*providers |
2978 | }; | |
2979 | } | |
2980 | ||
cc61c64b XL |
2981 | /// A map for the local crate mapping each type to a vector of its |
2982 | /// inherent impls. This is not meant to be used outside of coherence; | |
2983 | /// rather, you should request the vector for a specific type via | |
7cac9316 XL |
2984 | /// `tcx.inherent_impls(def_id)` so as to minimize your dependencies |
2985 | /// (constructing this map requires touching the entire crate). | |
cc61c64b XL |
2986 | #[derive(Clone, Debug)] |
2987 | pub struct CrateInherentImpls { | |
0531ce1d | 2988 | pub inherent_impls: DefIdMap<Lrc<Vec<DefId>>>, |
cc61c64b XL |
2989 | } |
2990 | ||
0531ce1d | 2991 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)] |
7cac9316 XL |
2992 | pub struct SymbolName { |
2993 | // FIXME: we don't rely on interning or equality here - better have | |
2994 | // this be a `&'tcx str`. | |
2995 | pub name: InternedString | |
2996 | } | |
2997 | ||
ea8adc8c XL |
2998 | impl_stable_hash_for!(struct self::SymbolName { |
2999 | name | |
3000 | }); | |
3001 | ||
0531ce1d XL |
3002 | impl SymbolName { |
3003 | pub fn new(name: &str) -> SymbolName { | |
3004 | SymbolName { | |
83c7162d | 3005 | name: Symbol::intern(name).as_interned_str() |
0531ce1d XL |
3006 | } |
3007 | } | |
7cac9316 | 3008 | |
83c7162d XL |
3009 | pub fn as_str(&self) -> LocalInternedString { |
3010 | self.name.as_str() | |
3011 | } | |
7cac9316 XL |
3012 | } |
3013 | ||
3014 | impl fmt::Display for SymbolName { | |
3015 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
3016 | fmt::Display::fmt(&self.name, fmt) | |
3017 | } | |
3018 | } | |
0531ce1d XL |
3019 | |
3020 | impl fmt::Debug for SymbolName { | |
3021 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
3022 | fmt::Display::fmt(&self.name, fmt) | |
3023 | } | |
3024 | } |