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