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