]>
Commit | Line | Data |
---|---|---|
fc512014 XL |
1 | //! Defines how the compiler represents types internally. |
2 | //! | |
3 | //! Two important entities in this module are: | |
4 | //! | |
5 | //! - [`rustc_middle::ty::Ty`], used to represent the semantics of a type. | |
6 | //! - [`rustc_middle::ty::TyCtxt`], the central data structure in the compiler. | |
7 | //! | |
8 | //! For more information, see ["The `ty` module: representing types"] in the ructc-dev-guide. | |
9 | //! | |
10 | //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html | |
11 | ||
3dfed10e | 12 | pub use self::fold::{TypeFoldable, TypeFolder, TypeVisitor}; |
dc9dc135 | 13 | pub use self::AssocItemContainer::*; |
e9174d1e | 14 | pub use self::BorrowKind::*; |
e9174d1e | 15 | pub use self::IntVarValue::*; |
dfeec247 | 16 | pub use self::Variance::*; |
6a06907d XL |
17 | pub use adt::*; |
18 | pub use assoc::*; | |
6a06907d | 19 | pub use generics::*; |
136023e0 | 20 | pub use vtable::*; |
dfeec247 | 21 | |
dfeec247 | 22 | use crate::hir::exports::ExportMap; |
6a06907d | 23 | use crate::mir::{Body, GeneratorLayout}; |
9fa01778 XL |
24 | use crate::traits::{self, Reveal}; |
25 | use crate::ty; | |
f035d41b | 26 | use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; |
6a06907d | 27 | use crate::ty::util::Discr; |
3dfed10e | 28 | use rustc_ast as ast; |
74b04a01 | 29 | use rustc_attr as attr; |
6a06907d | 30 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
dfeec247 | 31 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; |
3dfed10e | 32 | use rustc_data_structures::tagged_ptr::CopyTaggedPtr; |
dfeec247 | 33 | use rustc_hir as hir; |
6a06907d | 34 | use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; |
17df50a5 | 35 | use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, CRATE_DEF_INDEX}; |
94222f64 | 36 | use rustc_hir::Node; |
dfeec247 | 37 | use rustc_macros::HashStable; |
c295e0f8 XL |
38 | use rustc_query_system::ich::StableHashingContext; |
39 | use rustc_session::cstore::CrateStoreDyn; | |
6a06907d | 40 | use rustc_span::symbol::{kw, Ident, Symbol}; |
c295e0f8 | 41 | use rustc_span::{sym, Span}; |
6a06907d | 42 | use rustc_target::abi::Align; |
74b04a01 | 43 | |
f9f354fc | 44 | use std::cmp::Ordering; |
94222f64 | 45 | use std::collections::BTreeMap; |
e9174d1e | 46 | use std::hash::{Hash, Hasher}; |
6a06907d XL |
47 | use std::ops::ControlFlow; |
48 | use std::{fmt, ptr, str}; | |
54a0048b | 49 | |
60c5eb7d | 50 | pub use crate::ty::diagnostics::*; |
5869c6ff XL |
51 | pub use rustc_type_ir::InferTy::*; |
52 | pub use rustc_type_ir::*; | |
e9174d1e | 53 | |
3b2f2976 XL |
54 | pub use self::binding::BindingMode; |
55 | pub use self::binding::BindingMode::*; | |
94222f64 XL |
56 | pub use self::closure::{ |
57 | is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo, | |
58 | CapturedPlace, ClosureKind, MinCaptureInformationMap, MinCaptureList, | |
59 | RootVariableMinCaptureList, UpvarBorrow, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, | |
60 | UpvarPath, CAPTURE_STRUCT_LOCAL, | |
61 | }; | |
cdc7bbd5 | 62 | pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Unevaluated, ValTree}; |
0731742a | 63 | pub use self::context::{ |
6a06907d XL |
64 | tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, |
65 | CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt, | |
136023e0 | 66 | Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex, |
0731742a | 67 | }; |
cc61c64b | 68 | pub use self::instance::{Instance, InstanceDef}; |
f9f354fc | 69 | pub use self::list::List; |
6a06907d XL |
70 | pub use self::sty::BoundRegionKind::*; |
71 | pub use self::sty::RegionKind::*; | |
72 | pub use self::sty::TyKind::*; | |
73 | pub use self::sty::{ | |
cdc7bbd5 XL |
74 | Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind, |
75 | CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion, | |
76 | ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, | |
3c0e092e XL |
77 | GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, InlineConstSubstsParts, ParamConst, |
78 | ParamTy, PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, | |
79 | PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, | |
80 | UpvarSubsts, VarianceDiagInfo, VarianceDiagMutKind, | |
6a06907d | 81 | }; |
7cac9316 | 82 | pub use self::trait_def::TraitDef; |
9cc50fc6 | 83 | |
3dfed10e | 84 | pub mod _match; |
e9174d1e | 85 | pub mod adjustment; |
3b2f2976 | 86 | pub mod binding; |
e9174d1e | 87 | pub mod cast; |
abe05a73 | 88 | pub mod codec; |
dfeec247 | 89 | pub mod error; |
e9174d1e | 90 | pub mod fast_reject; |
48663c56 | 91 | pub mod flags; |
e9174d1e | 92 | pub mod fold; |
32a655c1 | 93 | pub mod inhabitedness; |
54a0048b | 94 | pub mod layout; |
dfeec247 | 95 | pub mod normalize_erasing_regions; |
532ac7d7 | 96 | pub mod print; |
94b46f34 | 97 | pub mod query; |
e9174d1e | 98 | pub mod relate; |
54a0048b | 99 | pub mod subst; |
9cc50fc6 | 100 | pub mod trait_def; |
e9174d1e | 101 | pub mod util; |
136023e0 | 102 | pub mod vtable; |
dfeec247 | 103 | pub mod walk; |
e9174d1e | 104 | |
6a06907d XL |
105 | mod adt; |
106 | mod assoc; | |
107 | mod closure; | |
f035d41b | 108 | mod consts; |
e9174d1e | 109 | mod context; |
dfeec247 | 110 | mod diagnostics; |
6a06907d XL |
111 | mod erase_regions; |
112 | mod generics; | |
c295e0f8 | 113 | mod impls_ty; |
cc61c64b | 114 | mod instance; |
f9f354fc | 115 | mod list; |
e9174d1e SL |
116 | mod structural_impls; |
117 | mod sty; | |
118 | ||
e9174d1e SL |
119 | // Data types |
120 | ||
136023e0 | 121 | #[derive(Debug)] |
e74abb32 | 122 | pub struct ResolverOutputs { |
ba9703b0 | 123 | pub definitions: rustc_hir::definitions::Definitions, |
e74abb32 | 124 | pub cstore: Box<CrateStoreDyn>, |
29967ef6 | 125 | pub visibilities: FxHashMap<LocalDefId, Visibility>, |
f9f354fc | 126 | pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>, |
f9f354fc XL |
127 | pub maybe_unused_trait_imports: FxHashSet<LocalDefId>, |
128 | pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, | |
c295e0f8 | 129 | pub export_map: ExportMap, |
f9f354fc | 130 | pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>, |
0bf4aa26 XL |
131 | /// Extern prelude entries. The value is `true` if the entry was introduced |
132 | /// via `extern crate` item and not `--extern` option or compiler built-in. | |
f9f354fc | 133 | pub extern_prelude: FxHashMap<Symbol, bool>, |
cdc7bbd5 | 134 | pub main_def: Option<MainDefinition>, |
94222f64 XL |
135 | pub trait_impls: BTreeMap<DefId, Vec<LocalDefId>>, |
136 | /// A list of proc macro LocalDefIds, written out in the order in which | |
137 | /// they are declared in the static array generated by proc_macro_harness. | |
138 | pub proc_macros: Vec<LocalDefId>, | |
c295e0f8 XL |
139 | /// Mapping from ident span to path span for paths that don't exist as written, but that |
140 | /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. | |
141 | pub confused_type_with_std_module: FxHashMap<Span, Span>, | |
cdc7bbd5 XL |
142 | } |
143 | ||
136023e0 | 144 | #[derive(Clone, Copy, Debug)] |
cdc7bbd5 XL |
145 | pub struct MainDefinition { |
146 | pub res: Res<ast::NodeId>, | |
147 | pub is_import: bool, | |
148 | pub span: Span, | |
149 | } | |
150 | ||
151 | impl MainDefinition { | |
152 | pub fn opt_fn_def_id(self) -> Option<DefId> { | |
153 | if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None } | |
154 | } | |
e9174d1e SL |
155 | } |
156 | ||
54a0048b SL |
157 | /// The "header" of an impl is everything outside the body: a Self type, a trait |
158 | /// ref (in the case of a trait impl), and a set of predicates (from the | |
9fa01778 | 159 | /// bounds / where-clauses). |
60c5eb7d | 160 | #[derive(Clone, Debug, TypeFoldable)] |
54a0048b SL |
161 | pub struct ImplHeader<'tcx> { |
162 | pub impl_def_id: DefId, | |
163 | pub self_ty: Ty<'tcx>, | |
164 | pub trait_ref: Option<TraitRef<'tcx>>, | |
165 | pub predicates: Vec<Predicate<'tcx>>, | |
166 | } | |
167 | ||
3c0e092e XL |
168 | #[derive( |
169 | Copy, | |
170 | Clone, | |
171 | PartialEq, | |
172 | Eq, | |
173 | Hash, | |
174 | TyEncodable, | |
175 | TyDecodable, | |
176 | HashStable, | |
177 | Debug, | |
178 | TypeFoldable | |
179 | )] | |
e74abb32 XL |
180 | pub enum ImplPolarity { |
181 | /// `impl Trait for Type` | |
182 | Positive, | |
183 | /// `impl !Trait for Type` | |
184 | Negative, | |
185 | /// `#[rustc_reservation_impl] impl Trait for Type` | |
186 | /// | |
187 | /// This is a "stability hack", not a real Rust feature. | |
188 | /// See #64631 for details. | |
189 | Reservation, | |
190 | } | |
191 | ||
3c0e092e XL |
192 | impl ImplPolarity { |
193 | /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`. | |
194 | pub fn flip(&self) -> Option<ImplPolarity> { | |
195 | match self { | |
196 | ImplPolarity::Positive => Some(ImplPolarity::Negative), | |
197 | ImplPolarity::Negative => Some(ImplPolarity::Positive), | |
198 | ImplPolarity::Reservation => None, | |
199 | } | |
200 | } | |
201 | } | |
202 | ||
203 | impl fmt::Display for ImplPolarity { | |
204 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
205 | match self { | |
206 | Self::Positive => f.write_str("positive"), | |
207 | Self::Negative => f.write_str("negative"), | |
208 | Self::Reservation => f.write_str("reservation"), | |
209 | } | |
210 | } | |
211 | } | |
212 | ||
3dfed10e | 213 | #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)] |
54a0048b SL |
214 | pub enum Visibility { |
215 | /// Visible everywhere (including in other crates). | |
216 | Public, | |
217 | /// Visible only in the given crate-local module. | |
32a655c1 | 218 | Restricted(DefId), |
54a0048b | 219 | /// Not visible anywhere in the local crate. This is the visibility of private external items. |
32a655c1 | 220 | Invisible, |
54a0048b SL |
221 | } |
222 | ||
94222f64 XL |
223 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] |
224 | pub enum BoundConstness { | |
225 | /// `T: Trait` | |
226 | NotConst, | |
227 | /// `T: ~const Trait` | |
228 | /// | |
229 | /// Requires resolving to const only when we are in a const context. | |
230 | ConstIfConst, | |
231 | } | |
232 | ||
233 | impl fmt::Display for BoundConstness { | |
234 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
235 | match self { | |
236 | Self::NotConst => f.write_str("normal"), | |
237 | Self::ConstIfConst => f.write_str("`~const`"), | |
238 | } | |
239 | } | |
240 | } | |
241 | ||
136023e0 XL |
242 | #[derive( |
243 | Clone, | |
244 | Debug, | |
245 | PartialEq, | |
246 | Eq, | |
247 | Copy, | |
248 | Hash, | |
249 | TyEncodable, | |
250 | TyDecodable, | |
251 | HashStable, | |
252 | TypeFoldable | |
253 | )] | |
254 | pub struct ClosureSizeProfileData<'tcx> { | |
255 | /// Tuple containing the types of closure captures before the feature `capture_disjoint_fields` | |
256 | pub before_feature_tys: Ty<'tcx>, | |
257 | /// Tuple containing the types of closure captures after the feature `capture_disjoint_fields` | |
258 | pub after_feature_tys: Ty<'tcx>, | |
259 | } | |
260 | ||
32a655c1 SL |
261 | pub trait DefIdTree: Copy { |
262 | fn parent(self, id: DefId) -> Option<DefId>; | |
a7813a04 | 263 | |
32a655c1 SL |
264 | fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool { |
265 | if descendant.krate != ancestor.krate { | |
266 | return false; | |
267 | } | |
268 | ||
269 | while descendant != ancestor { | |
270 | match self.parent(descendant) { | |
271 | Some(parent) => descendant = parent, | |
272 | None => return false, | |
a7813a04 | 273 | } |
a7813a04 XL |
274 | } |
275 | true | |
276 | } | |
277 | } | |
278 | ||
dc9dc135 | 279 | impl<'tcx> DefIdTree for TyCtxt<'tcx> { |
32a655c1 | 280 | fn parent(self, id: DefId) -> Option<DefId> { |
74b04a01 | 281 | self.def_key(id).parent.map(|index| DefId { index, ..id }) |
32a655c1 SL |
282 | } |
283 | } | |
284 | ||
54a0048b | 285 | impl Visibility { |
dfeec247 | 286 | pub fn from_hir(visibility: &hir::Visibility<'_>, id: hir::HirId, tcx: TyCtxt<'_>) -> Self { |
8faf50e0 XL |
287 | match visibility.node { |
288 | hir::VisibilityKind::Public => Visibility::Public, | |
289 | hir::VisibilityKind::Crate(_) => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)), | |
48663c56 | 290 | hir::VisibilityKind::Restricted { ref path, .. } => match path.res { |
a7813a04 XL |
291 | // If there is no resolution, `resolve` will have already reported an error, so |
292 | // assume that the visibility is public to avoid reporting more privacy errors. | |
48663c56 | 293 | Res::Err => Visibility::Public, |
32a655c1 | 294 | def => Visibility::Restricted(def.def_id()), |
a7813a04 | 295 | }, |
ba9703b0 XL |
296 | hir::VisibilityKind::Inherited => { |
297 | Visibility::Restricted(tcx.parent_module(id).to_def_id()) | |
298 | } | |
54a0048b SL |
299 | } |
300 | } | |
301 | ||
a1dfa0c6 | 302 | /// Returns `true` if an item with this visibility is accessible from the given block. |
32a655c1 | 303 | pub fn is_accessible_from<T: DefIdTree>(self, module: DefId, tree: T) -> bool { |
54a0048b SL |
304 | let restriction = match self { |
305 | // Public items are visible everywhere. | |
306 | Visibility::Public => return true, | |
307 | // Private items from other crates are visible nowhere. | |
32a655c1 | 308 | Visibility::Invisible => return false, |
54a0048b | 309 | // Restricted items are visible in an arbitrary local module. |
32a655c1 | 310 | Visibility::Restricted(other) if other.krate != module.krate => return false, |
54a0048b SL |
311 | Visibility::Restricted(module) => module, |
312 | }; | |
313 | ||
32a655c1 | 314 | tree.is_descendant_of(module, restriction) |
54a0048b SL |
315 | } |
316 | ||
a1dfa0c6 | 317 | /// Returns `true` if this visibility is at least as accessible as the given visibility |
32a655c1 | 318 | pub fn is_at_least<T: DefIdTree>(self, vis: Visibility, tree: T) -> bool { |
54a0048b SL |
319 | let vis_restriction = match vis { |
320 | Visibility::Public => return self == Visibility::Public, | |
32a655c1 | 321 | Visibility::Invisible => return true, |
54a0048b SL |
322 | Visibility::Restricted(module) => module, |
323 | }; | |
324 | ||
a7813a04 | 325 | self.is_accessible_from(vis_restriction, tree) |
54a0048b | 326 | } |
ff7c6d11 | 327 | |
a1dfa0c6 | 328 | // Returns `true` if this item is visible anywhere in the local crate. |
ff7c6d11 XL |
329 | pub fn is_visible_locally(self) -> bool { |
330 | match self { | |
331 | Visibility::Public => true, | |
332 | Visibility::Restricted(def_id) => def_id.is_local(), | |
333 | Visibility::Invisible => false, | |
334 | } | |
335 | } | |
3c0e092e XL |
336 | |
337 | pub fn is_public(self) -> bool { | |
338 | matches!(self, Visibility::Public) | |
339 | } | |
54a0048b SL |
340 | } |
341 | ||
7cac9316 XL |
342 | /// The crate variances map is computed during typeck and contains the |
343 | /// variance of every item in the local crate. You should not use it | |
344 | /// directly, because to do so will make your pass dependent on the | |
345 | /// HIR of every item in the local crate. Instead, use | |
346 | /// `tcx.variances_of()` to get the variance for a *particular* | |
347 | /// item. | |
5869c6ff | 348 | #[derive(HashStable, Debug)] |
48663c56 | 349 | pub struct CrateVariancesMap<'tcx> { |
7cac9316 | 350 | /// For each item with generics, maps to a vector of the variance |
9fa01778 | 351 | /// of its generics. If an item has no generics, it will have no |
7cac9316 | 352 | /// entry. |
48663c56 | 353 | pub variances: FxHashMap<DefId, &'tcx [ty::Variance]>, |
7cac9316 XL |
354 | } |
355 | ||
e9174d1e SL |
356 | // Contains information needed to resolve types and (in the future) look up |
357 | // the types of AST nodes. | |
358 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
359 | pub struct CReaderCacheKey { | |
17df50a5 | 360 | pub cnum: Option<CrateNum>, |
e9174d1e | 361 | pub pos: usize, |
e9174d1e SL |
362 | } |
363 | ||
e1599b0c | 364 | #[allow(rustc::usage_of_ty_tykind)] |
e9174d1e | 365 | pub struct TyS<'tcx> { |
1b1a35ee XL |
366 | /// This field shouldn't be used directly and may be removed in the future. |
367 | /// Use `TyS::kind()` instead. | |
368 | kind: TyKind<'tcx>, | |
369 | /// This field shouldn't be used directly and may be removed in the future. | |
370 | /// Use `TyS::flags()` instead. | |
371 | flags: TypeFlags, | |
e9174d1e | 372 | |
94b46f34 XL |
373 | /// This is a kind of confusing thing: it stores the smallest |
374 | /// binder such that | |
375 | /// | |
376 | /// (a) the binder itself captures nothing but | |
377 | /// (b) all the late-bound things within the type are captured | |
378 | /// by some sub-binder. | |
379 | /// | |
380 | /// So, for a type without any late-bound things, like `u32`, this | |
0731742a | 381 | /// will be *innermost*, because that is the innermost binder that |
94b46f34 | 382 | /// captures nothing. But for a type `&'D u32`, where `'D` is a |
9fa01778 | 383 | /// late-bound region with De Bruijn index `D`, this would be `D + 1` |
0731742a XL |
384 | /// -- the binder itself does not capture `D`, but `D` is captured |
385 | /// by an inner binder. | |
94b46f34 | 386 | /// |
0731742a | 387 | /// We call this concept an "exclusive" binder `D` because all |
9fa01778 | 388 | /// De Bruijn indices within the type are contained within `0..D` |
0731742a | 389 | /// (exclusive). |
94b46f34 XL |
390 | outer_exclusive_binder: ty::DebruijnIndex, |
391 | } | |
392 | ||
fc512014 XL |
393 | impl<'tcx> TyS<'tcx> { |
394 | /// A constructor used only for internal testing. | |
395 | #[allow(rustc::usage_of_ty_tykind)] | |
396 | pub fn make_for_test( | |
397 | kind: TyKind<'tcx>, | |
398 | flags: TypeFlags, | |
399 | outer_exclusive_binder: ty::DebruijnIndex, | |
400 | ) -> TyS<'tcx> { | |
401 | TyS { kind, flags, outer_exclusive_binder } | |
402 | } | |
403 | } | |
404 | ||
a1dfa0c6 | 405 | // `TyS` is used a lot. Make sure it doesn't unintentionally get bigger. |
6a06907d | 406 | #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] |
cdc7bbd5 | 407 | static_assert_size!(TyS<'_>, 40); |
a1dfa0c6 | 408 | |
94b46f34 XL |
409 | impl<'tcx> Ord for TyS<'tcx> { |
410 | fn cmp(&self, other: &TyS<'tcx>) -> Ordering { | |
1b1a35ee | 411 | self.kind().cmp(other.kind()) |
94b46f34 XL |
412 | } |
413 | } | |
414 | ||
415 | impl<'tcx> PartialOrd for TyS<'tcx> { | |
416 | fn partial_cmp(&self, other: &TyS<'tcx>) -> Option<Ordering> { | |
1b1a35ee | 417 | Some(self.kind().cmp(other.kind())) |
94b46f34 | 418 | } |
e9174d1e SL |
419 | } |
420 | ||
421 | impl<'tcx> PartialEq for TyS<'tcx> { | |
422 | #[inline] | |
423 | fn eq(&self, other: &TyS<'tcx>) -> bool { | |
8faf50e0 | 424 | ptr::eq(self, other) |
e9174d1e SL |
425 | } |
426 | } | |
427 | impl<'tcx> Eq for TyS<'tcx> {} | |
428 | ||
429 | impl<'tcx> Hash for TyS<'tcx> { | |
430 | fn hash<H: Hasher>(&self, s: &mut H) { | |
0bf4aa26 | 431 | (self as *const TyS<'_>).hash(s) |
e9174d1e SL |
432 | } |
433 | } | |
434 | ||
f035d41b | 435 | impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> { |
e74abb32 | 436 | fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
cc61c64b | 437 | let ty::TyS { |
e74abb32 | 438 | ref kind, |
cc61c64b XL |
439 | |
440 | // The other fields just provide fast access to information that is | |
e74abb32 | 441 | // also contained in `kind`, so no need to hash them. |
cc61c64b | 442 | flags: _, |
94b46f34 XL |
443 | |
444 | outer_exclusive_binder: _, | |
cc61c64b XL |
445 | } = *self; |
446 | ||
e74abb32 | 447 | kind.hash_stable(hcx, hasher); |
cc61c64b XL |
448 | } |
449 | } | |
450 | ||
e74abb32 | 451 | #[rustc_diagnostic_item = "Ty"] |
e9174d1e SL |
452 | pub type Ty<'tcx> = &'tcx TyS<'tcx>; |
453 | ||
94b46f34 | 454 | impl ty::EarlyBoundRegion { |
b7449926 XL |
455 | /// Does this early bound region have a name? Early bound regions normally |
456 | /// always have names except when using anonymous lifetimes (`'_`). | |
457 | pub fn has_name(&self) -> bool { | |
e74abb32 | 458 | self.name != kw::UnderscoreLifetime |
b7449926 | 459 | } |
94b46f34 | 460 | } |
ea8adc8c | 461 | |
f035d41b XL |
462 | #[derive(Debug)] |
463 | crate struct PredicateInner<'tcx> { | |
cdc7bbd5 | 464 | kind: Binder<'tcx, PredicateKind<'tcx>>, |
f035d41b XL |
465 | flags: TypeFlags, |
466 | /// See the comment for the corresponding field of [TyS]. | |
467 | outer_exclusive_binder: ty::DebruijnIndex, | |
468 | } | |
469 | ||
6a06907d | 470 | #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] |
cdc7bbd5 | 471 | static_assert_size!(PredicateInner<'_>, 48); |
f035d41b XL |
472 | |
473 | #[derive(Clone, Copy, Lift)] | |
f9f354fc | 474 | pub struct Predicate<'tcx> { |
f035d41b | 475 | inner: &'tcx PredicateInner<'tcx>, |
f9f354fc XL |
476 | } |
477 | ||
478 | impl<'tcx> PartialEq for Predicate<'tcx> { | |
479 | fn eq(&self, other: &Self) -> bool { | |
480 | // `self.kind` is always interned. | |
f035d41b XL |
481 | ptr::eq(self.inner, other.inner) |
482 | } | |
483 | } | |
484 | ||
485 | impl Hash for Predicate<'_> { | |
486 | fn hash<H: Hasher>(&self, s: &mut H) { | |
487 | (self.inner as *const PredicateInner<'_>).hash(s) | |
f9f354fc XL |
488 | } |
489 | } | |
490 | ||
491 | impl<'tcx> Eq for Predicate<'tcx> {} | |
492 | ||
493 | impl<'tcx> Predicate<'tcx> { | |
cdc7bbd5 | 494 | /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. |
6a06907d | 495 | #[inline] |
cdc7bbd5 | 496 | pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { |
5869c6ff | 497 | self.inner.kind |
3dfed10e | 498 | } |
3c0e092e XL |
499 | |
500 | /// Flips the polarity of a Predicate. | |
501 | /// | |
502 | /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. | |
503 | pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option<Predicate<'tcx>> { | |
504 | let kind = self | |
505 | .inner | |
506 | .kind | |
507 | .map_bound(|kind| match kind { | |
508 | PredicateKind::Trait(TraitPredicate { trait_ref, constness, polarity }) => { | |
509 | Some(PredicateKind::Trait(TraitPredicate { | |
510 | trait_ref, | |
511 | constness, | |
512 | polarity: polarity.flip()?, | |
513 | })) | |
514 | } | |
515 | ||
516 | _ => None, | |
517 | }) | |
518 | .transpose()?; | |
519 | ||
520 | Some(tcx.mk_predicate(kind)) | |
521 | } | |
f035d41b XL |
522 | } |
523 | ||
524 | impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> { | |
525 | fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { | |
526 | let PredicateInner { | |
527 | ref kind, | |
528 | ||
529 | // The other fields just provide fast access to information that is | |
530 | // also contained in `kind`, so no need to hash them. | |
531 | flags: _, | |
532 | outer_exclusive_binder: _, | |
533 | } = self.inner; | |
534 | ||
535 | kind.hash_stable(hcx, hasher); | |
f9f354fc XL |
536 | } |
537 | } | |
538 | ||
3dfed10e | 539 | #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] |
60c5eb7d | 540 | #[derive(HashStable, TypeFoldable)] |
f9f354fc | 541 | pub enum PredicateKind<'tcx> { |
dc9dc135 | 542 | /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be |
e9174d1e | 543 | /// the `Self` type of the trait reference and `A`, `B`, and `C` |
9e0c209e | 544 | /// would be the type parameters. |
94222f64 | 545 | Trait(TraitPredicate<'tcx>), |
e9174d1e | 546 | |
dc9dc135 | 547 | /// `where 'a: 'b` |
3dfed10e | 548 | RegionOutlives(RegionOutlivesPredicate<'tcx>), |
e9174d1e | 549 | |
dc9dc135 | 550 | /// `where T: 'a` |
3dfed10e | 551 | TypeOutlives(TypeOutlivesPredicate<'tcx>), |
e9174d1e | 552 | |
dc9dc135 | 553 | /// `where <T as TraitRef>::Name == X`, approximately. |
a1dfa0c6 | 554 | /// See the `ProjectionPredicate` struct for details. |
3dfed10e | 555 | Projection(ProjectionPredicate<'tcx>), |
e9174d1e | 556 | |
dc9dc135 | 557 | /// No syntax: `T` well-formed. |
f035d41b | 558 | WellFormed(GenericArg<'tcx>), |
e9174d1e | 559 | |
dc9dc135 | 560 | /// Trait must be object-safe. |
e9174d1e | 561 | ObjectSafe(DefId), |
a7813a04 | 562 | |
a1dfa0c6 XL |
563 | /// No direct syntax. May be thought of as `where T: FnFoo<...>` |
564 | /// for some substitutions `...` and `T` being a closure type. | |
9e0c209e | 565 | /// Satisfied (or refuted) once we know the closure's kind. |
e74abb32 | 566 | ClosureKind(DefId, SubstsRef<'tcx>, ClosureKind), |
cc61c64b XL |
567 | |
568 | /// `T1 <: T2` | |
94222f64 XL |
569 | /// |
570 | /// This obligation is created most often when we have two | |
571 | /// unresolved type variables and hence don't have enough | |
572 | /// information to process the subtyping obligation yet. | |
3dfed10e | 573 | Subtype(SubtypePredicate<'tcx>), |
ea8adc8c | 574 | |
94222f64 XL |
575 | /// `T1` coerced to `T2` |
576 | /// | |
577 | /// Like a subtyping obligation, this is created most often | |
578 | /// when we have two unresolved type variables and hence | |
579 | /// don't have enough information to process the coercion | |
580 | /// obligation yet. At the moment, we actually process coercions | |
581 | /// very much like subtyping and don't handle the full coercion | |
582 | /// logic. | |
583 | Coerce(CoercePredicate<'tcx>), | |
584 | ||
ea8adc8c | 585 | /// Constant initializer must evaluate successfully. |
94222f64 | 586 | ConstEvaluatable(ty::Unevaluated<'tcx, ()>), |
f9f354fc XL |
587 | |
588 | /// Constants must be equal. The first component is the const that is expected. | |
589 | ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>), | |
1b1a35ee XL |
590 | |
591 | /// Represents a type found in the environment that we can use for implied bounds. | |
592 | /// | |
593 | /// Only used for Chalk. | |
594 | TypeWellFormedFromEnv(Ty<'tcx>), | |
e9174d1e SL |
595 | } |
596 | ||
83c7162d XL |
597 | /// The crate outlives map is computed during typeck and contains the |
598 | /// outlives of every item in the local crate. You should not use it | |
599 | /// directly, because to do so will make your pass dependent on the | |
600 | /// HIR of every item in the local crate. Instead, use | |
601 | /// `tcx.inferred_outlives_of()` to get the outlives for a *particular* | |
602 | /// item. | |
5869c6ff | 603 | #[derive(HashStable, Debug)] |
83c7162d XL |
604 | pub struct CratePredicatesMap<'tcx> { |
605 | /// For each struct with outlive bounds, maps to a vector of the | |
606 | /// predicate of its outlive bounds. If an item has no outlives | |
607 | /// bounds, it will have no entry. | |
3dfed10e | 608 | pub predicates: FxHashMap<DefId, &'tcx [(Predicate<'tcx>, Span)]>, |
83c7162d XL |
609 | } |
610 | ||
dc9dc135 | 611 | impl<'tcx> Predicate<'tcx> { |
e9174d1e SL |
612 | /// Performs a substitution suitable for going from a |
613 | /// poly-trait-ref to supertraits that must hold if that | |
614 | /// poly-trait-ref holds. This is slightly different from a normal | |
9fa01778 | 615 | /// substitution in terms of what happens with bound regions. See |
e9174d1e | 616 | /// lengthy comment below for details. |
dc9dc135 | 617 | pub fn subst_supertrait( |
f9f354fc | 618 | self, |
dc9dc135 XL |
619 | tcx: TyCtxt<'tcx>, |
620 | trait_ref: &ty::PolyTraitRef<'tcx>, | |
3dfed10e | 621 | ) -> Predicate<'tcx> { |
e9174d1e SL |
622 | // The interaction between HRTB and supertraits is not entirely |
623 | // obvious. Let me walk you (and myself) through an example. | |
624 | // | |
625 | // Let's start with an easy case. Consider two traits: | |
626 | // | |
a1dfa0c6 | 627 | // trait Foo<'a>: Bar<'a,'a> { } |
e9174d1e SL |
628 | // trait Bar<'b,'c> { } |
629 | // | |
a1dfa0c6 XL |
630 | // Now, if we have a trait reference `for<'x> T: Foo<'x>`, then |
631 | // we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we | |
e9174d1e SL |
632 | // knew that `Foo<'x>` (for any 'x) then we also know that |
633 | // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from | |
634 | // normal substitution. | |
635 | // | |
636 | // In terms of why this is sound, the idea is that whenever there | |
637 | // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` | |
638 | // holds. So if there is an impl of `T:Foo<'a>` that applies to | |
639 | // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all | |
640 | // `'a`. | |
641 | // | |
642 | // Another example to be careful of is this: | |
643 | // | |
a1dfa0c6 | 644 | // trait Foo1<'a>: for<'b> Bar1<'a,'b> { } |
e9174d1e SL |
645 | // trait Bar1<'b,'c> { } |
646 | // | |
a1dfa0c6 XL |
647 | // Here, if we have `for<'x> T: Foo1<'x>`, then what do we know? |
648 | // The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The | |
e9174d1e | 649 | // reason is similar to the previous example: any impl of |
a1dfa0c6 | 650 | // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So |
e9174d1e SL |
651 | // basically we would want to collapse the bound lifetimes from |
652 | // the input (`trait_ref`) and the supertraits. | |
653 | // | |
654 | // To achieve this in practice is fairly straightforward. Let's | |
655 | // consider the more complicated scenario: | |
656 | // | |
a1dfa0c6 XL |
657 | // - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x` |
658 | // has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`, | |
e9174d1e SL |
659 | // where both `'x` and `'b` would have a DB index of 1. |
660 | // The substitution from the input trait-ref is therefore going to be | |
661 | // `'a => 'x` (where `'x` has a DB index of 1). | |
c295e0f8 | 662 | // - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an |
e9174d1e SL |
663 | // early-bound parameter and `'b' is a late-bound parameter with a |
664 | // DB index of 1. | |
665 | // - If we replace `'a` with `'x` from the input, it too will have | |
666 | // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` | |
667 | // just as we wanted. | |
668 | // | |
669 | // There is only one catch. If we just apply the substitution `'a | |
670 | // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will | |
671 | // adjust the DB index because we substituting into a binder (it | |
672 | // tries to be so smart...) resulting in `for<'x> for<'b> | |
673 | // Bar1<'x,'b>` (we have no syntax for this, so use your | |
674 | // imagination). Basically the 'x will have DB index of 2 and 'b | |
675 | // will have DB index of 1. Not quite what we want. So we apply | |
676 | // the substitution to the *contents* of the trait reference, | |
677 | // rather than the trait reference itself (put another way, the | |
678 | // substitution code expects equal binding levels in the values | |
679 | // from the substitution and the value being substituted into, and | |
680 | // this trick achieves that). | |
cdc7bbd5 XL |
681 | |
682 | // Working through the second example: | |
683 | // trait_ref: for<'x> T: Foo1<'^0.0>; substs: [T, '^0.0] | |
684 | // predicate: for<'b> Self: Bar1<'a, '^0.0>; substs: [Self, 'a, '^0.0] | |
685 | // We want to end up with: | |
686 | // for<'x, 'b> T: Bar1<'^0.0, '^0.1> | |
687 | // To do this: | |
688 | // 1) We must shift all bound vars in predicate by the length | |
689 | // of trait ref's bound vars. So, we would end up with predicate like | |
690 | // Self: Bar1<'a, '^0.1> | |
691 | // 2) We can then apply the trait substs to this, ending up with | |
692 | // T: Bar1<'^0.0, '^0.1> | |
693 | // 3) Finally, to create the final bound vars, we concatenate the bound | |
694 | // vars of the trait ref with those of the predicate: | |
695 | // ['x, 'b] | |
696 | let bound_pred = self.kind(); | |
697 | let pred_bound_vars = bound_pred.bound_vars(); | |
698 | let trait_bound_vars = trait_ref.bound_vars(); | |
699 | // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1> | |
700 | let shifted_pred = | |
701 | tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); | |
702 | // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> | |
703 | let new = shifted_pred.subst(tcx, trait_ref.skip_binder().substs); | |
704 | // 3) ['x] + ['b] -> ['x, 'b] | |
705 | let bound_vars = | |
706 | tcx.mk_bound_variable_kinds(trait_bound_vars.iter().chain(pred_bound_vars)); | |
707 | tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars)) | |
e9174d1e SL |
708 | } |
709 | } | |
710 | ||
3dfed10e | 711 | #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] |
60c5eb7d | 712 | #[derive(HashStable, TypeFoldable)] |
e9174d1e | 713 | pub struct TraitPredicate<'tcx> { |
dfeec247 | 714 | pub trait_ref: TraitRef<'tcx>, |
94222f64 XL |
715 | |
716 | pub constness: BoundConstness, | |
3c0e092e XL |
717 | |
718 | pub polarity: ImplPolarity, | |
e9174d1e | 719 | } |
a1dfa0c6 | 720 | |
cdc7bbd5 | 721 | pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; |
e9174d1e SL |
722 | |
723 | impl<'tcx> TraitPredicate<'tcx> { | |
f9f354fc | 724 | pub fn def_id(self) -> DefId { |
e9174d1e SL |
725 | self.trait_ref.def_id |
726 | } | |
727 | ||
f9f354fc | 728 | pub fn self_ty(self) -> Ty<'tcx> { |
e9174d1e SL |
729 | self.trait_ref.self_ty() |
730 | } | |
731 | } | |
732 | ||
733 | impl<'tcx> PolyTraitPredicate<'tcx> { | |
f9f354fc | 734 | pub fn def_id(self) -> DefId { |
416331ca | 735 | // Ok to skip binder since trait `DefId` does not care about regions. |
83c7162d | 736 | self.skip_binder().def_id() |
e9174d1e | 737 | } |
fc512014 | 738 | |
cdc7bbd5 | 739 | pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { |
fc512014 XL |
740 | self.map_bound(|trait_ref| trait_ref.self_ty()) |
741 | } | |
e9174d1e SL |
742 | } |
743 | ||
3dfed10e | 744 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] |
60c5eb7d | 745 | #[derive(HashStable, TypeFoldable)] |
dc9dc135 | 746 | pub struct OutlivesPredicate<A, B>(pub A, pub B); // `A: B` |
dc9dc135 XL |
747 | pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>; |
748 | pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>; | |
cdc7bbd5 XL |
749 | pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>; |
750 | pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>; | |
e9174d1e | 751 | |
94222f64 XL |
752 | /// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates |
753 | /// whether the `a` type is the type that we should label as "expected" when | |
754 | /// presenting user diagnostics. | |
3dfed10e | 755 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] |
60c5eb7d | 756 | #[derive(HashStable, TypeFoldable)] |
cc61c64b XL |
757 | pub struct SubtypePredicate<'tcx> { |
758 | pub a_is_expected: bool, | |
759 | pub a: Ty<'tcx>, | |
dfeec247 | 760 | pub b: Ty<'tcx>, |
cc61c64b | 761 | } |
cdc7bbd5 | 762 | pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; |
cc61c64b | 763 | |
94222f64 XL |
764 | /// Encodes that we have to coerce *from* the `a` type to the `b` type. |
765 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] | |
766 | #[derive(HashStable, TypeFoldable)] | |
767 | pub struct CoercePredicate<'tcx> { | |
768 | pub a: Ty<'tcx>, | |
769 | pub b: Ty<'tcx>, | |
770 | } | |
771 | pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; | |
772 | ||
e9174d1e SL |
773 | /// This kind of predicate has no *direct* correspondent in the |
774 | /// syntax, but it roughly corresponds to the syntactic forms: | |
775 | /// | |
9fa01778 | 776 | /// 1. `T: TraitRef<..., Item = Type>` |
e9174d1e SL |
777 | /// 2. `<T as TraitRef<...>>::Item == Type` (NYI) |
778 | /// | |
779 | /// In particular, form #1 is "desugared" to the combination of a | |
a1dfa0c6 | 780 | /// normal trait predicate (`T: TraitRef<...>`) and one of these |
e9174d1e | 781 | /// predicates. Form #2 is a broader form in that it also permits |
ff7c6d11 XL |
782 | /// equality between arbitrary types. Processing an instance of |
783 | /// Form #2 eventually yields one of these `ProjectionPredicate` | |
e9174d1e | 784 | /// instances to normalize the LHS. |
3dfed10e | 785 | #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] |
60c5eb7d | 786 | #[derive(HashStable, TypeFoldable)] |
e9174d1e SL |
787 | pub struct ProjectionPredicate<'tcx> { |
788 | pub projection_ty: ProjectionTy<'tcx>, | |
789 | pub ty: Ty<'tcx>, | |
790 | } | |
791 | ||
cdc7bbd5 | 792 | pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; |
e9174d1e SL |
793 | |
794 | impl<'tcx> PolyProjectionPredicate<'tcx> { | |
6a06907d XL |
795 | /// Returns the `DefId` of the trait of the associated item being projected. |
796 | #[inline] | |
797 | pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { | |
798 | self.skip_binder().projection_ty.trait_def_id(tcx) | |
799 | } | |
800 | ||
6a06907d XL |
801 | /// Get the [PolyTraitRef] required for this projection to be well formed. |
802 | /// Note that for generic associated types the predicates of the associated | |
803 | /// type also need to be checked. | |
a1dfa0c6 | 804 | #[inline] |
6a06907d | 805 | pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> { |
a1dfa0c6 XL |
806 | // Note: unlike with `TraitRef::to_poly_trait_ref()`, |
807 | // `self.0.trait_ref` is permitted to have escaping regions. | |
041b39d2 XL |
808 | // This is because here `self` has a `Binder` and so does our |
809 | // return value, so we are preserving the number of binding | |
810 | // levels. | |
83c7162d | 811 | self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) |
e9174d1e | 812 | } |
3b2f2976 | 813 | |
cdc7bbd5 | 814 | pub fn ty(&self) -> Binder<'tcx, Ty<'tcx>> { |
83c7162d XL |
815 | self.map_bound(|predicate| predicate.ty) |
816 | } | |
817 | ||
a1dfa0c6 | 818 | /// The `DefId` of the `TraitItem` for the associated type. |
83c7162d | 819 | /// |
a1dfa0c6 XL |
820 | /// Note that this is not the `DefId` of the `TraitRef` containing this |
821 | /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. | |
83c7162d | 822 | pub fn projection_def_id(&self) -> DefId { |
416331ca | 823 | // Ok to skip binder since trait `DefId` does not care about regions. |
83c7162d | 824 | self.skip_binder().projection_ty.item_def_id |
3b2f2976 | 825 | } |
e9174d1e SL |
826 | } |
827 | ||
828 | pub trait ToPolyTraitRef<'tcx> { | |
829 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; | |
830 | } | |
831 | ||
e9174d1e SL |
832 | impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { |
833 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { | |
7453a54e | 834 | self.map_bound_ref(|trait_pred| trait_pred.trait_ref) |
e9174d1e SL |
835 | } |
836 | } | |
837 | ||
e9174d1e | 838 | pub trait ToPredicate<'tcx> { |
f035d41b | 839 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>; |
f9f354fc XL |
840 | } |
841 | ||
cdc7bbd5 | 842 | impl ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { |
f9f354fc | 843 | #[inline(always)] |
f035d41b XL |
844 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { |
845 | tcx.mk_predicate(self) | |
f9f354fc | 846 | } |
e9174d1e SL |
847 | } |
848 | ||
dfeec247 | 849 | impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> { |
f035d41b | 850 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { |
cdc7bbd5 XL |
851 | self.value |
852 | .map_bound(|trait_ref| { | |
3c0e092e XL |
853 | PredicateKind::Trait(ty::TraitPredicate { |
854 | trait_ref, | |
855 | constness: self.constness, | |
856 | polarity: ty::ImplPolarity::Positive, | |
857 | }) | |
cdc7bbd5 XL |
858 | }) |
859 | .to_predicate(tcx) | |
dfeec247 XL |
860 | } |
861 | } | |
862 | ||
94222f64 | 863 | impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { |
f035d41b | 864 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { |
94222f64 | 865 | self.map_bound(PredicateKind::Trait).to_predicate(tcx) |
e9174d1e SL |
866 | } |
867 | } | |
868 | ||
9e0c209e | 869 | impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { |
f035d41b | 870 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { |
5869c6ff | 871 | self.map_bound(PredicateKind::RegionOutlives).to_predicate(tcx) |
e9174d1e SL |
872 | } |
873 | } | |
874 | ||
875 | impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { | |
f035d41b | 876 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { |
5869c6ff | 877 | self.map_bound(PredicateKind::TypeOutlives).to_predicate(tcx) |
e9174d1e SL |
878 | } |
879 | } | |
880 | ||
881 | impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { | |
f035d41b | 882 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { |
5869c6ff | 883 | self.map_bound(PredicateKind::Projection).to_predicate(tcx) |
e9174d1e SL |
884 | } |
885 | } | |
886 | ||
887 | impl<'tcx> Predicate<'tcx> { | |
fc512014 | 888 | pub fn to_opt_poly_trait_ref(self) -> Option<ConstnessAnd<PolyTraitRef<'tcx>>> { |
5869c6ff | 889 | let predicate = self.kind(); |
fc512014 | 890 | match predicate.skip_binder() { |
94222f64 XL |
891 | PredicateKind::Trait(t) => { |
892 | Some(ConstnessAnd { constness: t.constness, value: predicate.rebind(t.trait_ref) }) | |
fc512014 | 893 | } |
5869c6ff XL |
894 | PredicateKind::Projection(..) |
895 | | PredicateKind::Subtype(..) | |
94222f64 | 896 | | PredicateKind::Coerce(..) |
5869c6ff XL |
897 | | PredicateKind::RegionOutlives(..) |
898 | | PredicateKind::WellFormed(..) | |
899 | | PredicateKind::ObjectSafe(..) | |
900 | | PredicateKind::ClosureKind(..) | |
901 | | PredicateKind::TypeOutlives(..) | |
902 | | PredicateKind::ConstEvaluatable(..) | |
903 | | PredicateKind::ConstEquate(..) | |
904 | | PredicateKind::TypeWellFormedFromEnv(..) => None, | |
e9174d1e SL |
905 | } |
906 | } | |
abe05a73 | 907 | |
f9f354fc | 908 | pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> { |
5869c6ff | 909 | let predicate = self.kind(); |
fc512014 | 910 | match predicate.skip_binder() { |
5869c6ff XL |
911 | PredicateKind::TypeOutlives(data) => Some(predicate.rebind(data)), |
912 | PredicateKind::Trait(..) | |
913 | | PredicateKind::Projection(..) | |
914 | | PredicateKind::Subtype(..) | |
94222f64 | 915 | | PredicateKind::Coerce(..) |
5869c6ff XL |
916 | | PredicateKind::RegionOutlives(..) |
917 | | PredicateKind::WellFormed(..) | |
918 | | PredicateKind::ObjectSafe(..) | |
919 | | PredicateKind::ClosureKind(..) | |
920 | | PredicateKind::ConstEvaluatable(..) | |
921 | | PredicateKind::ConstEquate(..) | |
922 | | PredicateKind::TypeWellFormedFromEnv(..) => None, | |
abe05a73 XL |
923 | } |
924 | } | |
e9174d1e SL |
925 | } |
926 | ||
927 | /// Represents the bounds declared on a particular set of type | |
9fa01778 | 928 | /// parameters. Should eventually be generalized into a flag list of |
94222f64 | 929 | /// where-clauses. You can obtain an `InstantiatedPredicates` list from a |
e9174d1e SL |
930 | /// `GenericPredicates` by using the `instantiate` method. Note that this method |
931 | /// reflects an important semantic invariant of `InstantiatedPredicates`: while | |
932 | /// the `GenericPredicates` are expressed in terms of the bound type | |
933 | /// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance | |
934 | /// represented a set of bounds for some particular instantiation, | |
935 | /// meaning that the generic parameters have been substituted with | |
936 | /// their values. | |
937 | /// | |
938 | /// Example: | |
939 | /// | |
dc9dc135 | 940 | /// struct Foo<T, U: Bar<T>> { ... } |
e9174d1e SL |
941 | /// |
942 | /// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like | |
9fa01778 | 943 | /// `[[], [U:Bar<T>]]`. Now if there were some particular reference |
e9174d1e SL |
944 | /// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[], |
945 | /// [usize:Bar<isize>]]`. | |
60c5eb7d | 946 | #[derive(Clone, Debug, TypeFoldable)] |
e9174d1e | 947 | pub struct InstantiatedPredicates<'tcx> { |
9e0c209e | 948 | pub predicates: Vec<Predicate<'tcx>>, |
74b04a01 | 949 | pub spans: Vec<Span>, |
e9174d1e SL |
950 | } |
951 | ||
952 | impl<'tcx> InstantiatedPredicates<'tcx> { | |
953 | pub fn empty() -> InstantiatedPredicates<'tcx> { | |
74b04a01 | 954 | InstantiatedPredicates { predicates: vec![], spans: vec![] } |
e9174d1e SL |
955 | } |
956 | ||
957 | pub fn is_empty(&self) -> bool { | |
958 | self.predicates.is_empty() | |
959 | } | |
960 | } | |
961 | ||
136023e0 | 962 | #[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, TypeFoldable)] |
17df50a5 XL |
963 | pub struct OpaqueTypeKey<'tcx> { |
964 | pub def_id: DefId, | |
965 | pub substs: SubstsRef<'tcx>, | |
966 | } | |
967 | ||
e74abb32 | 968 | rustc_index::newtype_index! { |
532ac7d7 XL |
969 | /// "Universes" are used during type- and trait-checking in the |
970 | /// presence of `for<..>` binders to control what sets of names are | |
971 | /// visible. Universes are arranged into a tree: the root universe | |
972 | /// contains names that are always visible. Each child then adds a new | |
973 | /// set of names that are visible, in addition to those of its parent. | |
974 | /// We say that the child universe "extends" the parent universe with | |
975 | /// new names. | |
976 | /// | |
977 | /// To make this more concrete, consider this program: | |
978 | /// | |
979 | /// ``` | |
980 | /// struct Foo { } | |
981 | /// fn bar<T>(x: T) { | |
982 | /// let y: for<'a> fn(&'a u8, Foo) = ...; | |
983 | /// } | |
984 | /// ``` | |
985 | /// | |
986 | /// The struct name `Foo` is in the root universe U0. But the type | |
987 | /// parameter `T`, introduced on `bar`, is in an extended universe U1 | |
988 | /// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside | |
989 | /// of `bar`, we cannot name `T`. Then, within the type of `y`, the | |
990 | /// region `'a` is in a universe U2 that extends U1, because we can | |
991 | /// name it inside the fn type but not outside. | |
992 | /// | |
993 | /// Universes are used to do type- and trait-checking around these | |
994 | /// "forall" binders (also called **universal quantification**). The | |
995 | /// idea is that when, in the body of `bar`, we refer to `T` as a | |
996 | /// type, we aren't referring to any type in particular, but rather a | |
997 | /// kind of "fresh" type that is distinct from all other types we have | |
998 | /// actually declared. This is called a **placeholder** type, and we | |
999 | /// use universes to talk about this. In other words, a type name in | |
1000 | /// universe 0 always corresponds to some "ground" type that the user | |
1001 | /// declared, but a type name in a non-zero universe is a placeholder | |
1002 | /// type -- an idealized representative of "types in general" that we | |
1003 | /// use for checking generic functions. | |
0bf4aa26 | 1004 | pub struct UniverseIndex { |
60c5eb7d | 1005 | derive [HashStable] |
0bf4aa26 XL |
1006 | DEBUG_FORMAT = "U{}", |
1007 | } | |
1008 | } | |
0531ce1d | 1009 | |
0bf4aa26 | 1010 | impl UniverseIndex { |
ba9703b0 | 1011 | pub const ROOT: UniverseIndex = UniverseIndex::from_u32(0); |
8faf50e0 | 1012 | |
0bf4aa26 XL |
1013 | /// Returns the "next" universe index in order -- this new index |
1014 | /// is considered to extend all previous universes. This | |
9fa01778 | 1015 | /// corresponds to entering a `forall` quantifier. So, for |
0bf4aa26 | 1016 | /// example, suppose we have this type in universe `U`: |
0531ce1d XL |
1017 | /// |
1018 | /// ``` | |
1019 | /// for<'a> fn(&'a u32) | |
1020 | /// ``` | |
1021 | /// | |
1022 | /// Once we "enter" into this `for<'a>` quantifier, we are in a | |
0bf4aa26 XL |
1023 | /// new universe that extends `U` -- in this new universe, we can |
1024 | /// name the region `'a`, but that region was not nameable from | |
1025 | /// `U` because it was not in scope there. | |
1026 | pub fn next_universe(self) -> UniverseIndex { | |
1027 | UniverseIndex::from_u32(self.private.checked_add(1).unwrap()) | |
8faf50e0 XL |
1028 | } |
1029 | ||
a1dfa0c6 | 1030 | /// Returns `true` if `self` can name a name from `other` -- in other words, |
0bf4aa26 | 1031 | /// if the set of names in `self` is a superset of those in |
a1dfa0c6 | 1032 | /// `other` (`self >= other`). |
0bf4aa26 XL |
1033 | pub fn can_name(self, other: UniverseIndex) -> bool { |
1034 | self.private >= other.private | |
83c7162d | 1035 | } |
a1dfa0c6 XL |
1036 | |
1037 | /// Returns `true` if `self` cannot name some names from `other` -- in other | |
1038 | /// words, if the set of names in `self` is a strict subset of | |
1039 | /// those in `other` (`self < other`). | |
1040 | pub fn cannot_name(self, other: UniverseIndex) -> bool { | |
1041 | self.private < other.private | |
1042 | } | |
83c7162d XL |
1043 | } |
1044 | ||
fc512014 XL |
1045 | /// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are |
1046 | /// identified by both a universe, as well as a name residing within that universe. Distinct bound | |
1047 | /// regions/types/consts within the same universe simply have an unknown relationship to one | |
0bf4aa26 | 1048 | /// another. |
3dfed10e | 1049 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)] |
a1dfa0c6 | 1050 | pub struct Placeholder<T> { |
0bf4aa26 | 1051 | pub universe: UniverseIndex, |
a1dfa0c6 | 1052 | pub name: T, |
0531ce1d XL |
1053 | } |
1054 | ||
dc9dc135 XL |
1055 | impl<'a, T> HashStable<StableHashingContext<'a>> for Placeholder<T> |
1056 | where | |
1057 | T: HashStable<StableHashingContext<'a>>, | |
a1dfa0c6 | 1058 | { |
e74abb32 | 1059 | fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
a1dfa0c6 XL |
1060 | self.universe.hash_stable(hcx, hasher); |
1061 | self.name.hash_stable(hcx, hasher); | |
1062 | } | |
1063 | } | |
1064 | ||
fc512014 | 1065 | pub type PlaceholderRegion = Placeholder<BoundRegionKind>; |
a1dfa0c6 XL |
1066 | |
1067 | pub type PlaceholderType = Placeholder<BoundVar>; | |
1068 | ||
fc512014 XL |
1069 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] |
1070 | #[derive(TyEncodable, TyDecodable, PartialOrd, Ord)] | |
1071 | pub struct BoundConst<'tcx> { | |
1072 | pub var: BoundVar, | |
1073 | pub ty: Ty<'tcx>, | |
1074 | } | |
1075 | ||
1076 | pub type PlaceholderConst<'tcx> = Placeholder<BoundConst<'tcx>>; | |
48663c56 | 1077 | |
fc512014 XL |
1078 | /// A `DefId` which, in case it is a const argument, is potentially bundled with |
1079 | /// the `DefId` of the generic parameter it instantiates. | |
3dfed10e | 1080 | /// |
fc512014 XL |
1081 | /// This is used to avoid calls to `type_of` for const arguments during typeck |
1082 | /// which cause cycle errors. | |
3dfed10e XL |
1083 | /// |
1084 | /// ```rust | |
3dfed10e XL |
1085 | /// struct A; |
1086 | /// impl A { | |
fc512014 XL |
1087 | /// fn foo<const N: usize>(&self) -> [u8; N] { [0; N] } |
1088 | /// // ^ const parameter | |
3dfed10e XL |
1089 | /// } |
1090 | /// struct B; | |
1091 | /// impl B { | |
fc512014 XL |
1092 | /// fn foo<const M: u8>(&self) -> usize { 42 } |
1093 | /// // ^ const parameter | |
3dfed10e XL |
1094 | /// } |
1095 | /// | |
1096 | /// fn main() { | |
1097 | /// let a = A; | |
fc512014 XL |
1098 | /// let _b = a.foo::<{ 3 + 7 }>(); |
1099 | /// // ^^^^^^^^^ const argument | |
3dfed10e XL |
1100 | /// } |
1101 | /// ``` | |
fc512014 XL |
1102 | /// |
1103 | /// Let's look at the call `a.foo::<{ 3 + 7 }>()` here. We do not know | |
1104 | /// which `foo` is used until we know the type of `a`. | |
1105 | /// | |
1106 | /// We only know the type of `a` once we are inside of `typeck(main)`. | |
1107 | /// We also end up normalizing the type of `_b` during `typeck(main)` which | |
1108 | /// requires us to evaluate the const argument. | |
1109 | /// | |
1110 | /// To evaluate that const argument we need to know its type, | |
1111 | /// which we would get using `type_of(const_arg)`. This requires us to | |
1112 | /// resolve `foo` as it can be either `usize` or `u8` in this example. | |
1113 | /// However, resolving `foo` once again requires `typeck(main)` to get the type of `a`, | |
1114 | /// which results in a cycle. | |
1115 | /// | |
1116 | /// In short we must not call `type_of(const_arg)` during `typeck(main)`. | |
1117 | /// | |
1118 | /// When first creating the `ty::Const` of the const argument inside of `typeck` we have | |
1119 | /// already resolved `foo` so we know which const parameter this argument instantiates. | |
1120 | /// This means that we also know the expected result of `type_of(const_arg)` even if we | |
1121 | /// aren't allowed to call that query: it is equal to `type_of(const_param)` which is | |
1122 | /// trivial to compute. | |
1123 | /// | |
1124 | /// If we now want to use that constant in a place which potentionally needs its type | |
1125 | /// we also pass the type of its `const_param`. This is the point of `WithOptConstParam`, | |
1126 | /// except that instead of a `Ty` we bundle the `DefId` of the const parameter. | |
1127 | /// Meaning that we need to use `type_of(const_param_did)` if `const_param_did` is `Some` | |
1128 | /// to get the type of `did`. | |
3dfed10e XL |
1129 | #[derive(Copy, Clone, Debug, TypeFoldable, Lift, TyEncodable, TyDecodable)] |
1130 | #[derive(PartialEq, Eq, PartialOrd, Ord)] | |
1131 | #[derive(Hash, HashStable)] | |
1132 | pub struct WithOptConstParam<T> { | |
1133 | pub did: T, | |
29967ef6 | 1134 | /// The `DefId` of the corresponding generic parameter in case `did` is |
3dfed10e XL |
1135 | /// a const argument. |
1136 | /// | |
1137 | /// Note that even if `did` is a const argument, this may still be `None`. | |
1138 | /// All queries taking `WithOptConstParam` start by calling `tcx.opt_const_param_of(def.did)` | |
fc512014 | 1139 | /// to potentially update `param_did` in the case it is `None`. |
3dfed10e XL |
1140 | pub const_param_did: Option<DefId>, |
1141 | } | |
1142 | ||
1143 | impl<T> WithOptConstParam<T> { | |
1144 | /// Creates a new `WithOptConstParam` setting `const_param_did` to `None`. | |
1145 | #[inline(always)] | |
1146 | pub fn unknown(did: T) -> WithOptConstParam<T> { | |
1147 | WithOptConstParam { did, const_param_did: None } | |
1148 | } | |
1149 | } | |
1150 | ||
1151 | impl WithOptConstParam<LocalDefId> { | |
1152 | /// Returns `Some((did, param_did))` if `def_id` is a const argument, | |
1153 | /// `None` otherwise. | |
1154 | #[inline(always)] | |
1155 | pub fn try_lookup(did: LocalDefId, tcx: TyCtxt<'_>) -> Option<(LocalDefId, DefId)> { | |
1156 | tcx.opt_const_param_of(did).map(|param_did| (did, param_did)) | |
1157 | } | |
1158 | ||
1159 | /// In case `self` is unknown but `self.did` is a const argument, this returns | |
1160 | /// a `WithOptConstParam` with the correct `const_param_did`. | |
1161 | #[inline(always)] | |
1162 | pub fn try_upgrade(self, tcx: TyCtxt<'_>) -> Option<WithOptConstParam<LocalDefId>> { | |
1163 | if self.const_param_did.is_none() { | |
1164 | if let const_param_did @ Some(_) = tcx.opt_const_param_of(self.did) { | |
1165 | return Some(WithOptConstParam { did: self.did, const_param_did }); | |
1166 | } | |
1167 | } | |
1168 | ||
1169 | None | |
1170 | } | |
1171 | ||
1172 | pub fn to_global(self) -> WithOptConstParam<DefId> { | |
1173 | WithOptConstParam { did: self.did.to_def_id(), const_param_did: self.const_param_did } | |
1174 | } | |
1175 | ||
1176 | pub fn def_id_for_type_of(self) -> DefId { | |
1177 | if let Some(did) = self.const_param_did { did } else { self.did.to_def_id() } | |
1178 | } | |
1179 | } | |
1180 | ||
1181 | impl WithOptConstParam<DefId> { | |
1182 | pub fn as_local(self) -> Option<WithOptConstParam<LocalDefId>> { | |
1183 | self.did | |
1184 | .as_local() | |
1185 | .map(|did| WithOptConstParam { did, const_param_did: self.const_param_did }) | |
1186 | } | |
1187 | ||
1188 | pub fn as_const_arg(self) -> Option<(LocalDefId, DefId)> { | |
1189 | if let Some(param_did) = self.const_param_did { | |
1190 | if let Some(did) = self.did.as_local() { | |
1191 | return Some((did, param_did)); | |
1192 | } | |
1193 | } | |
1194 | ||
1195 | None | |
1196 | } | |
1197 | ||
3dfed10e XL |
1198 | pub fn is_local(self) -> bool { |
1199 | self.did.is_local() | |
1200 | } | |
1201 | ||
1202 | pub fn def_id_for_type_of(self) -> DefId { | |
1203 | self.const_param_did.unwrap_or(self.did) | |
1204 | } | |
1205 | } | |
1206 | ||
7cac9316 XL |
1207 | /// When type checking, we use the `ParamEnv` to track |
1208 | /// details about the set of where-clauses that are in scope at this | |
1209 | /// particular point. | |
3dfed10e | 1210 | #[derive(Copy, Clone, Hash, PartialEq, Eq)] |
7cac9316 | 1211 | pub struct ParamEnv<'tcx> { |
3dfed10e XL |
1212 | /// This packs both caller bounds and the reveal enum into one pointer. |
1213 | /// | |
1214 | /// Caller bounds are `Obligation`s that the caller must satisfy. This is | |
1215 | /// basically the set of bounds on the in-scope type parameters, translated | |
416331ca | 1216 | /// into `Obligation`s, and elaborated and normalized. |
f035d41b | 1217 | /// |
3dfed10e XL |
1218 | /// Use the `caller_bounds()` method to access. |
1219 | /// | |
94b46f34 | 1220 | /// Typically, this is `Reveal::UserFacing`, but during codegen we |
f035d41b XL |
1221 | /// want `Reveal::All`. |
1222 | /// | |
3dfed10e XL |
1223 | /// Note: This is packed, use the reveal() method to access it. |
1224 | packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, traits::Reveal, true>, | |
7cac9316 XL |
1225 | } |
1226 | ||
3dfed10e XL |
1227 | unsafe impl rustc_data_structures::tagged_ptr::Tag for traits::Reveal { |
1228 | const BITS: usize = 1; | |
17df50a5 | 1229 | #[inline] |
3dfed10e XL |
1230 | fn into_usize(self) -> usize { |
1231 | match self { | |
1232 | traits::Reveal::UserFacing => 0, | |
1233 | traits::Reveal::All => 1, | |
1234 | } | |
1235 | } | |
17df50a5 | 1236 | #[inline] |
3dfed10e XL |
1237 | unsafe fn from_usize(ptr: usize) -> Self { |
1238 | match ptr { | |
1239 | 0 => traits::Reveal::UserFacing, | |
1240 | 1 => traits::Reveal::All, | |
1241 | _ => std::hint::unreachable_unchecked(), | |
1242 | } | |
1243 | } | |
1244 | } | |
1245 | ||
f035d41b XL |
1246 | impl<'tcx> fmt::Debug for ParamEnv<'tcx> { |
1247 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
1248 | f.debug_struct("ParamEnv") | |
1249 | .field("caller_bounds", &self.caller_bounds()) | |
1250 | .field("reveal", &self.reveal()) | |
f035d41b XL |
1251 | .finish() |
1252 | } | |
1253 | } | |
1254 | ||
f035d41b XL |
1255 | impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> { |
1256 | fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { | |
1257 | self.caller_bounds().hash_stable(hcx, hasher); | |
1258 | self.reveal().hash_stable(hcx, hasher); | |
f035d41b XL |
1259 | } |
1260 | } | |
1261 | ||
1262 | impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> { | |
fc512014 | 1263 | fn super_fold_with<F: ty::fold::TypeFolder<'tcx>>(self, folder: &mut F) -> Self { |
1b1a35ee | 1264 | ParamEnv::new(self.caller_bounds().fold_with(folder), self.reveal().fold_with(folder)) |
f035d41b XL |
1265 | } |
1266 | ||
fc512014 | 1267 | fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { |
29967ef6 XL |
1268 | self.caller_bounds().visit_with(visitor)?; |
1269 | self.reveal().visit_with(visitor) | |
f035d41b XL |
1270 | } |
1271 | } | |
1272 | ||
7cac9316 | 1273 | impl<'tcx> ParamEnv<'tcx> { |
0531ce1d | 1274 | /// Construct a trait environment suitable for contexts where |
9fa01778 | 1275 | /// there are no where-clauses in scope. Hidden types (like `impl |
0531ce1d XL |
1276 | /// Trait`) are left hidden, so this is suitable for ordinary |
1277 | /// type-checking. | |
a1dfa0c6 | 1278 | #[inline] |
0531ce1d | 1279 | pub fn empty() -> Self { |
1b1a35ee | 1280 | Self::new(List::empty(), Reveal::UserFacing) |
0531ce1d XL |
1281 | } |
1282 | ||
f035d41b | 1283 | #[inline] |
3dfed10e XL |
1284 | pub fn caller_bounds(self) -> &'tcx List<Predicate<'tcx>> { |
1285 | self.packed.pointer() | |
f035d41b XL |
1286 | } |
1287 | ||
1288 | #[inline] | |
1289 | pub fn reveal(self) -> traits::Reveal { | |
3dfed10e | 1290 | self.packed.tag() |
f035d41b XL |
1291 | } |
1292 | ||
9fa01778 | 1293 | /// Construct a trait environment with no where-clauses in scope |
0531ce1d XL |
1294 | /// where the values of all `impl Trait` and other hidden types |
1295 | /// are revealed. This is suitable for monomorphized, post-typeck | |
94b46f34 | 1296 | /// environments like codegen or doing optimizations. |
0531ce1d | 1297 | /// |
9fa01778 | 1298 | /// N.B., if you want to have predicates in scope, use `ParamEnv::new`, |
0531ce1d | 1299 | /// or invoke `param_env.with_reveal_all()`. |
a1dfa0c6 | 1300 | #[inline] |
0531ce1d | 1301 | pub fn reveal_all() -> Self { |
1b1a35ee | 1302 | Self::new(List::empty(), Reveal::All) |
0531ce1d XL |
1303 | } |
1304 | ||
1305 | /// Construct a trait environment with the given set of predicates. | |
a1dfa0c6 | 1306 | #[inline] |
1b1a35ee XL |
1307 | pub fn new(caller_bounds: &'tcx List<Predicate<'tcx>>, reveal: Reveal) -> Self { |
1308 | ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, reveal) } | |
f035d41b XL |
1309 | } |
1310 | ||
1311 | pub fn with_user_facing(mut self) -> Self { | |
3dfed10e | 1312 | self.packed.set_tag(Reveal::UserFacing); |
f035d41b | 1313 | self |
0531ce1d XL |
1314 | } |
1315 | ||
1316 | /// Returns a new parameter environment with the same clauses, but | |
1317 | /// which "reveals" the true results of projections in all cases | |
9fa01778 | 1318 | /// (even for associated types that are specializable). This is |
94b46f34 | 1319 | /// the desired behavior during codegen and certain other special |
0531ce1d XL |
1320 | /// contexts; normally though we want to use `Reveal::UserFacing`, |
1321 | /// which is the default. | |
3dfed10e XL |
1322 | /// All opaque types in the caller_bounds of the `ParamEnv` |
1323 | /// will be normalized to their underlying types. | |
1324 | /// See PR #65989 and issue #65918 for more details | |
1325 | pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self { | |
1326 | if self.packed.tag() == traits::Reveal::All { | |
1327 | return self; | |
1328 | } | |
1329 | ||
1b1a35ee | 1330 | ParamEnv::new(tcx.normalize_opaque_types(self.caller_bounds()), Reveal::All) |
0531ce1d XL |
1331 | } |
1332 | ||
1333 | /// Returns this same environment but with no caller bounds. | |
17df50a5 | 1334 | #[inline] |
0531ce1d | 1335 | pub fn without_caller_bounds(self) -> Self { |
1b1a35ee | 1336 | Self::new(List::empty(), self.reveal()) |
0531ce1d XL |
1337 | } |
1338 | ||
7cac9316 | 1339 | /// Creates a suitable environment in which to perform trait |
0531ce1d XL |
1340 | /// queries on the given value. When type-checking, this is simply |
1341 | /// the pair of the environment plus value. But when reveal is set to | |
1342 | /// All, then if `value` does not reference any type parameters, we will | |
1343 | /// pair it with the empty environment. This improves caching and is generally | |
1344 | /// invisible. | |
e9174d1e | 1345 | /// |
0731742a | 1346 | /// N.B., we preserve the environment when type-checking because it |
0531ce1d | 1347 | /// is possible for the user to have wacky where-clauses like |
7cac9316 | 1348 | /// `where Box<u32>: Copy`, which are clearly never |
0531ce1d XL |
1349 | /// satisfiable. We generally want to behave as if they were true, |
1350 | /// although the surrounding function is never reachable. | |
7cac9316 | 1351 | pub fn and<T: TypeFoldable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> { |
f035d41b | 1352 | match self.reveal() { |
dfeec247 | 1353 | Reveal::UserFacing => ParamEnvAnd { param_env: self, value }, |
0531ce1d XL |
1354 | |
1355 | Reveal::All => { | |
94222f64 | 1356 | if value.is_known_global() { |
dfeec247 | 1357 | ParamEnvAnd { param_env: self.without_caller_bounds(), value } |
74b04a01 XL |
1358 | } else { |
1359 | ParamEnvAnd { param_env: self, value } | |
0531ce1d | 1360 | } |
e9174d1e SL |
1361 | } |
1362 | } | |
1363 | } | |
1364 | } | |
1365 | ||
fc512014 | 1366 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] |
dfeec247 | 1367 | pub struct ConstnessAnd<T> { |
94222f64 | 1368 | pub constness: BoundConstness, |
dfeec247 XL |
1369 | pub value: T, |
1370 | } | |
1371 | ||
f9f354fc | 1372 | // FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that |
dfeec247 XL |
1373 | // the constness of trait bounds is being propagated correctly. |
1374 | pub trait WithConstness: Sized { | |
1375 | #[inline] | |
94222f64 | 1376 | fn with_constness(self, constness: BoundConstness) -> ConstnessAnd<Self> { |
dfeec247 XL |
1377 | ConstnessAnd { constness, value: self } |
1378 | } | |
1379 | ||
1380 | #[inline] | |
94222f64 XL |
1381 | fn with_const_if_const(self) -> ConstnessAnd<Self> { |
1382 | self.with_constness(BoundConstness::ConstIfConst) | |
dfeec247 XL |
1383 | } |
1384 | ||
1385 | #[inline] | |
1386 | fn without_const(self) -> ConstnessAnd<Self> { | |
94222f64 | 1387 | self.with_constness(BoundConstness::NotConst) |
dfeec247 XL |
1388 | } |
1389 | } | |
1390 | ||
1391 | impl<T> WithConstness for T {} | |
1392 | ||
60c5eb7d | 1393 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] |
7cac9316 XL |
1394 | pub struct ParamEnvAnd<'tcx, T> { |
1395 | pub param_env: ParamEnv<'tcx>, | |
1396 | pub value: T, | |
1397 | } | |
1398 | ||
1399 | impl<'tcx, T> ParamEnvAnd<'tcx, T> { | |
1400 | pub fn into_parts(self) -> (ParamEnv<'tcx>, T) { | |
1401 | (self.param_env, self.value) | |
1402 | } | |
1403 | } | |
1404 | ||
dc9dc135 XL |
1405 | impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for ParamEnvAnd<'tcx, T> |
1406 | where | |
1407 | T: HashStable<StableHashingContext<'a>>, | |
ea8adc8c | 1408 | { |
e74abb32 | 1409 | fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
dfeec247 | 1410 | let ParamEnvAnd { ref param_env, ref value } = *self; |
ea8adc8c XL |
1411 | |
1412 | param_env.hash_stable(hcx, hasher); | |
1413 | value.hash_stable(hcx, hasher); | |
1414 | } | |
1415 | } | |
1416 | ||
532ac7d7 | 1417 | #[derive(Copy, Clone, Debug, HashStable)] |
8bb4bdeb | 1418 | pub struct Destructor { |
9fa01778 | 1419 | /// The `DefId` of the destructor method |
8bb4bdeb | 1420 | pub did: DefId, |
c295e0f8 XL |
1421 | /// The constness of the destructor method |
1422 | pub constness: hir::Constness, | |
8bb4bdeb XL |
1423 | } |
1424 | ||
b7449926 | 1425 | bitflags! { |
532ac7d7 | 1426 | #[derive(HashStable)] |
b7449926 XL |
1427 | pub struct VariantFlags: u32 { |
1428 | const NO_VARIANT_FLAGS = 0; | |
1429 | /// Indicates whether the field list of this variant is `#[non_exhaustive]`. | |
1430 | const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0; | |
1b1a35ee XL |
1431 | /// Indicates whether this variant was obtained as part of recovering from |
1432 | /// a syntactic error. May be incomplete or bogus. | |
1433 | const IS_RECOVERED = 1 << 1; | |
e9174d1e SL |
1434 | } |
1435 | } | |
1436 | ||
94222f64 | 1437 | /// Definition of a variant -- a struct's fields or an enum variant. |
60c5eb7d | 1438 | #[derive(Debug, HashStable)] |
476ff2be | 1439 | pub struct VariantDef { |
532ac7d7 XL |
1440 | /// `DefId` that identifies the variant itself. |
1441 | /// If this variant belongs to a struct or union, then this is a copy of its `DefId`. | |
1442 | pub def_id: DefId, | |
1443 | /// `DefId` that identifies the variant's constructor. | |
1444 | /// If this variant is a struct variant, then this is `None`. | |
1445 | pub ctor_def_id: Option<DefId>, | |
1446 | /// Variant or struct name. | |
60c5eb7d | 1447 | #[stable_hasher(project(name))] |
532ac7d7 XL |
1448 | pub ident: Ident, |
1449 | /// Discriminant of this variant. | |
8bb4bdeb | 1450 | pub discr: VariantDiscr, |
532ac7d7 | 1451 | /// Fields of this variant. |
476ff2be | 1452 | pub fields: Vec<FieldDef>, |
532ac7d7 | 1453 | /// Type of constructor of variant. |
c30ab7b3 | 1454 | pub ctor_kind: CtorKind, |
532ac7d7 | 1455 | /// Flags of the variant (e.g. is field list non-exhaustive)? |
b7449926 | 1456 | flags: VariantFlags, |
e9174d1e SL |
1457 | } |
1458 | ||
1b1a35ee | 1459 | impl VariantDef { |
9fa01778 | 1460 | /// Creates a new `VariantDef`. |
b7449926 | 1461 | /// |
532ac7d7 XL |
1462 | /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef` |
1463 | /// represents an enum variant). | |
1464 | /// | |
1465 | /// `ctor_did` is the `DefId` that identifies the constructor of unit or | |
1466 | /// tuple-variants/structs. If this is a `struct`-variant then this should be `None`. | |
0bf4aa26 | 1467 | /// |
532ac7d7 XL |
1468 | /// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that |
1469 | /// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having | |
1470 | /// to go through the redirect of checking the ctor's attributes - but compiling a small crate | |
1471 | /// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any | |
0bf4aa26 XL |
1472 | /// built-in trait), and we do not want to load attributes twice. |
1473 | /// | |
1474 | /// If someone speeds up attribute loading to not be a performance concern, they can | |
9fa01778 | 1475 | /// remove this hack and use the constructor `DefId` everywhere. |
532ac7d7 | 1476 | pub fn new( |
532ac7d7 XL |
1477 | ident: Ident, |
1478 | variant_did: Option<DefId>, | |
1479 | ctor_def_id: Option<DefId>, | |
1480 | discr: VariantDiscr, | |
1481 | fields: Vec<FieldDef>, | |
1482 | ctor_kind: CtorKind, | |
1483 | adt_kind: AdtKind, | |
1484 | parent_did: DefId, | |
1485 | recovered: bool, | |
3dfed10e | 1486 | is_field_list_non_exhaustive: bool, |
532ac7d7 XL |
1487 | ) -> Self { |
1488 | debug!( | |
1489 | "VariantDef::new(ident = {:?}, variant_did = {:?}, ctor_def_id = {:?}, discr = {:?}, | |
1490 | fields = {:?}, ctor_kind = {:?}, adt_kind = {:?}, parent_did = {:?})", | |
dfeec247 | 1491 | ident, variant_did, ctor_def_id, discr, fields, ctor_kind, adt_kind, parent_did, |
532ac7d7 XL |
1492 | ); |
1493 | ||
b7449926 | 1494 | let mut flags = VariantFlags::NO_VARIANT_FLAGS; |
3dfed10e XL |
1495 | if is_field_list_non_exhaustive { |
1496 | flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; | |
b7449926 | 1497 | } |
532ac7d7 | 1498 | |
1b1a35ee XL |
1499 | if recovered { |
1500 | flags |= VariantFlags::IS_RECOVERED; | |
1501 | } | |
1502 | ||
b7449926 | 1503 | VariantDef { |
532ac7d7 XL |
1504 | def_id: variant_did.unwrap_or(parent_did), |
1505 | ctor_def_id, | |
0731742a | 1506 | ident, |
b7449926 XL |
1507 | discr, |
1508 | fields, | |
1509 | ctor_kind, | |
532ac7d7 | 1510 | flags, |
b7449926 XL |
1511 | } |
1512 | } | |
1513 | ||
532ac7d7 | 1514 | /// Is this field list non-exhaustive? |
b7449926 XL |
1515 | #[inline] |
1516 | pub fn is_field_list_non_exhaustive(&self) -> bool { | |
1517 | self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE) | |
1518 | } | |
f035d41b | 1519 | |
1b1a35ee XL |
1520 | /// Was this variant obtained as part of recovering from a syntactic error? |
1521 | #[inline] | |
1522 | pub fn is_recovered(&self) -> bool { | |
1523 | self.flags.intersects(VariantFlags::IS_RECOVERED) | |
f035d41b | 1524 | } |
b7449926 XL |
1525 | } |
1526 | ||
3dfed10e | 1527 | #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] |
8bb4bdeb | 1528 | pub enum VariantDiscr { |
0731742a | 1529 | /// Explicit value for this variant, i.e., `X = 123`. |
8bb4bdeb XL |
1530 | /// The `DefId` corresponds to the embedded constant. |
1531 | Explicit(DefId), | |
1532 | ||
1533 | /// The previous variant's discriminant plus one. | |
1534 | /// For efficiency reasons, the distance from the | |
1535 | /// last `Explicit` discriminant is being stored, | |
1536 | /// or `0` for the first variant, if it has none. | |
a1dfa0c6 | 1537 | Relative(u32), |
8bb4bdeb XL |
1538 | } |
1539 | ||
532ac7d7 | 1540 | #[derive(Debug, HashStable)] |
476ff2be | 1541 | pub struct FieldDef { |
e9174d1e | 1542 | pub did: DefId, |
532ac7d7 | 1543 | #[stable_hasher(project(name))] |
94b46f34 | 1544 | pub ident: Ident, |
54a0048b | 1545 | pub vis: Visibility, |
e9174d1e SL |
1546 | } |
1547 | ||
cc61c64b | 1548 | bitflags! { |
3dfed10e | 1549 | #[derive(TyEncodable, TyDecodable, Default, HashStable)] |
ea8adc8c XL |
1550 | pub struct ReprFlags: u8 { |
1551 | const IS_C = 1 << 0; | |
83c7162d XL |
1552 | const IS_SIMD = 1 << 1; |
1553 | const IS_TRANSPARENT = 1 << 2; | |
cc61c64b | 1554 | // Internal only for now. If true, don't reorder fields. |
83c7162d | 1555 | const IS_LINEAR = 1 << 3; |
74b04a01 XL |
1556 | // If true, don't expose any niche to type's context. |
1557 | const HIDE_NICHE = 1 << 4; | |
c295e0f8 XL |
1558 | // If true, the type's layout can be randomized using |
1559 | // the seed stored in `ReprOptions.layout_seed` | |
1560 | const RANDOMIZE_LAYOUT = 1 << 5; | |
cc61c64b XL |
1561 | // Any of these flags being set prevent field reordering optimisation. |
1562 | const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits | | |
cc61c64b | 1563 | ReprFlags::IS_SIMD.bits | |
ea8adc8c | 1564 | ReprFlags::IS_LINEAR.bits; |
cc61c64b XL |
1565 | } |
1566 | } | |
1567 | ||
8bb4bdeb | 1568 | /// Represents the repr options provided by the user, |
3dfed10e | 1569 | #[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Default, HashStable)] |
8bb4bdeb | 1570 | pub struct ReprOptions { |
8bb4bdeb | 1571 | pub int: Option<attr::IntType>, |
e1599b0c XL |
1572 | pub align: Option<Align>, |
1573 | pub pack: Option<Align>, | |
cc61c64b | 1574 | pub flags: ReprFlags, |
c295e0f8 XL |
1575 | /// The seed to be used for randomizing a type's layout |
1576 | /// | |
1577 | /// Note: This could technically be a `[u8; 16]` (a `u128`) which would | |
1578 | /// be the "most accurate" hash as it'd encompass the item and crate | |
1579 | /// hash without loss, but it does pay the price of being larger. | |
1580 | /// Everything's a tradeoff, a `u64` seed should be sufficient for our | |
1581 | /// purposes (primarily `-Z randomize-layout`) | |
1582 | pub field_shuffle_seed: u64, | |
8bb4bdeb XL |
1583 | } |
1584 | ||
1585 | impl ReprOptions { | |
dc9dc135 | 1586 | pub fn new(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { |
cc61c64b XL |
1587 | let mut flags = ReprFlags::empty(); |
1588 | let mut size = None; | |
e1599b0c XL |
1589 | let mut max_align: Option<Align> = None; |
1590 | let mut min_pack: Option<Align> = None; | |
c295e0f8 XL |
1591 | |
1592 | // Generate a deterministically-derived seed from the item's path hash | |
1593 | // to allow for cross-crate compilation to actually work | |
1594 | let field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash(); | |
1595 | ||
8bb4bdeb | 1596 | for attr in tcx.get_attrs(did).iter() { |
3dfed10e | 1597 | for r in attr::find_repr_attrs(&tcx.sess, attr) { |
cc61c64b | 1598 | flags.insert(match r { |
2c00a5a8 | 1599 | attr::ReprC => ReprFlags::IS_C, |
83c7162d | 1600 | attr::ReprPacked(pack) => { |
e1599b0c XL |
1601 | let pack = Align::from_bytes(pack as u64).unwrap(); |
1602 | min_pack = Some(if let Some(min_pack) = min_pack { | |
1603 | min_pack.min(pack) | |
83c7162d XL |
1604 | } else { |
1605 | pack | |
e1599b0c | 1606 | }); |
83c7162d | 1607 | ReprFlags::empty() |
dfeec247 | 1608 | } |
2c00a5a8 | 1609 | attr::ReprTransparent => ReprFlags::IS_TRANSPARENT, |
74b04a01 | 1610 | attr::ReprNoNiche => ReprFlags::HIDE_NICHE, |
cc61c64b XL |
1611 | attr::ReprSimd => ReprFlags::IS_SIMD, |
1612 | attr::ReprInt(i) => { | |
1613 | size = Some(i); | |
1614 | ReprFlags::empty() | |
dfeec247 | 1615 | } |
cc61c64b | 1616 | attr::ReprAlign(align) => { |
e1599b0c | 1617 | max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap())); |
cc61c64b | 1618 | ReprFlags::empty() |
dfeec247 | 1619 | } |
cc61c64b | 1620 | }); |
8bb4bdeb XL |
1621 | } |
1622 | } | |
1623 | ||
c295e0f8 XL |
1624 | // If `-Z randomize-layout` was enabled for the type definition then we can |
1625 | // consider performing layout randomization | |
1626 | if tcx.sess.opts.debugging_opts.randomize_layout { | |
1627 | flags.insert(ReprFlags::RANDOMIZE_LAYOUT); | |
1628 | } | |
1629 | ||
cc61c64b | 1630 | // This is here instead of layout because the choice must make it into metadata. |
532ac7d7 | 1631 | if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) { |
cc61c64b XL |
1632 | flags.insert(ReprFlags::IS_LINEAR); |
1633 | } | |
c295e0f8 XL |
1634 | |
1635 | Self { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed } | |
8bb4bdeb XL |
1636 | } |
1637 | ||
cc61c64b | 1638 | #[inline] |
dfeec247 XL |
1639 | pub fn simd(&self) -> bool { |
1640 | self.flags.contains(ReprFlags::IS_SIMD) | |
1641 | } | |
c295e0f8 | 1642 | |
cc61c64b | 1643 | #[inline] |
dfeec247 XL |
1644 | pub fn c(&self) -> bool { |
1645 | self.flags.contains(ReprFlags::IS_C) | |
1646 | } | |
c295e0f8 | 1647 | |
cc61c64b | 1648 | #[inline] |
dfeec247 XL |
1649 | pub fn packed(&self) -> bool { |
1650 | self.pack.is_some() | |
1651 | } | |
c295e0f8 | 1652 | |
cc61c64b | 1653 | #[inline] |
dfeec247 XL |
1654 | pub fn transparent(&self) -> bool { |
1655 | self.flags.contains(ReprFlags::IS_TRANSPARENT) | |
1656 | } | |
c295e0f8 | 1657 | |
2c00a5a8 | 1658 | #[inline] |
dfeec247 XL |
1659 | pub fn linear(&self) -> bool { |
1660 | self.flags.contains(ReprFlags::IS_LINEAR) | |
1661 | } | |
c295e0f8 | 1662 | |
74b04a01 XL |
1663 | #[inline] |
1664 | pub fn hide_niche(&self) -> bool { | |
1665 | self.flags.contains(ReprFlags::HIDE_NICHE) | |
1666 | } | |
cc61c64b | 1667 | |
f9f354fc XL |
1668 | /// Returns the discriminant type, given these `repr` options. |
1669 | /// This must only be called on enums! | |
8bb4bdeb | 1670 | pub fn discr_type(&self) -> attr::IntType { |
2c00a5a8 | 1671 | self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize)) |
8bb4bdeb XL |
1672 | } |
1673 | ||
a1dfa0c6 | 1674 | /// Returns `true` if this `#[repr()]` should inhabit "smart enum |
8bb4bdeb XL |
1675 | /// layout" optimizations, such as representing `Foo<&T>` as a |
1676 | /// single pointer. | |
1677 | pub fn inhibit_enum_layout_opt(&self) -> bool { | |
cc61c64b | 1678 | self.c() || self.int.is_some() |
8bb4bdeb | 1679 | } |
83c7162d | 1680 | |
a1dfa0c6 | 1681 | /// Returns `true` if this `#[repr()]` should inhibit struct field reordering |
9fa01778 | 1682 | /// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr(<int>)`. |
83c7162d | 1683 | pub fn inhibit_struct_field_reordering_opt(&self) -> bool { |
e1599b0c XL |
1684 | if let Some(pack) = self.pack { |
1685 | if pack.bytes() == 1 { | |
1686 | return true; | |
1687 | } | |
1688 | } | |
c295e0f8 | 1689 | |
e1599b0c | 1690 | self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some() |
83c7162d | 1691 | } |
a1dfa0c6 | 1692 | |
c295e0f8 XL |
1693 | /// Returns `true` if this type is valid for reordering and `-Z randomize-layout` |
1694 | /// was enabled for its declaration crate | |
1695 | pub fn can_randomize_type_layout(&self) -> bool { | |
1696 | !self.inhibit_struct_field_reordering_opt() | |
1697 | && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT) | |
1698 | } | |
1699 | ||
9fa01778 | 1700 | /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations. |
a1dfa0c6 XL |
1701 | pub fn inhibit_union_abi_opt(&self) -> bool { |
1702 | self.c() | |
1703 | } | |
8bb4bdeb XL |
1704 | } |
1705 | ||
dc9dc135 | 1706 | impl<'tcx> FieldDef { |
c295e0f8 XL |
1707 | /// Returns the type of this field. The resulting type is not normalized. The `subst` is |
1708 | /// typically obtained via the second field of `TyKind::AdtDef`. | |
dc9dc135 | 1709 | pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> { |
7cac9316 | 1710 | tcx.type_of(self.did).subst(tcx, subst) |
e9174d1e | 1711 | } |
e9174d1e SL |
1712 | } |
1713 | ||
ba9703b0 | 1714 | pub type Attributes<'tcx> = &'tcx [ast::Attribute]; |
cc61c64b | 1715 | |
0731742a XL |
1716 | #[derive(Debug, PartialEq, Eq)] |
1717 | pub enum ImplOverlapKind { | |
1718 | /// These impls are always allowed to overlap. | |
dfeec247 | 1719 | Permitted { |
74b04a01 | 1720 | /// Whether or not the impl is permitted due to the trait being a `#[marker]` trait |
dfeec247 XL |
1721 | marker: bool, |
1722 | }, | |
0731742a XL |
1723 | /// These impls are allowed to overlap, but that raises |
1724 | /// an issue #33140 future-compatibility warning. | |
1725 | /// | |
1726 | /// Some background: in Rust 1.0, the trait-object types `Send + Sync` (today's | |
1727 | /// `dyn Send + Sync`) and `Sync + Send` (now `dyn Sync + Send`) were different. | |
1728 | /// | |
1729 | /// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied | |
1730 | /// that difference, making what reduces to the following set of impls: | |
1731 | /// | |
1732 | /// ``` | |
1733 | /// trait Trait {} | |
1734 | /// impl Trait for dyn Send + Sync {} | |
1735 | /// impl Trait for dyn Sync + Send {} | |
1736 | /// ``` | |
1737 | /// | |
1738 | /// Obviously, once we made these types be identical, that code causes a coherence | |
1739 | /// error and a fairly big headache for us. However, luckily for us, the trait | |
1740 | /// `Trait` used in this case is basically a marker trait, and therefore having | |
1741 | /// overlapping impls for it is sound. | |
1742 | /// | |
1743 | /// To handle this, we basically regard the trait as a marker trait, with an additional | |
1744 | /// future-compatibility warning. To avoid accidentally "stabilizing" this feature, | |
1745 | /// it has the following restrictions: | |
1746 | /// | |
1747 | /// 1. The trait must indeed be a marker-like trait (i.e., no items), and must be | |
1748 | /// positive impls. | |
1749 | /// 2. The trait-ref of both impls must be equal. | |
1750 | /// 3. The trait-ref of both impls must be a trait object type consisting only of | |
1751 | /// marker traits. | |
1752 | /// 4. Neither of the impls can have any where-clauses. | |
1753 | /// | |
1754 | /// Once `traitobject` 0.1.0 is no longer an active concern, this hack can be removed. | |
dfeec247 | 1755 | Issue33140, |
0731742a XL |
1756 | } |
1757 | ||
dc9dc135 | 1758 | impl<'tcx> TyCtxt<'tcx> { |
3dfed10e XL |
1759 | pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> { |
1760 | self.typeck(self.hir().body_owner_def_id(body)) | |
32a655c1 SL |
1761 | } |
1762 | ||
74b04a01 | 1763 | pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'tcx AssocItem> { |
476ff2be | 1764 | self.associated_items(id) |
74b04a01 | 1765 | .in_definition_order() |
ba9703b0 | 1766 | .filter(|item| item.kind == AssocKind::Fn && item.defaultness.has_value()) |
e9174d1e SL |
1767 | } |
1768 | ||
29967ef6 XL |
1769 | fn item_name_from_hir(self, def_id: DefId) -> Option<Ident> { |
1770 | self.hir().get_if_local(def_id).and_then(|node| node.ident()) | |
1771 | } | |
1772 | ||
1773 | fn item_name_from_def_id(self, def_id: DefId) -> Option<Symbol> { | |
1774 | if def_id.index == CRATE_DEF_INDEX { | |
17df50a5 | 1775 | Some(self.crate_name(def_id.krate)) |
29967ef6 XL |
1776 | } else { |
1777 | let def_key = self.def_key(def_id); | |
1778 | match def_key.disambiguated_data.data { | |
1779 | // The name of a constructor is that of its parent. | |
1780 | rustc_hir::definitions::DefPathData::Ctor => self.item_name_from_def_id(DefId { | |
1781 | krate: def_id.krate, | |
1782 | index: def_key.parent.unwrap(), | |
1783 | }), | |
1784 | _ => def_key.disambiguated_data.data.get_opt_name(), | |
1785 | } | |
1786 | } | |
1787 | } | |
1788 | ||
1789 | /// Look up the name of an item across crates. This does not look at HIR. | |
1790 | /// | |
1791 | /// When possible, this function should be used for cross-crate lookups over | |
1792 | /// [`opt_item_name`] to avoid invalidating the incremental cache. If you | |
1793 | /// need to handle items without a name, or HIR items that will not be | |
1794 | /// serialized cross-crate, or if you need the span of the item, use | |
1795 | /// [`opt_item_name`] instead. | |
1796 | /// | |
1797 | /// [`opt_item_name`]: Self::opt_item_name | |
1798 | pub fn item_name(self, id: DefId) -> Symbol { | |
1799 | // Look at cross-crate items first to avoid invalidating the incremental cache | |
1800 | // unless we have to. | |
1801 | self.item_name_from_def_id(id).unwrap_or_else(|| { | |
1802 | bug!("item_name: no name for {:?}", self.def_path(id)); | |
1803 | }) | |
1804 | } | |
1805 | ||
1806 | /// Look up the name and span of an item or [`Node`]. | |
1807 | /// | |
1808 | /// See [`item_name`][Self::item_name] for more information. | |
e1599b0c | 1809 | pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> { |
29967ef6 XL |
1810 | // Look at the HIR first so the span will be correct if this is a local item. |
1811 | self.item_name_from_hir(def_id) | |
1812 | .or_else(|| self.item_name_from_def_id(def_id).map(Ident::with_dummy_span)) | |
e1599b0c XL |
1813 | } |
1814 | ||
f9f354fc | 1815 | pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> { |
5869c6ff XL |
1816 | if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { |
1817 | Some(self.associated_item(def_id)) | |
7cac9316 | 1818 | } else { |
5869c6ff XL |
1819 | None |
1820 | } | |
e9174d1e SL |
1821 | } |
1822 | ||
3dfed10e XL |
1823 | pub fn field_index(self, hir_id: hir::HirId, typeck_results: &TypeckResults<'_>) -> usize { |
1824 | typeck_results.field_indices().get(hir_id).cloned().expect("no index for a field") | |
83c7162d XL |
1825 | } |
1826 | ||
1827 | pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> { | |
dfeec247 | 1828 | variant.fields.iter().position(|field| self.hygienic_eq(ident, field.ident, variant.def_id)) |
83c7162d XL |
1829 | } |
1830 | ||
a1dfa0c6 | 1831 | /// Returns `true` if the impls are the same polarity and the trait either |
f9f354fc | 1832 | /// has no items or is annotated `#[marker]` and prevents item overrides. |
dfeec247 XL |
1833 | pub fn impls_are_allowed_to_overlap( |
1834 | self, | |
1835 | def_id1: DefId, | |
1836 | def_id2: DefId, | |
1837 | ) -> Option<ImplOverlapKind> { | |
e1599b0c XL |
1838 | // If either trait impl references an error, they're allowed to overlap, |
1839 | // as one of them essentially doesn't exist. | |
dfeec247 XL |
1840 | if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.references_error()) |
1841 | || self.impl_trait_ref(def_id2).map_or(false, |tr| tr.references_error()) | |
1842 | { | |
1843 | return Some(ImplOverlapKind::Permitted { marker: false }); | |
e1599b0c XL |
1844 | } |
1845 | ||
e74abb32 | 1846 | match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) { |
dfeec247 | 1847 | (ImplPolarity::Reservation, _) | (_, ImplPolarity::Reservation) => { |
e74abb32 | 1848 | // `#[rustc_reservation_impl]` impls don't overlap with anything |
dfeec247 XL |
1849 | debug!( |
1850 | "impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (reservations)", | |
1851 | def_id1, def_id2 | |
1852 | ); | |
1853 | return Some(ImplOverlapKind::Permitted { marker: false }); | |
e74abb32 | 1854 | } |
dfeec247 XL |
1855 | (ImplPolarity::Positive, ImplPolarity::Negative) |
1856 | | (ImplPolarity::Negative, ImplPolarity::Positive) => { | |
e74abb32 | 1857 | // `impl AutoTrait for Type` + `impl !AutoTrait for Type` |
dfeec247 XL |
1858 | debug!( |
1859 | "impls_are_allowed_to_overlap({:?}, {:?}) - None (differing polarities)", | |
1860 | def_id1, def_id2 | |
1861 | ); | |
e74abb32 XL |
1862 | return None; |
1863 | } | |
dfeec247 XL |
1864 | (ImplPolarity::Positive, ImplPolarity::Positive) |
1865 | | (ImplPolarity::Negative, ImplPolarity::Negative) => {} | |
e74abb32 XL |
1866 | }; |
1867 | ||
74b04a01 | 1868 | let is_marker_overlap = { |
0bf4aa26 XL |
1869 | let is_marker_impl = |def_id: DefId| -> bool { |
1870 | let trait_ref = self.impl_trait_ref(def_id); | |
1871 | trait_ref.map_or(false, |tr| self.trait_def(tr.def_id).is_marker) | |
1872 | }; | |
e74abb32 | 1873 | is_marker_impl(def_id1) && is_marker_impl(def_id2) |
0731742a XL |
1874 | }; |
1875 | ||
e74abb32 | 1876 | if is_marker_overlap { |
dfeec247 XL |
1877 | debug!( |
1878 | "impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (marker overlap)", | |
1879 | def_id1, def_id2 | |
1880 | ); | |
1881 | Some(ImplOverlapKind::Permitted { marker: true }) | |
0bf4aa26 | 1882 | } else { |
0731742a XL |
1883 | if let Some(self_ty1) = self.issue33140_self_ty(def_id1) { |
1884 | if let Some(self_ty2) = self.issue33140_self_ty(def_id2) { | |
1885 | if self_ty1 == self_ty2 { | |
dfeec247 XL |
1886 | debug!( |
1887 | "impls_are_allowed_to_overlap({:?}, {:?}) - issue #33140 HACK", | |
1888 | def_id1, def_id2 | |
1889 | ); | |
0731742a XL |
1890 | return Some(ImplOverlapKind::Issue33140); |
1891 | } else { | |
dfeec247 XL |
1892 | debug!( |
1893 | "impls_are_allowed_to_overlap({:?}, {:?}) - found {:?} != {:?}", | |
1894 | def_id1, def_id2, self_ty1, self_ty2 | |
1895 | ); | |
0731742a XL |
1896 | } |
1897 | } | |
1898 | } | |
1899 | ||
dfeec247 | 1900 | debug!("impls_are_allowed_to_overlap({:?}, {:?}) = None", def_id1, def_id2); |
0731742a | 1901 | None |
cc61c64b | 1902 | } |
cc61c64b XL |
1903 | } |
1904 | ||
48663c56 | 1905 | /// Returns `ty::VariantDef` if `res` refers to a struct, |
532ac7d7 | 1906 | /// or variant or their constructors, panics otherwise. |
48663c56 XL |
1907 | pub fn expect_variant_res(self, res: Res) -> &'tcx VariantDef { |
1908 | match res { | |
1909 | Res::Def(DefKind::Variant, did) => { | |
532ac7d7 | 1910 | let enum_did = self.parent(did).unwrap(); |
7cac9316 | 1911 | self.adt_def(enum_did).variant_with_id(did) |
5bcae85e | 1912 | } |
ba9703b0 | 1913 | Res::Def(DefKind::Struct | DefKind::Union, did) => self.adt_def(did).non_enum_variant(), |
48663c56 | 1914 | Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_did) => { |
532ac7d7 XL |
1915 | let variant_did = self.parent(variant_ctor_did).unwrap(); |
1916 | let enum_did = self.parent(variant_did).unwrap(); | |
1917 | self.adt_def(enum_did).variant_with_ctor_id(variant_ctor_did) | |
1918 | } | |
48663c56 | 1919 | Res::Def(DefKind::Ctor(CtorOf::Struct, ..), ctor_did) => { |
532ac7d7 XL |
1920 | let struct_did = self.parent(ctor_did).expect("struct ctor has no parent"); |
1921 | self.adt_def(struct_did).non_enum_variant() | |
c30ab7b3 | 1922 | } |
dfeec247 | 1923 | _ => bug!("expect_variant_res used with unexpected res {:?}", res), |
5bcae85e SL |
1924 | } |
1925 | } | |
1926 | ||
9fa01778 | 1927 | /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair. |
f9f354fc | 1928 | pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> { |
cc61c64b | 1929 | match instance { |
5869c6ff XL |
1930 | ty::InstanceDef::Item(def) => match self.def_kind(def.did) { |
1931 | DefKind::Const | |
1932 | | DefKind::Static | |
1933 | | DefKind::AssocConst | |
1934 | | DefKind::Ctor(..) | |
3c0e092e XL |
1935 | | DefKind::AnonConst |
1936 | | DefKind::InlineConst => self.mir_for_ctfe_opt_const_arg(def), | |
5869c6ff XL |
1937 | // If the caller wants `mir_for_ctfe` of a function they should not be using |
1938 | // `instance_mir`, so we'll assume const fn also wants the optimized version. | |
6a06907d XL |
1939 | _ => { |
1940 | assert_eq!(def.const_param_did, None); | |
1941 | self.optimized_mir(def.did) | |
1942 | } | |
5869c6ff | 1943 | }, |
dfeec247 XL |
1944 | ty::InstanceDef::VtableShim(..) |
1945 | | ty::InstanceDef::ReifyShim(..) | |
1946 | | ty::InstanceDef::Intrinsic(..) | |
1947 | | ty::InstanceDef::FnPtrShim(..) | |
1948 | | ty::InstanceDef::Virtual(..) | |
1949 | | ty::InstanceDef::ClosureOnceShim { .. } | |
1950 | | ty::InstanceDef::DropGlue(..) | |
f9f354fc | 1951 | | ty::InstanceDef::CloneShim(..) => self.mir_shims(instance), |
cc61c64b XL |
1952 | } |
1953 | } | |
1954 | ||
9fa01778 | 1955 | /// Gets the attributes of a definition. |
dc9dc135 | 1956 | pub fn get_attrs(self, did: DefId) -> Attributes<'tcx> { |
f9f354fc | 1957 | if let Some(did) = did.as_local() { |
3dfed10e | 1958 | self.hir().attrs(self.hir().local_def_id_to_hir_id(did)) |
e9174d1e | 1959 | } else { |
ba9703b0 | 1960 | self.item_attrs(did) |
e9174d1e SL |
1961 | } |
1962 | } | |
1963 | ||
9fa01778 | 1964 | /// Determines whether an item is annotated with an attribute. |
48663c56 | 1965 | pub fn has_attr(self, did: DefId, attr: Symbol) -> bool { |
3dfed10e | 1966 | self.sess.contains_name(&self.get_attrs(did), attr) |
e9174d1e SL |
1967 | } |
1968 | ||
c295e0f8 XL |
1969 | /// Determines whether an item is annotated with `doc(hidden)`. |
1970 | pub fn is_doc_hidden(self, did: DefId) -> bool { | |
1971 | self.get_attrs(did) | |
1972 | .iter() | |
1973 | .filter_map(|attr| if attr.has_name(sym::doc) { attr.meta_item_list() } else { None }) | |
1974 | .any(|items| items.iter().any(|item| item.has_name(sym::hidden))) | |
1975 | } | |
1976 | ||
a1dfa0c6 | 1977 | /// Returns `true` if this is an `auto trait`. |
abe05a73 XL |
1978 | pub fn trait_is_auto(self, trait_def_id: DefId) -> bool { |
1979 | self.trait_def(trait_def_id).has_auto_impl | |
b039eaaf SL |
1980 | } |
1981 | ||
5869c6ff XL |
1982 | /// Returns layout of a generator. Layout might be unavailable if the |
1983 | /// generator is tainted by errors. | |
1984 | pub fn generator_layout(self, def_id: DefId) -> Option<&'tcx GeneratorLayout<'tcx>> { | |
6a06907d | 1985 | self.optimized_mir(def_id).generator_layout() |
ea8adc8c XL |
1986 | } |
1987 | ||
9fa01778 XL |
1988 | /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. |
1989 | /// If it implements no trait, returns `None`. | |
a7813a04 | 1990 | pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> { |
e9174d1e SL |
1991 | self.impl_trait_ref(def_id).map(|tr| tr.def_id) |
1992 | } | |
1993 | ||
9fa01778 XL |
1994 | /// If the given defid describes a method belonging to an impl, returns the |
1995 | /// `DefId` of the impl that the method belongs to; otherwise, returns `None`. | |
a7813a04 | 1996 | pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> { |
ba9703b0 | 1997 | self.opt_associated_item(def_id).and_then(|trait_item| match trait_item.container { |
dfeec247 XL |
1998 | TraitContainer(_) => None, |
1999 | ImplContainer(def_id) => Some(def_id), | |
2000 | }) | |
e9174d1e SL |
2001 | } |
2002 | ||
54a0048b SL |
2003 | /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err` |
2004 | /// with the name of the crate containing the impl. | |
476ff2be | 2005 | pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> { |
f9f354fc | 2006 | if let Some(impl_did) = impl_did.as_local() { |
3dfed10e | 2007 | let hir_id = self.hir().local_def_id_to_hir_id(impl_did); |
dc9dc135 | 2008 | Ok(self.hir().span(hir_id)) |
54a0048b | 2009 | } else { |
ea8adc8c | 2010 | Err(self.crate_name(impl_did.krate)) |
54a0048b SL |
2011 | } |
2012 | } | |
7cac9316 | 2013 | |
9fa01778 XL |
2014 | /// Hygienically compares a use-site name (`use_name`) for a field or an associated item with |
2015 | /// its supposed definition name (`def_name`). The method also needs `DefId` of the supposed | |
2016 | /// definition's parent/scope to perform comparison. | |
8faf50e0 | 2017 | pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool { |
dc9dc135 XL |
2018 | // We could use `Ident::eq` here, but we deliberately don't. The name |
2019 | // comparison fails frequently, and we want to avoid the expensive | |
ba9703b0 | 2020 | // `normalize_to_macros_2_0()` calls required for the span comparison whenever possible. |
dfeec247 XL |
2021 | use_name.name == def_name.name |
2022 | && use_name | |
2023 | .span | |
2024 | .ctxt() | |
17df50a5 | 2025 | .hygienic_eq(def_name.span.ctxt(), self.expn_that_defined(def_parent_def_id)) |
dc9dc135 XL |
2026 | } |
2027 | ||
2028 | pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident { | |
17df50a5 | 2029 | ident.span.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)); |
dc9dc135 XL |
2030 | ident |
2031 | } | |
2032 | ||
dfeec247 XL |
2033 | pub fn adjust_ident_and_get_scope( |
2034 | self, | |
2035 | mut ident: Ident, | |
2036 | scope: DefId, | |
2037 | block: hir::HirId, | |
2038 | ) -> (Ident, DefId) { | |
136023e0 XL |
2039 | let scope = ident |
2040 | .span | |
2041 | .normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)) | |
2042 | .and_then(|actual_expansion| actual_expansion.expn_data().parent_module) | |
2043 | .unwrap_or_else(|| self.parent_module(block).to_def_id()); | |
7cac9316 XL |
2044 | (ident, scope) |
2045 | } | |
a1dfa0c6 | 2046 | |
74b04a01 XL |
2047 | pub fn is_object_safe(self, key: DefId) -> bool { |
2048 | self.object_safety_violations(key).is_empty() | |
a1dfa0c6 XL |
2049 | } |
2050 | } | |
2051 | ||
a1dfa0c6 | 2052 | /// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition. |
dc9dc135 | 2053 | pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> { |
f9f354fc | 2054 | if let Some(def_id) = def_id.as_local() { |
3dfed10e | 2055 | if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) { |
e74abb32 | 2056 | if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { |
416331ca | 2057 | return opaque_ty.impl_trait_fn; |
8faf50e0 XL |
2058 | } |
2059 | } | |
2060 | } | |
2061 | None | |
2062 | } | |
2063 | ||
5869c6ff XL |
2064 | pub fn int_ty(ity: ast::IntTy) -> IntTy { |
2065 | match ity { | |
2066 | ast::IntTy::Isize => IntTy::Isize, | |
2067 | ast::IntTy::I8 => IntTy::I8, | |
2068 | ast::IntTy::I16 => IntTy::I16, | |
2069 | ast::IntTy::I32 => IntTy::I32, | |
2070 | ast::IntTy::I64 => IntTy::I64, | |
2071 | ast::IntTy::I128 => IntTy::I128, | |
2072 | } | |
2073 | } | |
2074 | ||
2075 | pub fn uint_ty(uty: ast::UintTy) -> UintTy { | |
2076 | match uty { | |
2077 | ast::UintTy::Usize => UintTy::Usize, | |
2078 | ast::UintTy::U8 => UintTy::U8, | |
2079 | ast::UintTy::U16 => UintTy::U16, | |
2080 | ast::UintTy::U32 => UintTy::U32, | |
2081 | ast::UintTy::U64 => UintTy::U64, | |
2082 | ast::UintTy::U128 => UintTy::U128, | |
2083 | } | |
2084 | } | |
2085 | ||
2086 | pub fn float_ty(fty: ast::FloatTy) -> FloatTy { | |
2087 | match fty { | |
2088 | ast::FloatTy::F32 => FloatTy::F32, | |
2089 | ast::FloatTy::F64 => FloatTy::F64, | |
2090 | } | |
2091 | } | |
2092 | ||
2093 | pub fn ast_int_ty(ity: IntTy) -> ast::IntTy { | |
2094 | match ity { | |
2095 | IntTy::Isize => ast::IntTy::Isize, | |
2096 | IntTy::I8 => ast::IntTy::I8, | |
2097 | IntTy::I16 => ast::IntTy::I16, | |
2098 | IntTy::I32 => ast::IntTy::I32, | |
2099 | IntTy::I64 => ast::IntTy::I64, | |
2100 | IntTy::I128 => ast::IntTy::I128, | |
2101 | } | |
2102 | } | |
2103 | ||
2104 | pub fn ast_uint_ty(uty: UintTy) -> ast::UintTy { | |
2105 | match uty { | |
2106 | UintTy::Usize => ast::UintTy::Usize, | |
2107 | UintTy::U8 => ast::UintTy::U8, | |
2108 | UintTy::U16 => ast::UintTy::U16, | |
2109 | UintTy::U32 => ast::UintTy::U32, | |
2110 | UintTy::U64 => ast::UintTy::U64, | |
2111 | UintTy::U128 => ast::UintTy::U128, | |
2112 | } | |
2113 | } | |
2114 | ||
f035d41b | 2115 | pub fn provide(providers: &mut ty::query::Providers) { |
94222f64 | 2116 | closure::provide(providers); |
ea8adc8c | 2117 | context::provide(providers); |
abe05a73 | 2118 | erase_regions::provide(providers); |
ff7c6d11 | 2119 | layout::provide(providers); |
3dfed10e | 2120 | util::provide(providers); |
1b1a35ee | 2121 | print::provide(providers); |
ba9703b0 | 2122 | super::util::bug::provide(providers); |
136023e0 | 2123 | super::middle::provide(providers); |
ba9703b0 XL |
2124 | *providers = ty::query::Providers { |
2125 | trait_impls_of: trait_def::trait_impls_of_provider, | |
5869c6ff | 2126 | type_uninhabited_from: inhabitedness::type_uninhabited_from, |
cdc7bbd5 | 2127 | const_param_default: consts::const_param_default, |
dc3f5686 | 2128 | vtable_allocation: vtable::vtable_allocation_provider, |
ba9703b0 XL |
2129 | ..*providers |
2130 | }; | |
cc61c64b XL |
2131 | } |
2132 | ||
cc61c64b XL |
2133 | /// A map for the local crate mapping each type to a vector of its |
2134 | /// inherent impls. This is not meant to be used outside of coherence; | |
2135 | /// rather, you should request the vector for a specific type via | |
7cac9316 XL |
2136 | /// `tcx.inherent_impls(def_id)` so as to minimize your dependencies |
2137 | /// (constructing this map requires touching the entire crate). | |
532ac7d7 | 2138 | #[derive(Clone, Debug, Default, HashStable)] |
cc61c64b | 2139 | pub struct CrateInherentImpls { |
17df50a5 | 2140 | pub inherent_impls: LocalDefIdMap<Vec<DefId>>, |
cc61c64b XL |
2141 | } |
2142 | ||
3dfed10e XL |
2143 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)] |
2144 | pub struct SymbolName<'tcx> { | |
2145 | /// `&str` gives a consistent ordering, which ensures reproducible builds. | |
2146 | pub name: &'tcx str, | |
7cac9316 XL |
2147 | } |
2148 | ||
3dfed10e XL |
2149 | impl<'tcx> SymbolName<'tcx> { |
2150 | pub fn new(tcx: TyCtxt<'tcx>, name: &str) -> SymbolName<'tcx> { | |
2151 | SymbolName { | |
2152 | name: unsafe { str::from_utf8_unchecked(tcx.arena.alloc_slice(name.as_bytes())) }, | |
2153 | } | |
e74abb32 XL |
2154 | } |
2155 | } | |
2156 | ||
3dfed10e | 2157 | impl<'tcx> fmt::Display for SymbolName<'tcx> { |
0bf4aa26 | 2158 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
7cac9316 XL |
2159 | fmt::Display::fmt(&self.name, fmt) |
2160 | } | |
2161 | } | |
0531ce1d | 2162 | |
3dfed10e | 2163 | impl<'tcx> fmt::Debug for SymbolName<'tcx> { |
0bf4aa26 | 2164 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
0531ce1d XL |
2165 | fmt::Display::fmt(&self.name, fmt) |
2166 | } | |
2167 | } | |
c295e0f8 XL |
2168 | |
2169 | #[derive(Debug, Default, Copy, Clone)] | |
2170 | pub struct FoundRelationships { | |
2171 | /// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo` | |
2172 | /// obligation, where: | |
2173 | /// | |
2174 | /// * `Foo` is not `Sized` | |
2175 | /// * `(): Foo` may be satisfied | |
2176 | pub self_in_trait: bool, | |
2177 | /// This is true if we identified that this Ty (`?T`) is found in a `<_ as | |
2178 | /// _>::AssocType = ?T` | |
2179 | pub output: bool, | |
2180 | } |