]>
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 | //! | |
5e7ed085 | 8 | //! For more information, see ["The `ty` module: representing types"] in the rustc-dev-guide. |
fc512014 XL |
9 | //! |
10 | //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html | |
11 | ||
487cf647 FG |
12 | #![allow(rustc::usage_of_ty_tykind)] |
13 | ||
064997fb | 14 | pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; |
9ffffee4 | 15 | pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; |
dc9dc135 | 16 | pub use self::AssocItemContainer::*; |
e9174d1e | 17 | pub use self::BorrowKind::*; |
e9174d1e | 18 | pub use self::IntVarValue::*; |
dfeec247 | 19 | pub use self::Variance::*; |
f2b60f7d | 20 | use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; |
5099ac24 | 21 | use crate::metadata::ModChild; |
2b03887a | 22 | use crate::middle::privacy::EffectiveVisibilities; |
6a06907d | 23 | use crate::mir::{Body, GeneratorLayout}; |
9fa01778 XL |
24 | use crate::traits::{self, Reveal}; |
25 | use crate::ty; | |
5e7ed085 | 26 | use crate::ty::fast_reject::SimplifiedType; |
6a06907d | 27 | use crate::ty::util::Discr; |
04454e1e FG |
28 | pub use adt::*; |
29 | pub use assoc::*; | |
30 | pub use generics::*; | |
3dfed10e | 31 | use rustc_ast as ast; |
923072b8 | 32 | use rustc_ast::node_id::NodeMap; |
74b04a01 | 33 | use rustc_attr as attr; |
923072b8 | 34 | use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; |
487cf647 | 35 | use rustc_data_structures::intern::Interned; |
dfeec247 | 36 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; |
3dfed10e | 37 | use rustc_data_structures::tagged_ptr::CopyTaggedPtr; |
9ffffee4 | 38 | use rustc_errors::ErrorGuaranteed; |
dfeec247 | 39 | use rustc_hir as hir; |
9ffffee4 | 40 | use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; |
9c376795 | 41 | use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; |
94222f64 | 42 | use rustc_hir::Node; |
923072b8 | 43 | use rustc_index::vec::IndexVec; |
dfeec247 | 44 | use rustc_macros::HashStable; |
c295e0f8 | 45 | use rustc_query_system::ich::StableHashingContext; |
f2b60f7d | 46 | use rustc_serialize::{Decodable, Encodable}; |
923072b8 | 47 | use rustc_span::hygiene::MacroKind; |
04454e1e | 48 | use rustc_span::symbol::{kw, sym, Ident, Symbol}; |
9ffffee4 | 49 | use rustc_span::{ExpnId, ExpnKind, Span}; |
487cf647 FG |
50 | use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx}; |
51 | pub use rustc_target::abi::{ReprFlags, ReprOptions}; | |
52 | use rustc_type_ir::WithCachedTypeInfo; | |
923072b8 | 53 | pub use subst::*; |
04454e1e | 54 | pub use vtable::*; |
74b04a01 | 55 | |
5e7ed085 | 56 | use std::fmt::Debug; |
064997fb | 57 | use std::hash::{Hash, Hasher}; |
f2b60f7d FG |
58 | use std::marker::PhantomData; |
59 | use std::mem; | |
60 | use std::num::NonZeroUsize; | |
6a06907d | 61 | use std::ops::ControlFlow; |
5099ac24 | 62 | use std::{fmt, str}; |
54a0048b | 63 | |
60c5eb7d | 64 | pub use crate::ty::diagnostics::*; |
9c376795 | 65 | pub use rustc_type_ir::AliasKind::*; |
f2b60f7d | 66 | pub use rustc_type_ir::DynKind::*; |
5869c6ff | 67 | pub use rustc_type_ir::InferTy::*; |
923072b8 FG |
68 | pub use rustc_type_ir::RegionKind::*; |
69 | pub use rustc_type_ir::TyKind::*; | |
5869c6ff | 70 | pub use rustc_type_ir::*; |
e9174d1e | 71 | |
3b2f2976 XL |
72 | pub use self::binding::BindingMode; |
73 | pub use self::binding::BindingMode::*; | |
94222f64 XL |
74 | pub use self::closure::{ |
75 | is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo, | |
9ffffee4 | 76 | CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList, |
5099ac24 FG |
77 | RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath, |
78 | CAPTURE_STRUCT_LOCAL, | |
79 | }; | |
80 | pub use self::consts::{ | |
9c376795 | 81 | Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, |
94222f64 | 82 | }; |
0731742a | 83 | pub use self::context::{ |
9c376795 FG |
84 | tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, OnDiskCache, TyCtxt, |
85 | TyCtxtFeed, | |
0731742a | 86 | }; |
9c376795 | 87 | pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams}; |
f9f354fc | 88 | pub use self::list::List; |
923072b8 FG |
89 | pub use self::parameterized::ParameterizedOverTcx; |
90 | pub use self::rvalue_scopes::RvalueScopes; | |
6a06907d | 91 | pub use self::sty::BoundRegionKind::*; |
6a06907d | 92 | pub use self::sty::{ |
9c376795 | 93 | AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, |
923072b8 | 94 | BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, |
2b03887a FG |
95 | EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, |
96 | FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, | |
487cf647 FG |
97 | InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate, |
98 | PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, | |
9c376795 | 99 | Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo, |
6a06907d | 100 | }; |
7cac9316 | 101 | pub use self::trait_def::TraitDef; |
9c376795 FG |
102 | pub use self::typeck_results::{ |
103 | CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, | |
104 | GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType, | |
105 | UserTypeAnnotationIndex, | |
106 | }; | |
9cc50fc6 | 107 | |
3dfed10e | 108 | pub mod _match; |
064997fb | 109 | pub mod abstract_const; |
e9174d1e | 110 | pub mod adjustment; |
3b2f2976 | 111 | pub mod binding; |
e9174d1e | 112 | pub mod cast; |
abe05a73 | 113 | pub mod codec; |
dfeec247 | 114 | pub mod error; |
e9174d1e | 115 | pub mod fast_reject; |
48663c56 | 116 | pub mod flags; |
e9174d1e | 117 | pub mod fold; |
32a655c1 | 118 | pub mod inhabitedness; |
54a0048b | 119 | pub mod layout; |
dfeec247 | 120 | pub mod normalize_erasing_regions; |
532ac7d7 | 121 | pub mod print; |
94b46f34 | 122 | pub mod query; |
e9174d1e | 123 | pub mod relate; |
54a0048b | 124 | pub mod subst; |
9cc50fc6 | 125 | pub mod trait_def; |
e9174d1e | 126 | pub mod util; |
064997fb | 127 | pub mod visit; |
136023e0 | 128 | pub mod vtable; |
dfeec247 | 129 | pub mod walk; |
e9174d1e | 130 | |
6a06907d XL |
131 | mod adt; |
132 | mod assoc; | |
133 | mod closure; | |
f035d41b | 134 | mod consts; |
e9174d1e | 135 | mod context; |
dfeec247 | 136 | mod diagnostics; |
6a06907d XL |
137 | mod erase_regions; |
138 | mod generics; | |
c295e0f8 | 139 | mod impls_ty; |
cc61c64b | 140 | mod instance; |
f9f354fc | 141 | mod list; |
2b03887a | 142 | mod opaque_types; |
923072b8 FG |
143 | mod parameterized; |
144 | mod rvalue_scopes; | |
e9174d1e SL |
145 | mod structural_impls; |
146 | mod sty; | |
9c376795 | 147 | mod typeck_results; |
e9174d1e | 148 | |
e9174d1e SL |
149 | // Data types |
150 | ||
5099ac24 FG |
151 | pub type RegisteredTools = FxHashSet<Ident>; |
152 | ||
e74abb32 | 153 | pub struct ResolverOutputs { |
2b03887a FG |
154 | pub global_ctxt: ResolverGlobalCtxt, |
155 | pub ast_lowering: ResolverAstLowering, | |
156 | } | |
157 | ||
158 | #[derive(Debug)] | |
159 | pub struct ResolverGlobalCtxt { | |
29967ef6 | 160 | pub visibilities: FxHashMap<LocalDefId, Visibility>, |
04454e1e FG |
161 | /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error. |
162 | pub has_pub_restricted: bool, | |
923072b8 FG |
163 | /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. |
164 | pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>, | |
2b03887a | 165 | pub effective_visibilities: EffectiveVisibilities, |
f9f354fc | 166 | pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>, |
923072b8 | 167 | pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>, |
5099ac24 | 168 | pub reexport_map: FxHashMap<LocalDefId, Vec<ModChild>>, |
f9f354fc | 169 | pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>, |
cdc7bbd5 | 170 | pub main_def: Option<MainDefinition>, |
5099ac24 | 171 | pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>, |
94222f64 XL |
172 | /// A list of proc macro LocalDefIds, written out in the order in which |
173 | /// they are declared in the static array generated by proc_macro_harness. | |
174 | pub proc_macros: Vec<LocalDefId>, | |
c295e0f8 XL |
175 | /// Mapping from ident span to path span for paths that don't exist as written, but that |
176 | /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. | |
177 | pub confused_type_with_std_module: FxHashMap<Span, Span>, | |
5099ac24 | 178 | pub registered_tools: RegisteredTools, |
9ffffee4 FG |
179 | pub doc_link_resolutions: FxHashMap<LocalDefId, DocLinkResMap>, |
180 | pub doc_link_traits_in_scope: FxHashMap<LocalDefId, Vec<DefId>>, | |
181 | pub all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>, | |
cdc7bbd5 XL |
182 | } |
183 | ||
923072b8 FG |
184 | /// Resolutions that should only be used for lowering. |
185 | /// This struct is meant to be consumed by lowering. | |
186 | #[derive(Debug)] | |
187 | pub struct ResolverAstLowering { | |
188 | pub legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>, | |
189 | ||
190 | /// Resolutions for nodes that have a single resolution. | |
191 | pub partial_res_map: NodeMap<hir::def::PartialRes>, | |
192 | /// Resolutions for import nodes, which have multiple resolutions in different namespaces. | |
193 | pub import_res_map: NodeMap<hir::def::PerNS<Option<Res<ast::NodeId>>>>, | |
194 | /// Resolutions for labels (node IDs of their corresponding blocks or loops). | |
195 | pub label_res_map: NodeMap<ast::NodeId>, | |
196 | /// Resolutions for lifetimes. | |
197 | pub lifetimes_res_map: NodeMap<LifetimeRes>, | |
198 | /// Lifetime parameters that lowering will have to introduce. | |
199 | pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, LifetimeRes)>>, | |
200 | ||
201 | pub next_node_id: ast::NodeId, | |
202 | ||
203 | pub node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>, | |
204 | pub def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>, | |
205 | ||
206 | pub trait_map: NodeMap<Vec<hir::TraitCandidate>>, | |
207 | /// A small map keeping true kinds of built-in macros that appear to be fn-like on | |
208 | /// the surface (`macro` items in libcore), but are actually attributes or derives. | |
209 | pub builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>, | |
487cf647 FG |
210 | /// List functions and methods for which lifetime elision was successful. |
211 | pub lifetime_elision_allowed: FxHashSet<ast::NodeId>, | |
923072b8 FG |
212 | } |
213 | ||
136023e0 | 214 | #[derive(Clone, Copy, Debug)] |
cdc7bbd5 XL |
215 | pub struct MainDefinition { |
216 | pub res: Res<ast::NodeId>, | |
217 | pub is_import: bool, | |
218 | pub span: Span, | |
219 | } | |
220 | ||
221 | impl MainDefinition { | |
222 | pub fn opt_fn_def_id(self) -> Option<DefId> { | |
223 | if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None } | |
224 | } | |
e9174d1e SL |
225 | } |
226 | ||
54a0048b SL |
227 | /// The "header" of an impl is everything outside the body: a Self type, a trait |
228 | /// ref (in the case of a trait impl), and a set of predicates (from the | |
9fa01778 | 229 | /// bounds / where-clauses). |
064997fb | 230 | #[derive(Clone, Debug, TypeFoldable, TypeVisitable)] |
54a0048b SL |
231 | pub struct ImplHeader<'tcx> { |
232 | pub impl_def_id: DefId, | |
233 | pub self_ty: Ty<'tcx>, | |
234 | pub trait_ref: Option<TraitRef<'tcx>>, | |
235 | pub predicates: Vec<Predicate<'tcx>>, | |
236 | } | |
237 | ||
9c376795 | 238 | #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] |
5e7ed085 FG |
239 | pub enum ImplSubject<'tcx> { |
240 | Trait(TraitRef<'tcx>), | |
241 | Inherent(Ty<'tcx>), | |
242 | } | |
243 | ||
064997fb FG |
244 | #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] |
245 | #[derive(TypeFoldable, TypeVisitable)] | |
e74abb32 XL |
246 | pub enum ImplPolarity { |
247 | /// `impl Trait for Type` | |
248 | Positive, | |
249 | /// `impl !Trait for Type` | |
250 | Negative, | |
251 | /// `#[rustc_reservation_impl] impl Trait for Type` | |
252 | /// | |
253 | /// This is a "stability hack", not a real Rust feature. | |
254 | /// See #64631 for details. | |
255 | Reservation, | |
256 | } | |
257 | ||
3c0e092e XL |
258 | impl ImplPolarity { |
259 | /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`. | |
260 | pub fn flip(&self) -> Option<ImplPolarity> { | |
261 | match self { | |
262 | ImplPolarity::Positive => Some(ImplPolarity::Negative), | |
263 | ImplPolarity::Negative => Some(ImplPolarity::Positive), | |
264 | ImplPolarity::Reservation => None, | |
265 | } | |
266 | } | |
267 | } | |
268 | ||
269 | impl fmt::Display for ImplPolarity { | |
270 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
271 | match self { | |
272 | Self::Positive => f.write_str("positive"), | |
273 | Self::Negative => f.write_str("negative"), | |
274 | Self::Reservation => f.write_str("reservation"), | |
275 | } | |
276 | } | |
277 | } | |
278 | ||
923072b8 | 279 | #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Encodable, Decodable, HashStable)] |
f2b60f7d | 280 | pub enum Visibility<Id = LocalDefId> { |
54a0048b SL |
281 | /// Visible everywhere (including in other crates). |
282 | Public, | |
283 | /// Visible only in the given crate-local module. | |
f2b60f7d | 284 | Restricted(Id), |
54a0048b SL |
285 | } |
286 | ||
94222f64 XL |
287 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] |
288 | pub enum BoundConstness { | |
289 | /// `T: Trait` | |
290 | NotConst, | |
291 | /// `T: ~const Trait` | |
292 | /// | |
293 | /// Requires resolving to const only when we are in a const context. | |
294 | ConstIfConst, | |
295 | } | |
296 | ||
a2a8927a XL |
297 | impl BoundConstness { |
298 | /// Reduce `self` and `constness` to two possible combined states instead of four. | |
299 | pub fn and(&mut self, constness: hir::Constness) -> hir::Constness { | |
300 | match (constness, self) { | |
301 | (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const, | |
302 | (_, this) => { | |
303 | *this = BoundConstness::NotConst; | |
304 | hir::Constness::NotConst | |
305 | } | |
306 | } | |
307 | } | |
308 | } | |
309 | ||
94222f64 XL |
310 | impl fmt::Display for BoundConstness { |
311 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
312 | match self { | |
313 | Self::NotConst => f.write_str("normal"), | |
314 | Self::ConstIfConst => f.write_str("`~const`"), | |
315 | } | |
316 | } | |
317 | } | |
318 | ||
064997fb FG |
319 | #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)] |
320 | #[derive(TypeFoldable, TypeVisitable)] | |
136023e0 XL |
321 | pub struct ClosureSizeProfileData<'tcx> { |
322 | /// Tuple containing the types of closure captures before the feature `capture_disjoint_fields` | |
323 | pub before_feature_tys: Ty<'tcx>, | |
324 | /// Tuple containing the types of closure captures after the feature `capture_disjoint_fields` | |
325 | pub after_feature_tys: Ty<'tcx>, | |
326 | } | |
327 | ||
32a655c1 | 328 | pub trait DefIdTree: Copy { |
04454e1e FG |
329 | fn opt_parent(self, id: DefId) -> Option<DefId>; |
330 | ||
331 | #[inline] | |
332 | #[track_caller] | |
333 | fn parent(self, id: DefId) -> DefId { | |
334 | match self.opt_parent(id) { | |
335 | Some(id) => id, | |
336 | // not `unwrap_or_else` to avoid breaking caller tracking | |
337 | None => bug!("{id:?} doesn't have a parent"), | |
338 | } | |
339 | } | |
340 | ||
341 | #[inline] | |
342 | #[track_caller] | |
343 | fn opt_local_parent(self, id: LocalDefId) -> Option<LocalDefId> { | |
344 | self.opt_parent(id.to_def_id()).map(DefId::expect_local) | |
345 | } | |
a7813a04 | 346 | |
5e7ed085 | 347 | #[inline] |
04454e1e FG |
348 | #[track_caller] |
349 | fn local_parent(self, id: LocalDefId) -> LocalDefId { | |
350 | self.parent(id.to_def_id()).expect_local() | |
5e7ed085 FG |
351 | } |
352 | ||
32a655c1 SL |
353 | fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool { |
354 | if descendant.krate != ancestor.krate { | |
355 | return false; | |
356 | } | |
357 | ||
358 | while descendant != ancestor { | |
04454e1e | 359 | match self.opt_parent(descendant) { |
32a655c1 SL |
360 | Some(parent) => descendant = parent, |
361 | None => return false, | |
a7813a04 | 362 | } |
a7813a04 XL |
363 | } |
364 | true | |
365 | } | |
366 | } | |
367 | ||
dc9dc135 | 368 | impl<'tcx> DefIdTree for TyCtxt<'tcx> { |
04454e1e FG |
369 | #[inline] |
370 | fn opt_parent(self, id: DefId) -> Option<DefId> { | |
74b04a01 | 371 | self.def_key(id).parent.map(|index| DefId { index, ..id }) |
32a655c1 SL |
372 | } |
373 | } | |
374 | ||
f2b60f7d FG |
375 | impl<Id> Visibility<Id> { |
376 | pub fn is_public(self) -> bool { | |
377 | matches!(self, Visibility::Public) | |
378 | } | |
379 | ||
380 | pub fn map_id<OutId>(self, f: impl FnOnce(Id) -> OutId) -> Visibility<OutId> { | |
381 | match self { | |
382 | Visibility::Public => Visibility::Public, | |
383 | Visibility::Restricted(id) => Visibility::Restricted(f(id)), | |
384 | } | |
385 | } | |
386 | } | |
54a0048b | 387 | |
f2b60f7d FG |
388 | impl<Id: Into<DefId>> Visibility<Id> { |
389 | pub fn to_def_id(self) -> Visibility<DefId> { | |
390 | self.map_id(Into::into) | |
391 | } | |
392 | ||
393 | /// Returns `true` if an item with this visibility is accessible from the given module. | |
394 | pub fn is_accessible_from(self, module: impl Into<DefId>, tree: impl DefIdTree) -> bool { | |
395 | match self { | |
396 | // Public items are visible everywhere. | |
397 | Visibility::Public => true, | |
398 | Visibility::Restricted(id) => tree.is_descendant_of(module.into(), id.into()), | |
399 | } | |
54a0048b SL |
400 | } |
401 | ||
a1dfa0c6 | 402 | /// Returns `true` if this visibility is at least as accessible as the given visibility |
f2b60f7d FG |
403 | pub fn is_at_least(self, vis: Visibility<impl Into<DefId>>, tree: impl DefIdTree) -> bool { |
404 | match vis { | |
405 | Visibility::Public => self.is_public(), | |
406 | Visibility::Restricted(id) => self.is_accessible_from(id, tree), | |
407 | } | |
408 | } | |
409 | } | |
54a0048b | 410 | |
f2b60f7d FG |
411 | impl Visibility<DefId> { |
412 | pub fn expect_local(self) -> Visibility { | |
413 | self.map_id(|id| id.expect_local()) | |
54a0048b | 414 | } |
ff7c6d11 | 415 | |
487cf647 | 416 | /// Returns `true` if this item is visible anywhere in the local crate. |
ff7c6d11 XL |
417 | pub fn is_visible_locally(self) -> bool { |
418 | match self { | |
419 | Visibility::Public => true, | |
420 | Visibility::Restricted(def_id) => def_id.is_local(), | |
ff7c6d11 XL |
421 | } |
422 | } | |
54a0048b SL |
423 | } |
424 | ||
7cac9316 XL |
425 | /// The crate variances map is computed during typeck and contains the |
426 | /// variance of every item in the local crate. You should not use it | |
427 | /// directly, because to do so will make your pass dependent on the | |
428 | /// HIR of every item in the local crate. Instead, use | |
429 | /// `tcx.variances_of()` to get the variance for a *particular* | |
430 | /// item. | |
5869c6ff | 431 | #[derive(HashStable, Debug)] |
48663c56 | 432 | pub struct CrateVariancesMap<'tcx> { |
7cac9316 | 433 | /// For each item with generics, maps to a vector of the variance |
9fa01778 | 434 | /// of its generics. If an item has no generics, it will have no |
7cac9316 | 435 | /// entry. |
9c376795 | 436 | pub variances: DefIdMap<&'tcx [ty::Variance]>, |
7cac9316 XL |
437 | } |
438 | ||
e9174d1e SL |
439 | // Contains information needed to resolve types and (in the future) look up |
440 | // the types of AST nodes. | |
441 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
442 | pub struct CReaderCacheKey { | |
17df50a5 | 443 | pub cnum: Option<CrateNum>, |
e9174d1e | 444 | pub pos: usize, |
e9174d1e SL |
445 | } |
446 | ||
487cf647 | 447 | /// Use this rather than `TyKind`, whenever possible. |
04454e1e | 448 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] |
5099ac24 | 449 | #[rustc_diagnostic_item = "Ty"] |
5e7ed085 | 450 | #[rustc_pass_by_value] |
487cf647 | 451 | pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>); |
5099ac24 | 452 | |
94b46f34 | 453 | impl ty::EarlyBoundRegion { |
b7449926 XL |
454 | /// Does this early bound region have a name? Early bound regions normally |
455 | /// always have names except when using anonymous lifetimes (`'_`). | |
456 | pub fn has_name(&self) -> bool { | |
487cf647 | 457 | self.name != kw::UnderscoreLifetime && self.name != kw::Empty |
b7449926 | 458 | } |
94b46f34 | 459 | } |
ea8adc8c | 460 | |
487cf647 FG |
461 | /// Use this rather than `PredicateKind`, whenever possible. |
462 | #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] | |
5e7ed085 | 463 | #[rustc_pass_by_value] |
487cf647 FG |
464 | pub struct Predicate<'tcx>( |
465 | Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>, | |
466 | ); | |
f9f354fc XL |
467 | |
468 | impl<'tcx> Predicate<'tcx> { | |
cdc7bbd5 | 469 | /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. |
6a06907d | 470 | #[inline] |
cdc7bbd5 | 471 | pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { |
487cf647 | 472 | self.0.internee |
5099ac24 FG |
473 | } |
474 | ||
475 | #[inline(always)] | |
476 | pub fn flags(self) -> TypeFlags { | |
477 | self.0.flags | |
478 | } | |
479 | ||
480 | #[inline(always)] | |
481 | pub fn outer_exclusive_binder(self) -> DebruijnIndex { | |
482 | self.0.outer_exclusive_binder | |
3dfed10e | 483 | } |
3c0e092e XL |
484 | |
485 | /// Flips the polarity of a Predicate. | |
486 | /// | |
487 | /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. | |
5099ac24 | 488 | pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option<Predicate<'tcx>> { |
3c0e092e | 489 | let kind = self |
5099ac24 | 490 | .kind() |
3c0e092e | 491 | .map_bound(|kind| match kind { |
487cf647 FG |
492 | PredicateKind::Clause(Clause::Trait(TraitPredicate { |
493 | trait_ref, | |
494 | constness, | |
495 | polarity, | |
496 | })) => Some(PredicateKind::Clause(Clause::Trait(TraitPredicate { | |
497 | trait_ref, | |
498 | constness, | |
499 | polarity: polarity.flip()?, | |
500 | }))), | |
3c0e092e XL |
501 | |
502 | _ => None, | |
503 | }) | |
504 | .transpose()?; | |
505 | ||
506 | Some(tcx.mk_predicate(kind)) | |
507 | } | |
064997fb FG |
508 | |
509 | pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self { | |
487cf647 | 510 | if let PredicateKind::Clause(Clause::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder() |
064997fb FG |
511 | && constness != BoundConstness::NotConst |
512 | { | |
487cf647 | 513 | self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(Clause::Trait(TraitPredicate { |
064997fb FG |
514 | trait_ref, |
515 | constness: BoundConstness::NotConst, | |
516 | polarity, | |
487cf647 | 517 | })))); |
064997fb FG |
518 | } |
519 | self | |
520 | } | |
f2b60f7d | 521 | |
9c376795 FG |
522 | #[instrument(level = "debug", skip(tcx), ret)] |
523 | pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool { | |
524 | match self.kind().skip_binder() { | |
525 | ty::PredicateKind::Clause(ty::Clause::Trait(data)) => { | |
526 | tcx.trait_is_coinductive(data.def_id()) | |
527 | } | |
528 | ty::PredicateKind::WellFormed(_) => true, | |
529 | _ => false, | |
530 | } | |
531 | } | |
532 | ||
f2b60f7d FG |
533 | /// Whether this projection can be soundly normalized. |
534 | /// | |
535 | /// Wf predicates must not be normalized, as normalization | |
536 | /// can remove required bounds which would cause us to | |
537 | /// unsoundly accept some programs. See #91068. | |
538 | #[inline] | |
539 | pub fn allow_normalization(self) -> bool { | |
540 | match self.kind().skip_binder() { | |
541 | PredicateKind::WellFormed(_) => false, | |
487cf647 FG |
542 | PredicateKind::Clause(Clause::Trait(_)) |
543 | | PredicateKind::Clause(Clause::RegionOutlives(_)) | |
544 | | PredicateKind::Clause(Clause::TypeOutlives(_)) | |
545 | | PredicateKind::Clause(Clause::Projection(_)) | |
9ffffee4 FG |
546 | | PredicateKind::Clause(Clause::ConstArgHasType(..)) |
547 | | PredicateKind::AliasEq(..) | |
f2b60f7d FG |
548 | | PredicateKind::ObjectSafe(_) |
549 | | PredicateKind::ClosureKind(_, _, _) | |
550 | | PredicateKind::Subtype(_) | |
551 | | PredicateKind::Coerce(_) | |
552 | | PredicateKind::ConstEvaluatable(_) | |
553 | | PredicateKind::ConstEquate(_, _) | |
487cf647 | 554 | | PredicateKind::Ambiguous |
f2b60f7d FG |
555 | | PredicateKind::TypeWellFormedFromEnv(_) => true, |
556 | } | |
557 | } | |
f035d41b XL |
558 | } |
559 | ||
064997fb FG |
560 | impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { |
561 | fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { | |
562 | rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) | |
563 | } | |
564 | } | |
565 | ||
3dfed10e | 566 | #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] |
f2b60f7d | 567 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
487cf647 FG |
568 | /// A clause is something that can appear in where bounds or be inferred |
569 | /// by implied bounds. | |
570 | pub enum Clause<'tcx> { | |
dc9dc135 | 571 | /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be |
e9174d1e | 572 | /// the `Self` type of the trait reference and `A`, `B`, and `C` |
9e0c209e | 573 | /// would be the type parameters. |
94222f64 | 574 | Trait(TraitPredicate<'tcx>), |
e9174d1e | 575 | |
dc9dc135 | 576 | /// `where 'a: 'b` |
3dfed10e | 577 | RegionOutlives(RegionOutlivesPredicate<'tcx>), |
e9174d1e | 578 | |
dc9dc135 | 579 | /// `where T: 'a` |
3dfed10e | 580 | TypeOutlives(TypeOutlivesPredicate<'tcx>), |
e9174d1e | 581 | |
dc9dc135 | 582 | /// `where <T as TraitRef>::Name == X`, approximately. |
a1dfa0c6 | 583 | /// See the `ProjectionPredicate` struct for details. |
3dfed10e | 584 | Projection(ProjectionPredicate<'tcx>), |
9ffffee4 FG |
585 | |
586 | /// Ensures that a const generic argument to a parameter `const N: u8` | |
587 | /// is of type `u8`. | |
588 | ConstArgHasType(Const<'tcx>, Ty<'tcx>), | |
487cf647 FG |
589 | } |
590 | ||
591 | #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] | |
592 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] | |
593 | pub enum PredicateKind<'tcx> { | |
594 | /// Prove a clause | |
595 | Clause(Clause<'tcx>), | |
e9174d1e | 596 | |
dc9dc135 | 597 | /// No syntax: `T` well-formed. |
f035d41b | 598 | WellFormed(GenericArg<'tcx>), |
e9174d1e | 599 | |
dc9dc135 | 600 | /// Trait must be object-safe. |
e9174d1e | 601 | ObjectSafe(DefId), |
a7813a04 | 602 | |
a1dfa0c6 XL |
603 | /// No direct syntax. May be thought of as `where T: FnFoo<...>` |
604 | /// for some substitutions `...` and `T` being a closure type. | |
9e0c209e | 605 | /// Satisfied (or refuted) once we know the closure's kind. |
e74abb32 | 606 | ClosureKind(DefId, SubstsRef<'tcx>, ClosureKind), |
cc61c64b XL |
607 | |
608 | /// `T1 <: T2` | |
94222f64 XL |
609 | /// |
610 | /// This obligation is created most often when we have two | |
611 | /// unresolved type variables and hence don't have enough | |
612 | /// information to process the subtyping obligation yet. | |
3dfed10e | 613 | Subtype(SubtypePredicate<'tcx>), |
ea8adc8c | 614 | |
94222f64 XL |
615 | /// `T1` coerced to `T2` |
616 | /// | |
617 | /// Like a subtyping obligation, this is created most often | |
618 | /// when we have two unresolved type variables and hence | |
619 | /// don't have enough information to process the coercion | |
620 | /// obligation yet. At the moment, we actually process coercions | |
621 | /// very much like subtyping and don't handle the full coercion | |
622 | /// logic. | |
623 | Coerce(CoercePredicate<'tcx>), | |
624 | ||
ea8adc8c | 625 | /// Constant initializer must evaluate successfully. |
2b03887a | 626 | ConstEvaluatable(ty::Const<'tcx>), |
f9f354fc XL |
627 | |
628 | /// Constants must be equal. The first component is the const that is expected. | |
5099ac24 | 629 | ConstEquate(Const<'tcx>, Const<'tcx>), |
1b1a35ee XL |
630 | |
631 | /// Represents a type found in the environment that we can use for implied bounds. | |
632 | /// | |
633 | /// Only used for Chalk. | |
634 | TypeWellFormedFromEnv(Ty<'tcx>), | |
487cf647 FG |
635 | |
636 | /// A marker predicate that is always ambiguous. | |
637 | /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous. | |
638 | Ambiguous, | |
9ffffee4 FG |
639 | |
640 | /// Separate from `Clause::Projection` which is used for normalization in new solver. | |
641 | /// This predicate requires two terms to be equal to eachother. | |
642 | /// | |
643 | /// Only used for new solver | |
644 | AliasEq(Term<'tcx>, Term<'tcx>), | |
e9174d1e SL |
645 | } |
646 | ||
83c7162d XL |
647 | /// The crate outlives map is computed during typeck and contains the |
648 | /// outlives of every item in the local crate. You should not use it | |
649 | /// directly, because to do so will make your pass dependent on the | |
650 | /// HIR of every item in the local crate. Instead, use | |
651 | /// `tcx.inferred_outlives_of()` to get the outlives for a *particular* | |
652 | /// item. | |
5869c6ff | 653 | #[derive(HashStable, Debug)] |
83c7162d XL |
654 | pub struct CratePredicatesMap<'tcx> { |
655 | /// For each struct with outlive bounds, maps to a vector of the | |
656 | /// predicate of its outlive bounds. If an item has no outlives | |
657 | /// bounds, it will have no entry. | |
487cf647 | 658 | pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>, |
83c7162d XL |
659 | } |
660 | ||
dc9dc135 | 661 | impl<'tcx> Predicate<'tcx> { |
e9174d1e SL |
662 | /// Performs a substitution suitable for going from a |
663 | /// poly-trait-ref to supertraits that must hold if that | |
664 | /// poly-trait-ref holds. This is slightly different from a normal | |
9fa01778 | 665 | /// substitution in terms of what happens with bound regions. See |
e9174d1e | 666 | /// lengthy comment below for details. |
dc9dc135 | 667 | pub fn subst_supertrait( |
f9f354fc | 668 | self, |
dc9dc135 XL |
669 | tcx: TyCtxt<'tcx>, |
670 | trait_ref: &ty::PolyTraitRef<'tcx>, | |
3dfed10e | 671 | ) -> Predicate<'tcx> { |
e9174d1e SL |
672 | // The interaction between HRTB and supertraits is not entirely |
673 | // obvious. Let me walk you (and myself) through an example. | |
674 | // | |
675 | // Let's start with an easy case. Consider two traits: | |
676 | // | |
a1dfa0c6 | 677 | // trait Foo<'a>: Bar<'a,'a> { } |
e9174d1e SL |
678 | // trait Bar<'b,'c> { } |
679 | // | |
a1dfa0c6 XL |
680 | // Now, if we have a trait reference `for<'x> T: Foo<'x>`, then |
681 | // we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we | |
e9174d1e SL |
682 | // knew that `Foo<'x>` (for any 'x) then we also know that |
683 | // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from | |
684 | // normal substitution. | |
685 | // | |
686 | // In terms of why this is sound, the idea is that whenever there | |
687 | // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` | |
9c376795 | 688 | // holds. So if there is an impl of `T:Foo<'a>` that applies to |
e9174d1e SL |
689 | // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all |
690 | // `'a`. | |
691 | // | |
692 | // Another example to be careful of is this: | |
693 | // | |
a1dfa0c6 | 694 | // trait Foo1<'a>: for<'b> Bar1<'a,'b> { } |
e9174d1e SL |
695 | // trait Bar1<'b,'c> { } |
696 | // | |
a1dfa0c6 XL |
697 | // Here, if we have `for<'x> T: Foo1<'x>`, then what do we know? |
698 | // The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The | |
e9174d1e | 699 | // reason is similar to the previous example: any impl of |
9c376795 | 700 | // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So |
e9174d1e SL |
701 | // basically we would want to collapse the bound lifetimes from |
702 | // the input (`trait_ref`) and the supertraits. | |
703 | // | |
704 | // To achieve this in practice is fairly straightforward. Let's | |
705 | // consider the more complicated scenario: | |
706 | // | |
a1dfa0c6 XL |
707 | // - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x` |
708 | // has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`, | |
e9174d1e SL |
709 | // where both `'x` and `'b` would have a DB index of 1. |
710 | // The substitution from the input trait-ref is therefore going to be | |
711 | // `'a => 'x` (where `'x` has a DB index of 1). | |
c295e0f8 | 712 | // - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an |
9ffffee4 | 713 | // early-bound parameter and `'b` is a late-bound parameter with a |
e9174d1e SL |
714 | // DB index of 1. |
715 | // - If we replace `'a` with `'x` from the input, it too will have | |
716 | // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` | |
717 | // just as we wanted. | |
718 | // | |
719 | // There is only one catch. If we just apply the substitution `'a | |
720 | // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will | |
721 | // adjust the DB index because we substituting into a binder (it | |
722 | // tries to be so smart...) resulting in `for<'x> for<'b> | |
723 | // Bar1<'x,'b>` (we have no syntax for this, so use your | |
724 | // imagination). Basically the 'x will have DB index of 2 and 'b | |
725 | // will have DB index of 1. Not quite what we want. So we apply | |
726 | // the substitution to the *contents* of the trait reference, | |
727 | // rather than the trait reference itself (put another way, the | |
728 | // substitution code expects equal binding levels in the values | |
729 | // from the substitution and the value being substituted into, and | |
730 | // this trick achieves that). | |
cdc7bbd5 XL |
731 | |
732 | // Working through the second example: | |
733 | // trait_ref: for<'x> T: Foo1<'^0.0>; substs: [T, '^0.0] | |
734 | // predicate: for<'b> Self: Bar1<'a, '^0.0>; substs: [Self, 'a, '^0.0] | |
735 | // We want to end up with: | |
736 | // for<'x, 'b> T: Bar1<'^0.0, '^0.1> | |
737 | // To do this: | |
738 | // 1) We must shift all bound vars in predicate by the length | |
739 | // of trait ref's bound vars. So, we would end up with predicate like | |
740 | // Self: Bar1<'a, '^0.1> | |
741 | // 2) We can then apply the trait substs to this, ending up with | |
742 | // T: Bar1<'^0.0, '^0.1> | |
743 | // 3) Finally, to create the final bound vars, we concatenate the bound | |
744 | // vars of the trait ref with those of the predicate: | |
745 | // ['x, 'b] | |
746 | let bound_pred = self.kind(); | |
747 | let pred_bound_vars = bound_pred.bound_vars(); | |
748 | let trait_bound_vars = trait_ref.bound_vars(); | |
749 | // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1> | |
750 | let shifted_pred = | |
751 | tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); | |
752 | // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> | |
04454e1e | 753 | let new = EarlyBinder(shifted_pred).subst(tcx, trait_ref.skip_binder().substs); |
cdc7bbd5 XL |
754 | // 3) ['x] + ['b] -> ['x, 'b] |
755 | let bound_vars = | |
9ffffee4 | 756 | tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars)); |
cdc7bbd5 | 757 | tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars)) |
e9174d1e SL |
758 | } |
759 | } | |
760 | ||
3dfed10e | 761 | #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] |
f2b60f7d | 762 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
e9174d1e | 763 | pub struct TraitPredicate<'tcx> { |
dfeec247 | 764 | pub trait_ref: TraitRef<'tcx>, |
94222f64 XL |
765 | |
766 | pub constness: BoundConstness, | |
3c0e092e | 767 | |
5e7ed085 FG |
768 | /// If polarity is Positive: we are proving that the trait is implemented. |
769 | /// | |
770 | /// If polarity is Negative: we are proving that a negative impl of this trait | |
771 | /// exists. (Note that coherence also checks whether negative impls of supertraits | |
772 | /// exist via a series of predicates.) | |
773 | /// | |
774 | /// If polarity is Reserved: that's a bug. | |
3c0e092e | 775 | pub polarity: ImplPolarity, |
e9174d1e | 776 | } |
a1dfa0c6 | 777 | |
cdc7bbd5 | 778 | pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; |
e9174d1e SL |
779 | |
780 | impl<'tcx> TraitPredicate<'tcx> { | |
064997fb FG |
781 | pub fn remap_constness(&mut self, param_env: &mut ParamEnv<'tcx>) { |
782 | *param_env = param_env.with_constness(self.constness.and(param_env.constness())) | |
a2a8927a | 783 | } |
5099ac24 FG |
784 | |
785 | /// Remap the constness of this predicate before emitting it for diagnostics. | |
786 | pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { | |
787 | // this is different to `remap_constness` that callees want to print this predicate | |
788 | // in case of selection errors. `T: ~const Drop` bounds cannot end up here when the | |
064997fb | 789 | // param_env is not const because it is always satisfied in non-const contexts. |
5099ac24 FG |
790 | if let hir::Constness::NotConst = param_env.constness() { |
791 | self.constness = ty::BoundConstness::NotConst; | |
792 | } | |
793 | } | |
794 | ||
9c376795 FG |
795 | pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { |
796 | Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self } | |
487cf647 FG |
797 | } |
798 | ||
f9f354fc | 799 | pub fn def_id(self) -> DefId { |
e9174d1e SL |
800 | self.trait_ref.def_id |
801 | } | |
802 | ||
f9f354fc | 803 | pub fn self_ty(self) -> Ty<'tcx> { |
e9174d1e SL |
804 | self.trait_ref.self_ty() |
805 | } | |
5099ac24 FG |
806 | |
807 | #[inline] | |
808 | pub fn is_const_if_const(self) -> bool { | |
809 | self.constness == BoundConstness::ConstIfConst | |
810 | } | |
064997fb FG |
811 | |
812 | pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool { | |
813 | match (self.constness, constness) { | |
814 | (BoundConstness::NotConst, _) | |
815 | | (BoundConstness::ConstIfConst, hir::Constness::Const) => true, | |
816 | (BoundConstness::ConstIfConst, hir::Constness::NotConst) => false, | |
817 | } | |
818 | } | |
2b03887a FG |
819 | |
820 | pub fn without_const(mut self) -> Self { | |
821 | self.constness = BoundConstness::NotConst; | |
822 | self | |
823 | } | |
e9174d1e SL |
824 | } |
825 | ||
826 | impl<'tcx> PolyTraitPredicate<'tcx> { | |
f9f354fc | 827 | pub fn def_id(self) -> DefId { |
416331ca | 828 | // Ok to skip binder since trait `DefId` does not care about regions. |
83c7162d | 829 | self.skip_binder().def_id() |
e9174d1e | 830 | } |
fc512014 | 831 | |
cdc7bbd5 | 832 | pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { |
fc512014 XL |
833 | self.map_bound(|trait_ref| trait_ref.self_ty()) |
834 | } | |
5099ac24 FG |
835 | |
836 | /// Remap the constness of this predicate before emitting it for diagnostics. | |
837 | pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { | |
838 | *self = self.map_bound(|mut p| { | |
839 | p.remap_constness_diag(param_env); | |
840 | p | |
841 | }); | |
842 | } | |
843 | ||
844 | #[inline] | |
845 | pub fn is_const_if_const(self) -> bool { | |
846 | self.skip_binder().is_const_if_const() | |
847 | } | |
e9174d1e SL |
848 | } |
849 | ||
487cf647 | 850 | /// `A: B` |
3dfed10e | 851 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] |
f2b60f7d | 852 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
487cf647 | 853 | pub struct OutlivesPredicate<A, B>(pub A, pub B); |
dc9dc135 XL |
854 | pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>; |
855 | pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>; | |
cdc7bbd5 XL |
856 | pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>; |
857 | pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>; | |
e9174d1e | 858 | |
94222f64 XL |
859 | /// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates |
860 | /// whether the `a` type is the type that we should label as "expected" when | |
861 | /// presenting user diagnostics. | |
3dfed10e | 862 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] |
f2b60f7d | 863 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
cc61c64b XL |
864 | pub struct SubtypePredicate<'tcx> { |
865 | pub a_is_expected: bool, | |
866 | pub a: Ty<'tcx>, | |
dfeec247 | 867 | pub b: Ty<'tcx>, |
cc61c64b | 868 | } |
cdc7bbd5 | 869 | pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; |
cc61c64b | 870 | |
94222f64 XL |
871 | /// Encodes that we have to coerce *from* the `a` type to the `b` type. |
872 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] | |
f2b60f7d | 873 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
94222f64 XL |
874 | pub struct CoercePredicate<'tcx> { |
875 | pub a: Ty<'tcx>, | |
876 | pub b: Ty<'tcx>, | |
877 | } | |
878 | pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; | |
879 | ||
f2b60f7d FG |
880 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
881 | pub struct Term<'tcx> { | |
882 | ptr: NonZeroUsize, | |
883 | marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>, | |
884 | } | |
885 | ||
886 | impl Debug for Term<'_> { | |
887 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
888 | let data = if let Some(ty) = self.ty() { | |
889 | format!("Term::Ty({:?})", ty) | |
890 | } else if let Some(ct) = self.ct() { | |
891 | format!("Term::Ct({:?})", ct) | |
892 | } else { | |
893 | unreachable!() | |
894 | }; | |
895 | f.write_str(&data) | |
896 | } | |
5099ac24 FG |
897 | } |
898 | ||
899 | impl<'tcx> From<Ty<'tcx>> for Term<'tcx> { | |
900 | fn from(ty: Ty<'tcx>) -> Self { | |
f2b60f7d | 901 | TermKind::Ty(ty).pack() |
5099ac24 FG |
902 | } |
903 | } | |
904 | ||
905 | impl<'tcx> From<Const<'tcx>> for Term<'tcx> { | |
906 | fn from(c: Const<'tcx>) -> Self { | |
f2b60f7d FG |
907 | TermKind::Const(c).pack() |
908 | } | |
909 | } | |
910 | ||
911 | impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Term<'tcx> { | |
912 | fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { | |
913 | self.unpack().hash_stable(hcx, hasher); | |
914 | } | |
915 | } | |
916 | ||
9ffffee4 FG |
917 | impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> { |
918 | fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( | |
919 | self, | |
920 | folder: &mut F, | |
921 | ) -> Result<Self, F::Error> { | |
f2b60f7d FG |
922 | Ok(self.unpack().try_fold_with(folder)?.pack()) |
923 | } | |
924 | } | |
925 | ||
9ffffee4 FG |
926 | impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> { |
927 | fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { | |
f2b60f7d FG |
928 | self.unpack().visit_with(visitor) |
929 | } | |
930 | } | |
931 | ||
932 | impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for Term<'tcx> { | |
933 | fn encode(&self, e: &mut E) { | |
934 | self.unpack().encode(e) | |
935 | } | |
936 | } | |
937 | ||
938 | impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Term<'tcx> { | |
939 | fn decode(d: &mut D) -> Self { | |
940 | let res: TermKind<'tcx> = Decodable::decode(d); | |
941 | res.pack() | |
5099ac24 FG |
942 | } |
943 | } | |
944 | ||
945 | impl<'tcx> Term<'tcx> { | |
f2b60f7d FG |
946 | #[inline] |
947 | pub fn unpack(self) -> TermKind<'tcx> { | |
948 | let ptr = self.ptr.get(); | |
949 | // SAFETY: use of `Interned::new_unchecked` here is ok because these | |
950 | // pointers were originally created from `Interned` types in `pack()`, | |
951 | // and this is just going in the other direction. | |
952 | unsafe { | |
953 | match ptr & TAG_MASK { | |
954 | TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( | |
487cf647 | 955 | &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>), |
f2b60f7d FG |
956 | ))), |
957 | CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( | |
9c376795 | 958 | &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>), |
f2b60f7d FG |
959 | ))), |
960 | _ => core::intrinsics::unreachable(), | |
961 | } | |
962 | } | |
963 | } | |
964 | ||
5099ac24 | 965 | pub fn ty(&self) -> Option<Ty<'tcx>> { |
f2b60f7d | 966 | if let TermKind::Ty(ty) = self.unpack() { Some(ty) } else { None } |
5099ac24 | 967 | } |
064997fb | 968 | |
5099ac24 | 969 | pub fn ct(&self) -> Option<Const<'tcx>> { |
f2b60f7d | 970 | if let TermKind::Const(c) = self.unpack() { Some(c) } else { None } |
5099ac24 | 971 | } |
064997fb FG |
972 | |
973 | pub fn into_arg(self) -> GenericArg<'tcx> { | |
f2b60f7d FG |
974 | match self.unpack() { |
975 | TermKind::Ty(ty) => ty.into(), | |
976 | TermKind::Const(c) => c.into(), | |
064997fb FG |
977 | } |
978 | } | |
9ffffee4 FG |
979 | |
980 | /// This function returns `None` for `AliasKind::Opaque`. | |
981 | /// | |
982 | /// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly | |
983 | /// deal with constants. | |
984 | pub fn to_alias_term_no_opaque(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> { | |
985 | match self.unpack() { | |
986 | TermKind::Ty(ty) => match ty.kind() { | |
987 | ty::Alias(kind, alias_ty) => match kind { | |
988 | AliasKind::Projection => Some(*alias_ty), | |
989 | AliasKind::Opaque => None, | |
990 | }, | |
991 | _ => None, | |
992 | }, | |
993 | TermKind::Const(ct) => match ct.kind() { | |
994 | ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def.did, uv.substs)), | |
995 | _ => None, | |
996 | }, | |
997 | } | |
998 | } | |
999 | ||
1000 | pub fn is_infer(&self) -> bool { | |
1001 | match self.unpack() { | |
1002 | TermKind::Ty(ty) => ty.is_ty_or_numeric_infer(), | |
1003 | TermKind::Const(ct) => ct.is_ct_infer(), | |
1004 | } | |
1005 | } | |
5099ac24 FG |
1006 | } |
1007 | ||
f2b60f7d FG |
1008 | const TAG_MASK: usize = 0b11; |
1009 | const TYPE_TAG: usize = 0b00; | |
1010 | const CONST_TAG: usize = 0b01; | |
1011 | ||
1012 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)] | |
1013 | #[derive(HashStable, TypeFoldable, TypeVisitable)] | |
1014 | pub enum TermKind<'tcx> { | |
1015 | Ty(Ty<'tcx>), | |
1016 | Const(Const<'tcx>), | |
1017 | } | |
1018 | ||
1019 | impl<'tcx> TermKind<'tcx> { | |
1020 | #[inline] | |
1021 | fn pack(self) -> Term<'tcx> { | |
1022 | let (tag, ptr) = match self { | |
1023 | TermKind::Ty(ty) => { | |
1024 | // Ensure we can use the tag bits. | |
1025 | assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); | |
487cf647 | 1026 | (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize) |
f2b60f7d FG |
1027 | } |
1028 | TermKind::Const(ct) => { | |
1029 | // Ensure we can use the tag bits. | |
1030 | assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); | |
9c376795 | 1031 | (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize) |
f2b60f7d FG |
1032 | } |
1033 | }; | |
1034 | ||
1035 | Term { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData } | |
1036 | } | |
1037 | } | |
1038 | ||
e9174d1e SL |
1039 | /// This kind of predicate has no *direct* correspondent in the |
1040 | /// syntax, but it roughly corresponds to the syntactic forms: | |
1041 | /// | |
9fa01778 | 1042 | /// 1. `T: TraitRef<..., Item = Type>` |
e9174d1e SL |
1043 | /// 2. `<T as TraitRef<...>>::Item == Type` (NYI) |
1044 | /// | |
1045 | /// In particular, form #1 is "desugared" to the combination of a | |
a1dfa0c6 | 1046 | /// normal trait predicate (`T: TraitRef<...>`) and one of these |
e9174d1e | 1047 | /// predicates. Form #2 is a broader form in that it also permits |
ff7c6d11 XL |
1048 | /// equality between arbitrary types. Processing an instance of |
1049 | /// Form #2 eventually yields one of these `ProjectionPredicate` | |
e9174d1e | 1050 | /// instances to normalize the LHS. |
3dfed10e | 1051 | #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] |
f2b60f7d | 1052 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
e9174d1e | 1053 | pub struct ProjectionPredicate<'tcx> { |
9c376795 | 1054 | pub projection_ty: AliasTy<'tcx>, |
5099ac24 | 1055 | pub term: Term<'tcx>, |
e9174d1e SL |
1056 | } |
1057 | ||
9c376795 FG |
1058 | impl<'tcx> ProjectionPredicate<'tcx> { |
1059 | pub fn self_ty(self) -> Ty<'tcx> { | |
1060 | self.projection_ty.self_ty() | |
1061 | } | |
1062 | ||
1063 | pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> { | |
1064 | Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self } | |
1065 | } | |
1066 | ||
1067 | pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { | |
1068 | self.projection_ty.trait_def_id(tcx) | |
1069 | } | |
1070 | ||
1071 | pub fn def_id(self) -> DefId { | |
1072 | self.projection_ty.def_id | |
1073 | } | |
1074 | } | |
1075 | ||
cdc7bbd5 | 1076 | pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; |
e9174d1e SL |
1077 | |
1078 | impl<'tcx> PolyProjectionPredicate<'tcx> { | |
6a06907d XL |
1079 | /// Returns the `DefId` of the trait of the associated item being projected. |
1080 | #[inline] | |
1081 | pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { | |
1082 | self.skip_binder().projection_ty.trait_def_id(tcx) | |
1083 | } | |
1084 | ||
6a06907d XL |
1085 | /// Get the [PolyTraitRef] required for this projection to be well formed. |
1086 | /// Note that for generic associated types the predicates of the associated | |
1087 | /// type also need to be checked. | |
a1dfa0c6 | 1088 | #[inline] |
6a06907d | 1089 | pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> { |
a1dfa0c6 XL |
1090 | // Note: unlike with `TraitRef::to_poly_trait_ref()`, |
1091 | // `self.0.trait_ref` is permitted to have escaping regions. | |
041b39d2 XL |
1092 | // This is because here `self` has a `Binder` and so does our |
1093 | // return value, so we are preserving the number of binding | |
1094 | // levels. | |
83c7162d | 1095 | self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) |
e9174d1e | 1096 | } |
3b2f2976 | 1097 | |
5099ac24 FG |
1098 | pub fn term(&self) -> Binder<'tcx, Term<'tcx>> { |
1099 | self.map_bound(|predicate| predicate.term) | |
83c7162d XL |
1100 | } |
1101 | ||
a1dfa0c6 | 1102 | /// The `DefId` of the `TraitItem` for the associated type. |
83c7162d | 1103 | /// |
a1dfa0c6 XL |
1104 | /// Note that this is not the `DefId` of the `TraitRef` containing this |
1105 | /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. | |
83c7162d | 1106 | pub fn projection_def_id(&self) -> DefId { |
416331ca | 1107 | // Ok to skip binder since trait `DefId` does not care about regions. |
9c376795 | 1108 | self.skip_binder().projection_ty.def_id |
3b2f2976 | 1109 | } |
e9174d1e SL |
1110 | } |
1111 | ||
1112 | pub trait ToPolyTraitRef<'tcx> { | |
1113 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; | |
1114 | } | |
1115 | ||
e9174d1e SL |
1116 | impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { |
1117 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { | |
7453a54e | 1118 | self.map_bound_ref(|trait_pred| trait_pred.trait_ref) |
e9174d1e SL |
1119 | } |
1120 | } | |
1121 | ||
487cf647 FG |
1122 | pub trait ToPredicate<'tcx, P = Predicate<'tcx>> { |
1123 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P; | |
f9f354fc XL |
1124 | } |
1125 | ||
487cf647 FG |
1126 | impl<'tcx, T> ToPredicate<'tcx, T> for T { |
1127 | fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T { | |
f2b60f7d FG |
1128 | self |
1129 | } | |
1130 | } | |
1131 | ||
a2a8927a | 1132 | impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { |
f9f354fc | 1133 | #[inline(always)] |
f035d41b XL |
1134 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { |
1135 | tcx.mk_predicate(self) | |
f9f354fc | 1136 | } |
e9174d1e SL |
1137 | } |
1138 | ||
487cf647 FG |
1139 | impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { |
1140 | #[inline(always)] | |
1141 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { | |
1142 | tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self))) | |
1143 | } | |
1144 | } | |
1145 | ||
1146 | impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { | |
1147 | #[inline(always)] | |
1148 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { | |
1149 | let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); | |
1150 | pred.to_predicate(tcx) | |
1151 | } | |
1152 | } | |
1153 | ||
1154 | impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { | |
1155 | #[inline(always)] | |
1156 | fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { | |
1157 | self.map_bound(|trait_ref| TraitPredicate { | |
1158 | trait_ref, | |
1159 | constness: ty::BoundConstness::NotConst, | |
1160 | polarity: ty::ImplPolarity::Positive, | |
1161 | }) | |
1162 | } | |
1163 | } | |
1164 | ||
94222f64 | 1165 | impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { |
f035d41b | 1166 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { |
487cf647 | 1167 | self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx) |
e9174d1e SL |
1168 | } |
1169 | } | |
1170 | ||
9e0c209e | 1171 | impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { |
f035d41b | 1172 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { |
487cf647 | 1173 | self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx) |
e9174d1e SL |
1174 | } |
1175 | } | |
1176 | ||
1177 | impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { | |
f035d41b | 1178 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { |
487cf647 | 1179 | self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx) |
e9174d1e SL |
1180 | } |
1181 | } | |
1182 | ||
1183 | impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { | |
f035d41b | 1184 | fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { |
487cf647 | 1185 | self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx) |
e9174d1e SL |
1186 | } |
1187 | } | |
1188 | ||
1189 | impl<'tcx> Predicate<'tcx> { | |
a2a8927a | 1190 | pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> { |
5869c6ff | 1191 | let predicate = self.kind(); |
fc512014 | 1192 | match predicate.skip_binder() { |
487cf647 FG |
1193 | PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)), |
1194 | PredicateKind::Clause(Clause::Projection(..)) | |
9ffffee4 FG |
1195 | | PredicateKind::Clause(Clause::ConstArgHasType(..)) |
1196 | | PredicateKind::AliasEq(..) | |
5869c6ff | 1197 | | PredicateKind::Subtype(..) |
94222f64 | 1198 | | PredicateKind::Coerce(..) |
487cf647 | 1199 | | PredicateKind::Clause(Clause::RegionOutlives(..)) |
5869c6ff XL |
1200 | | PredicateKind::WellFormed(..) |
1201 | | PredicateKind::ObjectSafe(..) | |
1202 | | PredicateKind::ClosureKind(..) | |
487cf647 | 1203 | | PredicateKind::Clause(Clause::TypeOutlives(..)) |
5869c6ff XL |
1204 | | PredicateKind::ConstEvaluatable(..) |
1205 | | PredicateKind::ConstEquate(..) | |
487cf647 | 1206 | | PredicateKind::Ambiguous |
5869c6ff | 1207 | | PredicateKind::TypeWellFormedFromEnv(..) => None, |
e9174d1e SL |
1208 | } |
1209 | } | |
abe05a73 | 1210 | |
064997fb FG |
1211 | pub fn to_opt_poly_projection_pred(self) -> Option<PolyProjectionPredicate<'tcx>> { |
1212 | let predicate = self.kind(); | |
1213 | match predicate.skip_binder() { | |
487cf647 FG |
1214 | PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)), |
1215 | PredicateKind::Clause(Clause::Trait(..)) | |
9ffffee4 FG |
1216 | | PredicateKind::Clause(Clause::ConstArgHasType(..)) |
1217 | | PredicateKind::AliasEq(..) | |
064997fb FG |
1218 | | PredicateKind::Subtype(..) |
1219 | | PredicateKind::Coerce(..) | |
487cf647 | 1220 | | PredicateKind::Clause(Clause::RegionOutlives(..)) |
064997fb FG |
1221 | | PredicateKind::WellFormed(..) |
1222 | | PredicateKind::ObjectSafe(..) | |
1223 | | PredicateKind::ClosureKind(..) | |
487cf647 | 1224 | | PredicateKind::Clause(Clause::TypeOutlives(..)) |
064997fb FG |
1225 | | PredicateKind::ConstEvaluatable(..) |
1226 | | PredicateKind::ConstEquate(..) | |
487cf647 | 1227 | | PredicateKind::Ambiguous |
064997fb FG |
1228 | | PredicateKind::TypeWellFormedFromEnv(..) => None, |
1229 | } | |
1230 | } | |
1231 | ||
f9f354fc | 1232 | pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> { |
5869c6ff | 1233 | let predicate = self.kind(); |
fc512014 | 1234 | match predicate.skip_binder() { |
487cf647 FG |
1235 | PredicateKind::Clause(Clause::TypeOutlives(data)) => Some(predicate.rebind(data)), |
1236 | PredicateKind::Clause(Clause::Trait(..)) | |
9ffffee4 | 1237 | | PredicateKind::Clause(Clause::ConstArgHasType(..)) |
487cf647 | 1238 | | PredicateKind::Clause(Clause::Projection(..)) |
9ffffee4 | 1239 | | PredicateKind::AliasEq(..) |
5869c6ff | 1240 | | PredicateKind::Subtype(..) |
94222f64 | 1241 | | PredicateKind::Coerce(..) |
487cf647 | 1242 | | PredicateKind::Clause(Clause::RegionOutlives(..)) |
5869c6ff XL |
1243 | | PredicateKind::WellFormed(..) |
1244 | | PredicateKind::ObjectSafe(..) | |
1245 | | PredicateKind::ClosureKind(..) | |
1246 | | PredicateKind::ConstEvaluatable(..) | |
1247 | | PredicateKind::ConstEquate(..) | |
487cf647 | 1248 | | PredicateKind::Ambiguous |
5869c6ff | 1249 | | PredicateKind::TypeWellFormedFromEnv(..) => None, |
abe05a73 XL |
1250 | } |
1251 | } | |
e9174d1e SL |
1252 | } |
1253 | ||
1254 | /// Represents the bounds declared on a particular set of type | |
9fa01778 | 1255 | /// parameters. Should eventually be generalized into a flag list of |
94222f64 | 1256 | /// where-clauses. You can obtain an `InstantiatedPredicates` list from a |
e9174d1e SL |
1257 | /// `GenericPredicates` by using the `instantiate` method. Note that this method |
1258 | /// reflects an important semantic invariant of `InstantiatedPredicates`: while | |
1259 | /// the `GenericPredicates` are expressed in terms of the bound type | |
1260 | /// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance | |
1261 | /// represented a set of bounds for some particular instantiation, | |
1262 | /// meaning that the generic parameters have been substituted with | |
1263 | /// their values. | |
1264 | /// | |
1265 | /// Example: | |
04454e1e FG |
1266 | /// ```ignore (illustrative) |
1267 | /// struct Foo<T, U: Bar<T>> { ... } | |
1268 | /// ``` | |
e9174d1e | 1269 | /// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like |
9fa01778 | 1270 | /// `[[], [U:Bar<T>]]`. Now if there were some particular reference |
e9174d1e SL |
1271 | /// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[], |
1272 | /// [usize:Bar<isize>]]`. | |
064997fb | 1273 | #[derive(Clone, Debug, TypeFoldable, TypeVisitable)] |
e9174d1e | 1274 | pub struct InstantiatedPredicates<'tcx> { |
9e0c209e | 1275 | pub predicates: Vec<Predicate<'tcx>>, |
74b04a01 | 1276 | pub spans: Vec<Span>, |
e9174d1e SL |
1277 | } |
1278 | ||
1279 | impl<'tcx> InstantiatedPredicates<'tcx> { | |
1280 | pub fn empty() -> InstantiatedPredicates<'tcx> { | |
74b04a01 | 1281 | InstantiatedPredicates { predicates: vec![], spans: vec![] } |
e9174d1e SL |
1282 | } |
1283 | ||
1284 | pub fn is_empty(&self) -> bool { | |
1285 | self.predicates.is_empty() | |
1286 | } | |
9c376795 FG |
1287 | |
1288 | pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter { | |
1289 | (&self).into_iter() | |
1290 | } | |
1291 | } | |
1292 | ||
1293 | impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> { | |
1294 | type Item = (Predicate<'tcx>, Span); | |
1295 | ||
1296 | type IntoIter = std::iter::Zip<std::vec::IntoIter<Predicate<'tcx>>, std::vec::IntoIter<Span>>; | |
1297 | ||
1298 | fn into_iter(self) -> Self::IntoIter { | |
1299 | debug_assert_eq!(self.predicates.len(), self.spans.len()); | |
1300 | std::iter::zip(self.predicates, self.spans) | |
1301 | } | |
1302 | } | |
1303 | ||
1304 | impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> { | |
1305 | type Item = (Predicate<'tcx>, Span); | |
1306 | ||
1307 | type IntoIter = std::iter::Zip< | |
1308 | std::iter::Copied<std::slice::Iter<'a, Predicate<'tcx>>>, | |
1309 | std::iter::Copied<std::slice::Iter<'a, Span>>, | |
1310 | >; | |
1311 | ||
1312 | fn into_iter(self) -> Self::IntoIter { | |
1313 | debug_assert_eq!(self.predicates.len(), self.spans.len()); | |
1314 | std::iter::zip(self.predicates.iter().copied(), self.spans.iter().copied()) | |
1315 | } | |
e9174d1e SL |
1316 | } |
1317 | ||
487cf647 | 1318 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)] |
064997fb | 1319 | #[derive(TypeFoldable, TypeVisitable)] |
17df50a5 | 1320 | pub struct OpaqueTypeKey<'tcx> { |
064997fb | 1321 | pub def_id: LocalDefId, |
17df50a5 XL |
1322 | pub substs: SubstsRef<'tcx>, |
1323 | } | |
1324 | ||
064997fb | 1325 | #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)] |
5e7ed085 FG |
1326 | pub struct OpaqueHiddenType<'tcx> { |
1327 | /// The span of this particular definition of the opaque type. So | |
1328 | /// for example: | |
1329 | /// | |
1330 | /// ```ignore (incomplete snippet) | |
1331 | /// type Foo = impl Baz; | |
1332 | /// fn bar() -> Foo { | |
1333 | /// // ^^^ This is the span we are looking for! | |
1334 | /// } | |
1335 | /// ``` | |
1336 | /// | |
1337 | /// In cases where the fn returns `(impl Trait, impl Trait)` or | |
1338 | /// other such combinations, the result is currently | |
1339 | /// over-approximated, but better than nothing. | |
1340 | pub span: Span, | |
1341 | ||
1342 | /// The type variable that represents the value of the opaque type | |
1343 | /// that we require. In other words, after we compile this function, | |
1344 | /// we will be created a constraint like: | |
04454e1e FG |
1345 | /// ```ignore (pseudo-rust) |
1346 | /// Foo<'a, T> = ?C | |
1347 | /// ``` | |
5e7ed085 FG |
1348 | /// where `?C` is the value of this type variable. =) It may |
1349 | /// naturally refer to the type and lifetime parameters in scope | |
1350 | /// in this function, though ultimately it should only reference | |
1351 | /// those that are arguments to `Foo` in the constraint above. (In | |
1352 | /// other words, `?C` should not include `'b`, even though it's a | |
1353 | /// lifetime parameter on `foo`.) | |
1354 | pub ty: Ty<'tcx>, | |
1355 | } | |
1356 | ||
04454e1e | 1357 | impl<'tcx> OpaqueHiddenType<'tcx> { |
9ffffee4 | 1358 | pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) -> ErrorGuaranteed { |
04454e1e | 1359 | // Found different concrete types for the opaque type. |
f2b60f7d FG |
1360 | let sub_diag = if self.span == other.span { |
1361 | TypeMismatchReason::ConflictType { span: self.span } | |
04454e1e | 1362 | } else { |
f2b60f7d FG |
1363 | TypeMismatchReason::PreviousUse { span: self.span } |
1364 | }; | |
1365 | tcx.sess.emit_err(OpaqueHiddenTypeMismatch { | |
1366 | self_ty: self.ty, | |
1367 | other_ty: other.ty, | |
1368 | other_span: other.span, | |
1369 | sub: sub_diag, | |
9ffffee4 | 1370 | }) |
04454e1e | 1371 | } |
2b03887a FG |
1372 | |
1373 | #[instrument(level = "debug", skip(tcx), ret)] | |
1374 | pub fn remap_generic_params_to_declaration_params( | |
1375 | self, | |
1376 | opaque_type_key: OpaqueTypeKey<'tcx>, | |
1377 | tcx: TyCtxt<'tcx>, | |
1378 | // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck. | |
1379 | ignore_errors: bool, | |
2b03887a FG |
1380 | ) -> Self { |
1381 | let OpaqueTypeKey { def_id, substs } = opaque_type_key; | |
1382 | ||
1383 | // Use substs to build up a reverse map from regions to their | |
1384 | // identity mappings. This is necessary because of `impl | |
1385 | // Trait` lifetimes are computed by replacing existing | |
1386 | // lifetimes with 'static and remapping only those used in the | |
1387 | // `impl Trait` return type, resulting in the parameters | |
1388 | // shifting. | |
1389 | let id_substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); | |
1390 | debug!(?id_substs); | |
1391 | ||
487cf647 | 1392 | // This zip may have several times the same lifetime in `substs` paired with a different |
9c376795 | 1393 | // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour: |
487cf647 FG |
1394 | // it will pick the last one, which is the one we introduced in the impl-trait desugaring. |
1395 | let map = substs.iter().zip(id_substs).collect(); | |
2b03887a FG |
1396 | debug!("map = {:#?}", map); |
1397 | ||
1398 | // Convert the type from the function into a type valid outside | |
1399 | // the function, by replacing invalid regions with 'static, | |
1400 | // after producing an error for each of them. | |
1401 | self.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span, ignore_errors)) | |
1402 | } | |
04454e1e FG |
1403 | } |
1404 | ||
fc512014 XL |
1405 | /// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are |
1406 | /// identified by both a universe, as well as a name residing within that universe. Distinct bound | |
1407 | /// regions/types/consts within the same universe simply have an unknown relationship to one | |
0bf4aa26 | 1408 | /// another. |
064997fb FG |
1409 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] |
1410 | #[derive(HashStable, TyEncodable, TyDecodable)] | |
a1dfa0c6 | 1411 | pub struct Placeholder<T> { |
0bf4aa26 | 1412 | pub universe: UniverseIndex, |
a1dfa0c6 | 1413 | pub name: T, |
0531ce1d XL |
1414 | } |
1415 | ||
fc512014 | 1416 | pub type PlaceholderRegion = Placeholder<BoundRegionKind>; |
a1dfa0c6 | 1417 | |
9ffffee4 | 1418 | pub type PlaceholderType = Placeholder<BoundTyKind>; |
a1dfa0c6 | 1419 | |
fc512014 XL |
1420 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] |
1421 | #[derive(TyEncodable, TyDecodable, PartialOrd, Ord)] | |
1422 | pub struct BoundConst<'tcx> { | |
1423 | pub var: BoundVar, | |
1424 | pub ty: Ty<'tcx>, | |
1425 | } | |
1426 | ||
064997fb | 1427 | pub type PlaceholderConst<'tcx> = Placeholder<BoundVar>; |
48663c56 | 1428 | |
fc512014 XL |
1429 | /// A `DefId` which, in case it is a const argument, is potentially bundled with |
1430 | /// the `DefId` of the generic parameter it instantiates. | |
3dfed10e | 1431 | /// |
fc512014 XL |
1432 | /// This is used to avoid calls to `type_of` for const arguments during typeck |
1433 | /// which cause cycle errors. | |
3dfed10e XL |
1434 | /// |
1435 | /// ```rust | |
3dfed10e XL |
1436 | /// struct A; |
1437 | /// impl A { | |
fc512014 XL |
1438 | /// fn foo<const N: usize>(&self) -> [u8; N] { [0; N] } |
1439 | /// // ^ const parameter | |
3dfed10e XL |
1440 | /// } |
1441 | /// struct B; | |
1442 | /// impl B { | |
fc512014 XL |
1443 | /// fn foo<const M: u8>(&self) -> usize { 42 } |
1444 | /// // ^ const parameter | |
3dfed10e XL |
1445 | /// } |
1446 | /// | |
1447 | /// fn main() { | |
1448 | /// let a = A; | |
fc512014 XL |
1449 | /// let _b = a.foo::<{ 3 + 7 }>(); |
1450 | /// // ^^^^^^^^^ const argument | |
3dfed10e XL |
1451 | /// } |
1452 | /// ``` | |
fc512014 XL |
1453 | /// |
1454 | /// Let's look at the call `a.foo::<{ 3 + 7 }>()` here. We do not know | |
1455 | /// which `foo` is used until we know the type of `a`. | |
1456 | /// | |
1457 | /// We only know the type of `a` once we are inside of `typeck(main)`. | |
1458 | /// We also end up normalizing the type of `_b` during `typeck(main)` which | |
1459 | /// requires us to evaluate the const argument. | |
1460 | /// | |
1461 | /// To evaluate that const argument we need to know its type, | |
1462 | /// which we would get using `type_of(const_arg)`. This requires us to | |
1463 | /// resolve `foo` as it can be either `usize` or `u8` in this example. | |
1464 | /// However, resolving `foo` once again requires `typeck(main)` to get the type of `a`, | |
1465 | /// which results in a cycle. | |
1466 | /// | |
1467 | /// In short we must not call `type_of(const_arg)` during `typeck(main)`. | |
1468 | /// | |
1469 | /// When first creating the `ty::Const` of the const argument inside of `typeck` we have | |
1470 | /// already resolved `foo` so we know which const parameter this argument instantiates. | |
1471 | /// This means that we also know the expected result of `type_of(const_arg)` even if we | |
1472 | /// aren't allowed to call that query: it is equal to `type_of(const_param)` which is | |
1473 | /// trivial to compute. | |
1474 | /// | |
5e7ed085 | 1475 | /// If we now want to use that constant in a place which potentially needs its type |
fc512014 XL |
1476 | /// we also pass the type of its `const_param`. This is the point of `WithOptConstParam`, |
1477 | /// except that instead of a `Ty` we bundle the `DefId` of the const parameter. | |
1478 | /// Meaning that we need to use `type_of(const_param_did)` if `const_param_did` is `Some` | |
1479 | /// to get the type of `did`. | |
064997fb | 1480 | #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)] |
3dfed10e XL |
1481 | #[derive(PartialEq, Eq, PartialOrd, Ord)] |
1482 | #[derive(Hash, HashStable)] | |
1483 | pub struct WithOptConstParam<T> { | |
1484 | pub did: T, | |
29967ef6 | 1485 | /// The `DefId` of the corresponding generic parameter in case `did` is |
3dfed10e XL |
1486 | /// a const argument. |
1487 | /// | |
1488 | /// Note that even if `did` is a const argument, this may still be `None`. | |
1489 | /// All queries taking `WithOptConstParam` start by calling `tcx.opt_const_param_of(def.did)` | |
fc512014 | 1490 | /// to potentially update `param_did` in the case it is `None`. |
3dfed10e XL |
1491 | pub const_param_did: Option<DefId>, |
1492 | } | |
1493 | ||
1494 | impl<T> WithOptConstParam<T> { | |
1495 | /// Creates a new `WithOptConstParam` setting `const_param_did` to `None`. | |
1496 | #[inline(always)] | |
1497 | pub fn unknown(did: T) -> WithOptConstParam<T> { | |
1498 | WithOptConstParam { did, const_param_did: None } | |
1499 | } | |
1500 | } | |
1501 | ||
1502 | impl WithOptConstParam<LocalDefId> { | |
1503 | /// Returns `Some((did, param_did))` if `def_id` is a const argument, | |
1504 | /// `None` otherwise. | |
1505 | #[inline(always)] | |
1506 | pub fn try_lookup(did: LocalDefId, tcx: TyCtxt<'_>) -> Option<(LocalDefId, DefId)> { | |
1507 | tcx.opt_const_param_of(did).map(|param_did| (did, param_did)) | |
1508 | } | |
1509 | ||
1510 | /// In case `self` is unknown but `self.did` is a const argument, this returns | |
1511 | /// a `WithOptConstParam` with the correct `const_param_did`. | |
1512 | #[inline(always)] | |
1513 | pub fn try_upgrade(self, tcx: TyCtxt<'_>) -> Option<WithOptConstParam<LocalDefId>> { | |
1514 | if self.const_param_did.is_none() { | |
1515 | if let const_param_did @ Some(_) = tcx.opt_const_param_of(self.did) { | |
1516 | return Some(WithOptConstParam { did: self.did, const_param_did }); | |
1517 | } | |
1518 | } | |
1519 | ||
1520 | None | |
1521 | } | |
1522 | ||
1523 | pub fn to_global(self) -> WithOptConstParam<DefId> { | |
1524 | WithOptConstParam { did: self.did.to_def_id(), const_param_did: self.const_param_did } | |
1525 | } | |
1526 | ||
1527 | pub fn def_id_for_type_of(self) -> DefId { | |
1528 | if let Some(did) = self.const_param_did { did } else { self.did.to_def_id() } | |
1529 | } | |
1530 | } | |
1531 | ||
1532 | impl WithOptConstParam<DefId> { | |
1533 | pub fn as_local(self) -> Option<WithOptConstParam<LocalDefId>> { | |
1534 | self.did | |
1535 | .as_local() | |
1536 | .map(|did| WithOptConstParam { did, const_param_did: self.const_param_did }) | |
1537 | } | |
1538 | ||
1539 | pub fn as_const_arg(self) -> Option<(LocalDefId, DefId)> { | |
1540 | if let Some(param_did) = self.const_param_did { | |
1541 | if let Some(did) = self.did.as_local() { | |
1542 | return Some((did, param_did)); | |
1543 | } | |
1544 | } | |
1545 | ||
1546 | None | |
1547 | } | |
1548 | ||
3dfed10e XL |
1549 | pub fn is_local(self) -> bool { |
1550 | self.did.is_local() | |
1551 | } | |
1552 | ||
1553 | pub fn def_id_for_type_of(self) -> DefId { | |
1554 | self.const_param_did.unwrap_or(self.did) | |
1555 | } | |
1556 | } | |
1557 | ||
7cac9316 XL |
1558 | /// When type checking, we use the `ParamEnv` to track |
1559 | /// details about the set of where-clauses that are in scope at this | |
1560 | /// particular point. | |
3dfed10e | 1561 | #[derive(Copy, Clone, Hash, PartialEq, Eq)] |
7cac9316 | 1562 | pub struct ParamEnv<'tcx> { |
3dfed10e XL |
1563 | /// This packs both caller bounds and the reveal enum into one pointer. |
1564 | /// | |
1565 | /// Caller bounds are `Obligation`s that the caller must satisfy. This is | |
1566 | /// basically the set of bounds on the in-scope type parameters, translated | |
416331ca | 1567 | /// into `Obligation`s, and elaborated and normalized. |
f035d41b | 1568 | /// |
3dfed10e XL |
1569 | /// Use the `caller_bounds()` method to access. |
1570 | /// | |
94b46f34 | 1571 | /// Typically, this is `Reveal::UserFacing`, but during codegen we |
f035d41b XL |
1572 | /// want `Reveal::All`. |
1573 | /// | |
3dfed10e | 1574 | /// Note: This is packed, use the reveal() method to access it. |
a2a8927a | 1575 | packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, ParamTag, true>, |
7cac9316 XL |
1576 | } |
1577 | ||
a2a8927a XL |
1578 | #[derive(Copy, Clone)] |
1579 | struct ParamTag { | |
1580 | reveal: traits::Reveal, | |
1581 | constness: hir::Constness, | |
1582 | } | |
1583 | ||
1584 | unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag { | |
1585 | const BITS: usize = 2; | |
17df50a5 | 1586 | #[inline] |
3dfed10e XL |
1587 | fn into_usize(self) -> usize { |
1588 | match self { | |
a2a8927a XL |
1589 | Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } => 0, |
1590 | Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } => 1, | |
1591 | Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } => 2, | |
1592 | Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3, | |
3dfed10e XL |
1593 | } |
1594 | } | |
17df50a5 | 1595 | #[inline] |
3dfed10e XL |
1596 | unsafe fn from_usize(ptr: usize) -> Self { |
1597 | match ptr { | |
a2a8927a XL |
1598 | 0 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst }, |
1599 | 1 => Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst }, | |
1600 | 2 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const }, | |
1601 | 3 => Self { reveal: traits::Reveal::All, constness: hir::Constness::Const }, | |
3dfed10e XL |
1602 | _ => std::hint::unreachable_unchecked(), |
1603 | } | |
1604 | } | |
1605 | } | |
1606 | ||
f035d41b XL |
1607 | impl<'tcx> fmt::Debug for ParamEnv<'tcx> { |
1608 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
1609 | f.debug_struct("ParamEnv") | |
1610 | .field("caller_bounds", &self.caller_bounds()) | |
1611 | .field("reveal", &self.reveal()) | |
a2a8927a | 1612 | .field("constness", &self.constness()) |
f035d41b XL |
1613 | .finish() |
1614 | } | |
1615 | } | |
1616 | ||
f035d41b XL |
1617 | impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> { |
1618 | fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { | |
1619 | self.caller_bounds().hash_stable(hcx, hasher); | |
1620 | self.reveal().hash_stable(hcx, hasher); | |
a2a8927a | 1621 | self.constness().hash_stable(hcx, hasher); |
f035d41b XL |
1622 | } |
1623 | } | |
1624 | ||
9ffffee4 FG |
1625 | impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ParamEnv<'tcx> { |
1626 | fn try_fold_with<F: ty::fold::FallibleTypeFolder<TyCtxt<'tcx>>>( | |
a2a8927a XL |
1627 | self, |
1628 | folder: &mut F, | |
1629 | ) -> Result<Self, F::Error> { | |
1630 | Ok(ParamEnv::new( | |
1631 | self.caller_bounds().try_fold_with(folder)?, | |
1632 | self.reveal().try_fold_with(folder)?, | |
f2b60f7d | 1633 | self.constness(), |
a2a8927a | 1634 | )) |
f035d41b | 1635 | } |
064997fb | 1636 | } |
f035d41b | 1637 | |
9ffffee4 FG |
1638 | impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ParamEnv<'tcx> { |
1639 | fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { | |
29967ef6 | 1640 | self.caller_bounds().visit_with(visitor)?; |
f2b60f7d | 1641 | self.reveal().visit_with(visitor) |
f035d41b XL |
1642 | } |
1643 | } | |
1644 | ||
7cac9316 | 1645 | impl<'tcx> ParamEnv<'tcx> { |
0531ce1d | 1646 | /// Construct a trait environment suitable for contexts where |
9fa01778 | 1647 | /// there are no where-clauses in scope. Hidden types (like `impl |
0531ce1d XL |
1648 | /// Trait`) are left hidden, so this is suitable for ordinary |
1649 | /// type-checking. | |
a1dfa0c6 | 1650 | #[inline] |
0531ce1d | 1651 | pub fn empty() -> Self { |
a2a8927a | 1652 | Self::new(List::empty(), Reveal::UserFacing, hir::Constness::NotConst) |
0531ce1d XL |
1653 | } |
1654 | ||
f035d41b | 1655 | #[inline] |
3dfed10e XL |
1656 | pub fn caller_bounds(self) -> &'tcx List<Predicate<'tcx>> { |
1657 | self.packed.pointer() | |
f035d41b XL |
1658 | } |
1659 | ||
1660 | #[inline] | |
1661 | pub fn reveal(self) -> traits::Reveal { | |
a2a8927a XL |
1662 | self.packed.tag().reveal |
1663 | } | |
1664 | ||
1665 | #[inline] | |
1666 | pub fn constness(self) -> hir::Constness { | |
1667 | self.packed.tag().constness | |
f035d41b XL |
1668 | } |
1669 | ||
5099ac24 FG |
1670 | #[inline] |
1671 | pub fn is_const(self) -> bool { | |
1672 | self.packed.tag().constness == hir::Constness::Const | |
1673 | } | |
1674 | ||
9fa01778 | 1675 | /// Construct a trait environment with no where-clauses in scope |
0531ce1d XL |
1676 | /// where the values of all `impl Trait` and other hidden types |
1677 | /// are revealed. This is suitable for monomorphized, post-typeck | |
94b46f34 | 1678 | /// environments like codegen or doing optimizations. |
0531ce1d | 1679 | /// |
9fa01778 | 1680 | /// N.B., if you want to have predicates in scope, use `ParamEnv::new`, |
0531ce1d | 1681 | /// or invoke `param_env.with_reveal_all()`. |
a1dfa0c6 | 1682 | #[inline] |
0531ce1d | 1683 | pub fn reveal_all() -> Self { |
a2a8927a | 1684 | Self::new(List::empty(), Reveal::All, hir::Constness::NotConst) |
0531ce1d XL |
1685 | } |
1686 | ||
1687 | /// Construct a trait environment with the given set of predicates. | |
a1dfa0c6 | 1688 | #[inline] |
a2a8927a XL |
1689 | pub fn new( |
1690 | caller_bounds: &'tcx List<Predicate<'tcx>>, | |
1691 | reveal: Reveal, | |
1692 | constness: hir::Constness, | |
1693 | ) -> Self { | |
1694 | ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) } | |
f035d41b XL |
1695 | } |
1696 | ||
1697 | pub fn with_user_facing(mut self) -> Self { | |
a2a8927a | 1698 | self.packed.set_tag(ParamTag { reveal: Reveal::UserFacing, ..self.packed.tag() }); |
f035d41b | 1699 | self |
0531ce1d XL |
1700 | } |
1701 | ||
a2a8927a XL |
1702 | #[inline] |
1703 | pub fn with_constness(mut self, constness: hir::Constness) -> Self { | |
1704 | self.packed.set_tag(ParamTag { constness, ..self.packed.tag() }); | |
1705 | self | |
1706 | } | |
1707 | ||
1708 | #[inline] | |
1709 | pub fn with_const(mut self) -> Self { | |
1710 | self.packed.set_tag(ParamTag { constness: hir::Constness::Const, ..self.packed.tag() }); | |
1711 | self | |
1712 | } | |
1713 | ||
1714 | #[inline] | |
1715 | pub fn without_const(mut self) -> Self { | |
1716 | self.packed.set_tag(ParamTag { constness: hir::Constness::NotConst, ..self.packed.tag() }); | |
1717 | self | |
1718 | } | |
1719 | ||
1720 | #[inline] | |
1721 | pub fn remap_constness_with(&mut self, mut constness: ty::BoundConstness) { | |
1722 | *self = self.with_constness(constness.and(self.constness())) | |
1723 | } | |
1724 | ||
0531ce1d XL |
1725 | /// Returns a new parameter environment with the same clauses, but |
1726 | /// which "reveals" the true results of projections in all cases | |
9fa01778 | 1727 | /// (even for associated types that are specializable). This is |
94b46f34 | 1728 | /// the desired behavior during codegen and certain other special |
0531ce1d XL |
1729 | /// contexts; normally though we want to use `Reveal::UserFacing`, |
1730 | /// which is the default. | |
3dfed10e XL |
1731 | /// All opaque types in the caller_bounds of the `ParamEnv` |
1732 | /// will be normalized to their underlying types. | |
1733 | /// See PR #65989 and issue #65918 for more details | |
1734 | pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self { | |
a2a8927a | 1735 | if self.packed.tag().reveal == traits::Reveal::All { |
3dfed10e XL |
1736 | return self; |
1737 | } | |
1738 | ||
a2a8927a | 1739 | ParamEnv::new( |
487cf647 | 1740 | tcx.reveal_opaque_types_in_bounds(self.caller_bounds()), |
a2a8927a XL |
1741 | Reveal::All, |
1742 | self.constness(), | |
1743 | ) | |
0531ce1d XL |
1744 | } |
1745 | ||
1746 | /// Returns this same environment but with no caller bounds. | |
17df50a5 | 1747 | #[inline] |
0531ce1d | 1748 | pub fn without_caller_bounds(self) -> Self { |
a2a8927a | 1749 | Self::new(List::empty(), self.reveal(), self.constness()) |
0531ce1d XL |
1750 | } |
1751 | ||
7cac9316 | 1752 | /// Creates a suitable environment in which to perform trait |
0531ce1d XL |
1753 | /// queries on the given value. When type-checking, this is simply |
1754 | /// the pair of the environment plus value. But when reveal is set to | |
1755 | /// All, then if `value` does not reference any type parameters, we will | |
1756 | /// pair it with the empty environment. This improves caching and is generally | |
1757 | /// invisible. | |
e9174d1e | 1758 | /// |
0731742a | 1759 | /// N.B., we preserve the environment when type-checking because it |
0531ce1d | 1760 | /// is possible for the user to have wacky where-clauses like |
7cac9316 | 1761 | /// `where Box<u32>: Copy`, which are clearly never |
0531ce1d XL |
1762 | /// satisfiable. We generally want to behave as if they were true, |
1763 | /// although the surrounding function is never reachable. | |
9ffffee4 | 1764 | pub fn and<T: TypeVisitable<TyCtxt<'tcx>>>(self, value: T) -> ParamEnvAnd<'tcx, T> { |
f035d41b | 1765 | match self.reveal() { |
dfeec247 | 1766 | Reveal::UserFacing => ParamEnvAnd { param_env: self, value }, |
0531ce1d XL |
1767 | |
1768 | Reveal::All => { | |
5099ac24 | 1769 | if value.is_global() { |
dfeec247 | 1770 | ParamEnvAnd { param_env: self.without_caller_bounds(), value } |
74b04a01 XL |
1771 | } else { |
1772 | ParamEnvAnd { param_env: self, value } | |
0531ce1d | 1773 | } |
e9174d1e SL |
1774 | } |
1775 | } | |
1776 | } | |
1777 | } | |
1778 | ||
f9f354fc | 1779 | // FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that |
dfeec247 | 1780 | // the constness of trait bounds is being propagated correctly. |
a2a8927a | 1781 | impl<'tcx> PolyTraitRef<'tcx> { |
dfeec247 | 1782 | #[inline] |
a2a8927a XL |
1783 | pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> { |
1784 | self.map_bound(|trait_ref| ty::TraitPredicate { | |
1785 | trait_ref, | |
1786 | constness, | |
1787 | polarity: ty::ImplPolarity::Positive, | |
1788 | }) | |
dfeec247 | 1789 | } |
5099ac24 | 1790 | |
dfeec247 | 1791 | #[inline] |
a2a8927a | 1792 | pub fn without_const(self) -> PolyTraitPredicate<'tcx> { |
94222f64 | 1793 | self.with_constness(BoundConstness::NotConst) |
dfeec247 XL |
1794 | } |
1795 | } | |
1796 | ||
064997fb | 1797 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] |
f2b60f7d | 1798 | #[derive(HashStable, Lift)] |
7cac9316 XL |
1799 | pub struct ParamEnvAnd<'tcx, T> { |
1800 | pub param_env: ParamEnv<'tcx>, | |
1801 | pub value: T, | |
1802 | } | |
1803 | ||
1804 | impl<'tcx, T> ParamEnvAnd<'tcx, T> { | |
1805 | pub fn into_parts(self) -> (ParamEnv<'tcx>, T) { | |
1806 | (self.param_env, self.value) | |
1807 | } | |
a2a8927a XL |
1808 | |
1809 | #[inline] | |
1810 | pub fn without_const(mut self) -> Self { | |
1811 | self.param_env = self.param_env.without_const(); | |
1812 | self | |
1813 | } | |
7cac9316 XL |
1814 | } |
1815 | ||
923072b8 | 1816 | #[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] |
8bb4bdeb | 1817 | pub struct Destructor { |
9fa01778 | 1818 | /// The `DefId` of the destructor method |
8bb4bdeb | 1819 | pub did: DefId, |
c295e0f8 XL |
1820 | /// The constness of the destructor method |
1821 | pub constness: hir::Constness, | |
8bb4bdeb XL |
1822 | } |
1823 | ||
b7449926 | 1824 | bitflags! { |
a2a8927a | 1825 | #[derive(HashStable, TyEncodable, TyDecodable)] |
b7449926 XL |
1826 | pub struct VariantFlags: u32 { |
1827 | const NO_VARIANT_FLAGS = 0; | |
1828 | /// Indicates whether the field list of this variant is `#[non_exhaustive]`. | |
1829 | const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0; | |
1b1a35ee XL |
1830 | /// Indicates whether this variant was obtained as part of recovering from |
1831 | /// a syntactic error. May be incomplete or bogus. | |
1832 | const IS_RECOVERED = 1 << 1; | |
e9174d1e SL |
1833 | } |
1834 | } | |
1835 | ||
94222f64 | 1836 | /// Definition of a variant -- a struct's fields or an enum variant. |
a2a8927a | 1837 | #[derive(Debug, HashStable, TyEncodable, TyDecodable)] |
476ff2be | 1838 | pub struct VariantDef { |
532ac7d7 XL |
1839 | /// `DefId` that identifies the variant itself. |
1840 | /// If this variant belongs to a struct or union, then this is a copy of its `DefId`. | |
1841 | pub def_id: DefId, | |
1842 | /// `DefId` that identifies the variant's constructor. | |
1843 | /// If this variant is a struct variant, then this is `None`. | |
487cf647 | 1844 | pub ctor: Option<(CtorKind, DefId)>, |
532ac7d7 | 1845 | /// Variant or struct name. |
5099ac24 | 1846 | pub name: Symbol, |
532ac7d7 | 1847 | /// Discriminant of this variant. |
8bb4bdeb | 1848 | pub discr: VariantDiscr, |
532ac7d7 | 1849 | /// Fields of this variant. |
476ff2be | 1850 | pub fields: Vec<FieldDef>, |
532ac7d7 | 1851 | /// Flags of the variant (e.g. is field list non-exhaustive)? |
b7449926 | 1852 | flags: VariantFlags, |
e9174d1e SL |
1853 | } |
1854 | ||
1b1a35ee | 1855 | impl VariantDef { |
9fa01778 | 1856 | /// Creates a new `VariantDef`. |
b7449926 | 1857 | /// |
532ac7d7 XL |
1858 | /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef` |
1859 | /// represents an enum variant). | |
1860 | /// | |
1861 | /// `ctor_did` is the `DefId` that identifies the constructor of unit or | |
1862 | /// tuple-variants/structs. If this is a `struct`-variant then this should be `None`. | |
0bf4aa26 | 1863 | /// |
532ac7d7 XL |
1864 | /// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that |
1865 | /// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having | |
1866 | /// to go through the redirect of checking the ctor's attributes - but compiling a small crate | |
1867 | /// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any | |
0bf4aa26 XL |
1868 | /// built-in trait), and we do not want to load attributes twice. |
1869 | /// | |
1870 | /// If someone speeds up attribute loading to not be a performance concern, they can | |
9fa01778 | 1871 | /// remove this hack and use the constructor `DefId` everywhere. |
532ac7d7 | 1872 | pub fn new( |
5099ac24 | 1873 | name: Symbol, |
532ac7d7 | 1874 | variant_did: Option<DefId>, |
487cf647 | 1875 | ctor: Option<(CtorKind, DefId)>, |
532ac7d7 XL |
1876 | discr: VariantDiscr, |
1877 | fields: Vec<FieldDef>, | |
532ac7d7 XL |
1878 | adt_kind: AdtKind, |
1879 | parent_did: DefId, | |
1880 | recovered: bool, | |
3dfed10e | 1881 | is_field_list_non_exhaustive: bool, |
532ac7d7 XL |
1882 | ) -> Self { |
1883 | debug!( | |
487cf647 FG |
1884 | "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?}, |
1885 | fields = {:?}, adt_kind = {:?}, parent_did = {:?})", | |
1886 | name, variant_did, ctor, discr, fields, adt_kind, parent_did, | |
532ac7d7 XL |
1887 | ); |
1888 | ||
b7449926 | 1889 | let mut flags = VariantFlags::NO_VARIANT_FLAGS; |
3dfed10e XL |
1890 | if is_field_list_non_exhaustive { |
1891 | flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; | |
b7449926 | 1892 | } |
532ac7d7 | 1893 | |
1b1a35ee XL |
1894 | if recovered { |
1895 | flags |= VariantFlags::IS_RECOVERED; | |
1896 | } | |
1897 | ||
487cf647 | 1898 | VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags } |
b7449926 XL |
1899 | } |
1900 | ||
532ac7d7 | 1901 | /// Is this field list non-exhaustive? |
b7449926 XL |
1902 | #[inline] |
1903 | pub fn is_field_list_non_exhaustive(&self) -> bool { | |
1904 | self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE) | |
1905 | } | |
f035d41b | 1906 | |
1b1a35ee XL |
1907 | /// Was this variant obtained as part of recovering from a syntactic error? |
1908 | #[inline] | |
1909 | pub fn is_recovered(&self) -> bool { | |
1910 | self.flags.intersects(VariantFlags::IS_RECOVERED) | |
f035d41b | 1911 | } |
5099ac24 FG |
1912 | |
1913 | /// Computes the `Ident` of this variant by looking up the `Span` | |
1914 | pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { | |
1915 | Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) | |
1916 | } | |
487cf647 FG |
1917 | |
1918 | #[inline] | |
1919 | pub fn ctor_kind(&self) -> Option<CtorKind> { | |
1920 | self.ctor.map(|(kind, _)| kind) | |
1921 | } | |
1922 | ||
1923 | #[inline] | |
1924 | pub fn ctor_def_id(&self) -> Option<DefId> { | |
1925 | self.ctor.map(|(_, def_id)| def_id) | |
1926 | } | |
b7449926 XL |
1927 | } |
1928 | ||
064997fb FG |
1929 | impl PartialEq for VariantDef { |
1930 | #[inline] | |
1931 | fn eq(&self, other: &Self) -> bool { | |
1932 | // There should be only one `VariantDef` for each `def_id`, therefore | |
1933 | // it is fine to implement `PartialEq` only based on `def_id`. | |
1934 | // | |
1935 | // Below, we exhaustively destructure `self` and `other` so that if the | |
1936 | // definition of `VariantDef` changes, a compile-error will be produced, | |
1937 | // reminding us to revisit this assumption. | |
1938 | ||
487cf647 FG |
1939 | let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self; |
1940 | let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = other; | |
064997fb FG |
1941 | lhs_def_id == rhs_def_id |
1942 | } | |
1943 | } | |
1944 | ||
1945 | impl Eq for VariantDef {} | |
1946 | ||
1947 | impl Hash for VariantDef { | |
1948 | #[inline] | |
1949 | fn hash<H: Hasher>(&self, s: &mut H) { | |
1950 | // There should be only one `VariantDef` for each `def_id`, therefore | |
1951 | // it is fine to implement `Hash` only based on `def_id`. | |
1952 | // | |
1953 | // Below, we exhaustively destructure `self` so that if the definition | |
1954 | // of `VariantDef` changes, a compile-error will be produced, reminding | |
1955 | // us to revisit this assumption. | |
1956 | ||
487cf647 | 1957 | let Self { def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self; |
064997fb FG |
1958 | def_id.hash(s) |
1959 | } | |
1960 | } | |
1961 | ||
3dfed10e | 1962 | #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] |
8bb4bdeb | 1963 | pub enum VariantDiscr { |
0731742a | 1964 | /// Explicit value for this variant, i.e., `X = 123`. |
8bb4bdeb XL |
1965 | /// The `DefId` corresponds to the embedded constant. |
1966 | Explicit(DefId), | |
1967 | ||
1968 | /// The previous variant's discriminant plus one. | |
1969 | /// For efficiency reasons, the distance from the | |
1970 | /// last `Explicit` discriminant is being stored, | |
1971 | /// or `0` for the first variant, if it has none. | |
a1dfa0c6 | 1972 | Relative(u32), |
8bb4bdeb XL |
1973 | } |
1974 | ||
a2a8927a | 1975 | #[derive(Debug, HashStable, TyEncodable, TyDecodable)] |
476ff2be | 1976 | pub struct FieldDef { |
e9174d1e | 1977 | pub did: DefId, |
5099ac24 | 1978 | pub name: Symbol, |
f2b60f7d | 1979 | pub vis: Visibility<DefId>, |
e9174d1e SL |
1980 | } |
1981 | ||
064997fb FG |
1982 | impl PartialEq for FieldDef { |
1983 | #[inline] | |
1984 | fn eq(&self, other: &Self) -> bool { | |
1985 | // There should be only one `FieldDef` for each `did`, therefore it is | |
1986 | // fine to implement `PartialEq` only based on `did`. | |
1987 | // | |
1988 | // Below, we exhaustively destructure `self` so that if the definition | |
1989 | // of `FieldDef` changes, a compile-error will be produced, reminding | |
1990 | // us to revisit this assumption. | |
1991 | ||
1992 | let Self { did: lhs_did, name: _, vis: _ } = &self; | |
1993 | ||
1994 | let Self { did: rhs_did, name: _, vis: _ } = other; | |
1995 | ||
1996 | lhs_did == rhs_did | |
1997 | } | |
1998 | } | |
1999 | ||
2000 | impl Eq for FieldDef {} | |
2001 | ||
2002 | impl Hash for FieldDef { | |
2003 | #[inline] | |
2004 | fn hash<H: Hasher>(&self, s: &mut H) { | |
2005 | // There should be only one `FieldDef` for each `did`, therefore it is | |
2006 | // fine to implement `Hash` only based on `did`. | |
2007 | // | |
2008 | // Below, we exhaustively destructure `self` so that if the definition | |
2009 | // of `FieldDef` changes, a compile-error will be produced, reminding | |
2010 | // us to revisit this assumption. | |
2011 | ||
2012 | let Self { did, name: _, vis: _ } = &self; | |
2013 | ||
2014 | did.hash(s) | |
2015 | } | |
2016 | } | |
2017 | ||
dc9dc135 | 2018 | impl<'tcx> FieldDef { |
c295e0f8 | 2019 | /// Returns the type of this field. The resulting type is not normalized. The `subst` is |
a2a8927a | 2020 | /// typically obtained via the second field of [`TyKind::Adt`]. |
dc9dc135 | 2021 | pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> { |
9ffffee4 | 2022 | tcx.type_of(self.did).subst(tcx, subst) |
e9174d1e | 2023 | } |
5099ac24 FG |
2024 | |
2025 | /// Computes the `Ident` of this variant by looking up the `Span` | |
2026 | pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { | |
2027 | Ident::new(self.name, tcx.def_ident_span(self.did).unwrap()) | |
2028 | } | |
e9174d1e SL |
2029 | } |
2030 | ||
04454e1e | 2031 | pub type Attributes<'tcx> = impl Iterator<Item = &'tcx ast::Attribute>; |
0731742a XL |
2032 | #[derive(Debug, PartialEq, Eq)] |
2033 | pub enum ImplOverlapKind { | |
2034 | /// These impls are always allowed to overlap. | |
dfeec247 | 2035 | Permitted { |
74b04a01 | 2036 | /// Whether or not the impl is permitted due to the trait being a `#[marker]` trait |
dfeec247 XL |
2037 | marker: bool, |
2038 | }, | |
0731742a XL |
2039 | /// These impls are allowed to overlap, but that raises |
2040 | /// an issue #33140 future-compatibility warning. | |
2041 | /// | |
2042 | /// Some background: in Rust 1.0, the trait-object types `Send + Sync` (today's | |
2043 | /// `dyn Send + Sync`) and `Sync + Send` (now `dyn Sync + Send`) were different. | |
2044 | /// | |
2045 | /// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied | |
2046 | /// that difference, making what reduces to the following set of impls: | |
2047 | /// | |
04454e1e | 2048 | /// ```compile_fail,(E0119) |
0731742a XL |
2049 | /// trait Trait {} |
2050 | /// impl Trait for dyn Send + Sync {} | |
2051 | /// impl Trait for dyn Sync + Send {} | |
2052 | /// ``` | |
2053 | /// | |
2054 | /// Obviously, once we made these types be identical, that code causes a coherence | |
2055 | /// error and a fairly big headache for us. However, luckily for us, the trait | |
2056 | /// `Trait` used in this case is basically a marker trait, and therefore having | |
2057 | /// overlapping impls for it is sound. | |
2058 | /// | |
2059 | /// To handle this, we basically regard the trait as a marker trait, with an additional | |
2060 | /// future-compatibility warning. To avoid accidentally "stabilizing" this feature, | |
2061 | /// it has the following restrictions: | |
2062 | /// | |
2063 | /// 1. The trait must indeed be a marker-like trait (i.e., no items), and must be | |
2064 | /// positive impls. | |
2065 | /// 2. The trait-ref of both impls must be equal. | |
2066 | /// 3. The trait-ref of both impls must be a trait object type consisting only of | |
2067 | /// marker traits. | |
2068 | /// 4. Neither of the impls can have any where-clauses. | |
2069 | /// | |
2070 | /// Once `traitobject` 0.1.0 is no longer an active concern, this hack can be removed. | |
dfeec247 | 2071 | Issue33140, |
0731742a XL |
2072 | } |
2073 | ||
9ffffee4 FG |
2074 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] |
2075 | pub enum ImplTraitInTraitData { | |
2076 | Trait { fn_def_id: DefId, opaque_def_id: DefId }, | |
2077 | Impl { fn_def_id: DefId }, | |
2078 | } | |
2079 | ||
dc9dc135 | 2080 | impl<'tcx> TyCtxt<'tcx> { |
3dfed10e XL |
2081 | pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> { |
2082 | self.typeck(self.hir().body_owner_def_id(body)) | |
32a655c1 SL |
2083 | } |
2084 | ||
74b04a01 | 2085 | pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'tcx AssocItem> { |
476ff2be | 2086 | self.associated_items(id) |
74b04a01 | 2087 | .in_definition_order() |
064997fb | 2088 | .filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value()) |
e9174d1e SL |
2089 | } |
2090 | ||
487cf647 FG |
2091 | pub fn repr_options_of_def(self, did: DefId) -> ReprOptions { |
2092 | let mut flags = ReprFlags::empty(); | |
2093 | let mut size = None; | |
2094 | let mut max_align: Option<Align> = None; | |
2095 | let mut min_pack: Option<Align> = None; | |
2096 | ||
2097 | // Generate a deterministically-derived seed from the item's path hash | |
2098 | // to allow for cross-crate compilation to actually work | |
2099 | let mut field_shuffle_seed = self.def_path_hash(did).0.to_smaller_hash(); | |
2100 | ||
2101 | // If the user defined a custom seed for layout randomization, xor the item's | |
2102 | // path hash with the user defined seed, this will allowing determinism while | |
2103 | // still allowing users to further randomize layout generation for e.g. fuzzing | |
2104 | if let Some(user_seed) = self.sess.opts.unstable_opts.layout_seed { | |
2105 | field_shuffle_seed ^= user_seed; | |
2106 | } | |
2107 | ||
2108 | for attr in self.get_attrs(did, sym::repr) { | |
2109 | for r in attr::parse_repr_attr(&self.sess, attr) { | |
2110 | flags.insert(match r { | |
2111 | attr::ReprC => ReprFlags::IS_C, | |
2112 | attr::ReprPacked(pack) => { | |
2113 | let pack = Align::from_bytes(pack as u64).unwrap(); | |
2114 | min_pack = Some(if let Some(min_pack) = min_pack { | |
2115 | min_pack.min(pack) | |
2116 | } else { | |
2117 | pack | |
2118 | }); | |
2119 | ReprFlags::empty() | |
2120 | } | |
2121 | attr::ReprTransparent => ReprFlags::IS_TRANSPARENT, | |
2122 | attr::ReprSimd => ReprFlags::IS_SIMD, | |
2123 | attr::ReprInt(i) => { | |
2124 | size = Some(match i { | |
2125 | attr::IntType::SignedInt(x) => match x { | |
2126 | ast::IntTy::Isize => IntegerType::Pointer(true), | |
2127 | ast::IntTy::I8 => IntegerType::Fixed(Integer::I8, true), | |
2128 | ast::IntTy::I16 => IntegerType::Fixed(Integer::I16, true), | |
2129 | ast::IntTy::I32 => IntegerType::Fixed(Integer::I32, true), | |
2130 | ast::IntTy::I64 => IntegerType::Fixed(Integer::I64, true), | |
2131 | ast::IntTy::I128 => IntegerType::Fixed(Integer::I128, true), | |
2132 | }, | |
2133 | attr::IntType::UnsignedInt(x) => match x { | |
2134 | ast::UintTy::Usize => IntegerType::Pointer(false), | |
2135 | ast::UintTy::U8 => IntegerType::Fixed(Integer::I8, false), | |
2136 | ast::UintTy::U16 => IntegerType::Fixed(Integer::I16, false), | |
2137 | ast::UintTy::U32 => IntegerType::Fixed(Integer::I32, false), | |
2138 | ast::UintTy::U64 => IntegerType::Fixed(Integer::I64, false), | |
2139 | ast::UintTy::U128 => IntegerType::Fixed(Integer::I128, false), | |
2140 | }, | |
2141 | }); | |
2142 | ReprFlags::empty() | |
2143 | } | |
2144 | attr::ReprAlign(align) => { | |
2145 | max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap())); | |
2146 | ReprFlags::empty() | |
2147 | } | |
2148 | }); | |
2149 | } | |
2150 | } | |
2151 | ||
2152 | // If `-Z randomize-layout` was enabled for the type definition then we can | |
2153 | // consider performing layout randomization | |
2154 | if self.sess.opts.unstable_opts.randomize_layout { | |
2155 | flags.insert(ReprFlags::RANDOMIZE_LAYOUT); | |
2156 | } | |
2157 | ||
2158 | // This is here instead of layout because the choice must make it into metadata. | |
2159 | if !self.consider_optimizing(|| format!("Reorder fields of {:?}", self.def_path_str(did))) { | |
2160 | flags.insert(ReprFlags::IS_LINEAR); | |
2161 | } | |
2162 | ||
2163 | ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed } | |
2164 | } | |
2165 | ||
04454e1e | 2166 | /// Look up the name of a definition across crates. This does not look at HIR. |
923072b8 | 2167 | pub fn opt_item_name(self, def_id: DefId) -> Option<Symbol> { |
04454e1e FG |
2168 | if let Some(cnum) = def_id.as_crate_root() { |
2169 | Some(self.crate_name(cnum)) | |
29967ef6 XL |
2170 | } else { |
2171 | let def_key = self.def_key(def_id); | |
2172 | match def_key.disambiguated_data.data { | |
2173 | // The name of a constructor is that of its parent. | |
04454e1e FG |
2174 | rustc_hir::definitions::DefPathData::Ctor => self |
2175 | .opt_item_name(DefId { krate: def_id.krate, index: def_key.parent.unwrap() }), | |
2176 | // The name of opaque types only exists in HIR. | |
2177 | rustc_hir::definitions::DefPathData::ImplTrait | |
2178 | if let Some(def_id) = def_id.as_local() => | |
2179 | self.hir().opt_name(self.hir().local_def_id_to_hir_id(def_id)), | |
2180 | _ => def_key.get_opt_name(), | |
29967ef6 XL |
2181 | } |
2182 | } | |
2183 | } | |
2184 | ||
04454e1e | 2185 | /// Look up the name of a definition across crates. This does not look at HIR. |
29967ef6 | 2186 | /// |
9c376795 | 2187 | /// This method will ICE if the corresponding item does not have a name. In these cases, use |
29967ef6 XL |
2188 | /// [`opt_item_name`] instead. |
2189 | /// | |
2190 | /// [`opt_item_name`]: Self::opt_item_name | |
2191 | pub fn item_name(self, id: DefId) -> Symbol { | |
04454e1e | 2192 | self.opt_item_name(id).unwrap_or_else(|| { |
29967ef6 XL |
2193 | bug!("item_name: no name for {:?}", self.def_path(id)); |
2194 | }) | |
2195 | } | |
2196 | ||
04454e1e | 2197 | /// Look up the name and span of a definition. |
29967ef6 XL |
2198 | /// |
2199 | /// See [`item_name`][Self::item_name] for more information. | |
04454e1e FG |
2200 | pub fn opt_item_ident(self, def_id: DefId) -> Option<Ident> { |
2201 | let def = self.opt_item_name(def_id)?; | |
2202 | let span = def_id | |
2203 | .as_local() | |
2204 | .and_then(|id| self.def_ident_span(id)) | |
2205 | .unwrap_or(rustc_span::DUMMY_SP); | |
2206 | Some(Ident::new(def, span)) | |
e1599b0c XL |
2207 | } |
2208 | ||
9ffffee4 | 2209 | pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> { |
5869c6ff XL |
2210 | if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { |
2211 | Some(self.associated_item(def_id)) | |
7cac9316 | 2212 | } else { |
5869c6ff XL |
2213 | None |
2214 | } | |
e9174d1e SL |
2215 | } |
2216 | ||
83c7162d | 2217 | pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> { |
5099ac24 FG |
2218 | variant |
2219 | .fields | |
2220 | .iter() | |
2221 | .position(|field| self.hygienic_eq(ident, field.ident(self), variant.def_id)) | |
83c7162d XL |
2222 | } |
2223 | ||
a1dfa0c6 | 2224 | /// Returns `true` if the impls are the same polarity and the trait either |
f9f354fc | 2225 | /// has no items or is annotated `#[marker]` and prevents item overrides. |
dfeec247 XL |
2226 | pub fn impls_are_allowed_to_overlap( |
2227 | self, | |
2228 | def_id1: DefId, | |
2229 | def_id2: DefId, | |
2230 | ) -> Option<ImplOverlapKind> { | |
e1599b0c XL |
2231 | // If either trait impl references an error, they're allowed to overlap, |
2232 | // as one of them essentially doesn't exist. | |
9c376795 FG |
2233 | if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.subst_identity().references_error()) |
2234 | || self | |
2235 | .impl_trait_ref(def_id2) | |
2236 | .map_or(false, |tr| tr.subst_identity().references_error()) | |
dfeec247 XL |
2237 | { |
2238 | return Some(ImplOverlapKind::Permitted { marker: false }); | |
e1599b0c XL |
2239 | } |
2240 | ||
e74abb32 | 2241 | match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) { |
dfeec247 | 2242 | (ImplPolarity::Reservation, _) | (_, ImplPolarity::Reservation) => { |
e74abb32 | 2243 | // `#[rustc_reservation_impl]` impls don't overlap with anything |
dfeec247 XL |
2244 | debug!( |
2245 | "impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (reservations)", | |
2246 | def_id1, def_id2 | |
2247 | ); | |
2248 | return Some(ImplOverlapKind::Permitted { marker: false }); | |
e74abb32 | 2249 | } |
dfeec247 XL |
2250 | (ImplPolarity::Positive, ImplPolarity::Negative) |
2251 | | (ImplPolarity::Negative, ImplPolarity::Positive) => { | |
e74abb32 | 2252 | // `impl AutoTrait for Type` + `impl !AutoTrait for Type` |
dfeec247 XL |
2253 | debug!( |
2254 | "impls_are_allowed_to_overlap({:?}, {:?}) - None (differing polarities)", | |
2255 | def_id1, def_id2 | |
2256 | ); | |
e74abb32 XL |
2257 | return None; |
2258 | } | |
dfeec247 XL |
2259 | (ImplPolarity::Positive, ImplPolarity::Positive) |
2260 | | (ImplPolarity::Negative, ImplPolarity::Negative) => {} | |
e74abb32 XL |
2261 | }; |
2262 | ||
74b04a01 | 2263 | let is_marker_overlap = { |
0bf4aa26 XL |
2264 | let is_marker_impl = |def_id: DefId| -> bool { |
2265 | let trait_ref = self.impl_trait_ref(def_id); | |
9c376795 | 2266 | trait_ref.map_or(false, |tr| self.trait_def(tr.skip_binder().def_id).is_marker) |
0bf4aa26 | 2267 | }; |
e74abb32 | 2268 | is_marker_impl(def_id1) && is_marker_impl(def_id2) |
0731742a XL |
2269 | }; |
2270 | ||
e74abb32 | 2271 | if is_marker_overlap { |
dfeec247 XL |
2272 | debug!( |
2273 | "impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (marker overlap)", | |
2274 | def_id1, def_id2 | |
2275 | ); | |
2276 | Some(ImplOverlapKind::Permitted { marker: true }) | |
0bf4aa26 | 2277 | } else { |
0731742a XL |
2278 | if let Some(self_ty1) = self.issue33140_self_ty(def_id1) { |
2279 | if let Some(self_ty2) = self.issue33140_self_ty(def_id2) { | |
2280 | if self_ty1 == self_ty2 { | |
dfeec247 XL |
2281 | debug!( |
2282 | "impls_are_allowed_to_overlap({:?}, {:?}) - issue #33140 HACK", | |
2283 | def_id1, def_id2 | |
2284 | ); | |
0731742a XL |
2285 | return Some(ImplOverlapKind::Issue33140); |
2286 | } else { | |
dfeec247 XL |
2287 | debug!( |
2288 | "impls_are_allowed_to_overlap({:?}, {:?}) - found {:?} != {:?}", | |
2289 | def_id1, def_id2, self_ty1, self_ty2 | |
2290 | ); | |
0731742a XL |
2291 | } |
2292 | } | |
2293 | } | |
2294 | ||
dfeec247 | 2295 | debug!("impls_are_allowed_to_overlap({:?}, {:?}) = None", def_id1, def_id2); |
0731742a | 2296 | None |
cc61c64b | 2297 | } |
cc61c64b XL |
2298 | } |
2299 | ||
48663c56 | 2300 | /// Returns `ty::VariantDef` if `res` refers to a struct, |
532ac7d7 | 2301 | /// or variant or their constructors, panics otherwise. |
48663c56 XL |
2302 | pub fn expect_variant_res(self, res: Res) -> &'tcx VariantDef { |
2303 | match res { | |
2304 | Res::Def(DefKind::Variant, did) => { | |
04454e1e | 2305 | let enum_did = self.parent(did); |
7cac9316 | 2306 | self.adt_def(enum_did).variant_with_id(did) |
5bcae85e | 2307 | } |
ba9703b0 | 2308 | Res::Def(DefKind::Struct | DefKind::Union, did) => self.adt_def(did).non_enum_variant(), |
48663c56 | 2309 | Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_did) => { |
04454e1e FG |
2310 | let variant_did = self.parent(variant_ctor_did); |
2311 | let enum_did = self.parent(variant_did); | |
532ac7d7 XL |
2312 | self.adt_def(enum_did).variant_with_ctor_id(variant_ctor_did) |
2313 | } | |
48663c56 | 2314 | Res::Def(DefKind::Ctor(CtorOf::Struct, ..), ctor_did) => { |
04454e1e | 2315 | let struct_did = self.parent(ctor_did); |
532ac7d7 | 2316 | self.adt_def(struct_did).non_enum_variant() |
c30ab7b3 | 2317 | } |
dfeec247 | 2318 | _ => bug!("expect_variant_res used with unexpected res {:?}", res), |
5bcae85e SL |
2319 | } |
2320 | } | |
2321 | ||
9fa01778 | 2322 | /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair. |
923072b8 | 2323 | #[instrument(skip(self), level = "debug")] |
f9f354fc | 2324 | pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> { |
cc61c64b | 2325 | match instance { |
923072b8 FG |
2326 | ty::InstanceDef::Item(def) => { |
2327 | debug!("calling def_kind on def: {:?}", def); | |
2328 | let def_kind = self.def_kind(def.did); | |
2329 | debug!("returned from def_kind: {:?}", def_kind); | |
2330 | match def_kind { | |
2331 | DefKind::Const | |
2332 | | DefKind::Static(..) | |
2333 | | DefKind::AssocConst | |
2334 | | DefKind::Ctor(..) | |
2335 | | DefKind::AnonConst | |
2336 | | DefKind::InlineConst => self.mir_for_ctfe_opt_const_arg(def), | |
2337 | // If the caller wants `mir_for_ctfe` of a function they should not be using | |
2338 | // `instance_mir`, so we'll assume const fn also wants the optimized version. | |
2339 | _ => { | |
2340 | assert_eq!(def.const_param_did, None); | |
2341 | self.optimized_mir(def.did) | |
2342 | } | |
6a06907d | 2343 | } |
923072b8 | 2344 | } |
064997fb | 2345 | ty::InstanceDef::VTableShim(..) |
dfeec247 XL |
2346 | | ty::InstanceDef::ReifyShim(..) |
2347 | | ty::InstanceDef::Intrinsic(..) | |
2348 | | ty::InstanceDef::FnPtrShim(..) | |
2349 | | ty::InstanceDef::Virtual(..) | |
2350 | | ty::InstanceDef::ClosureOnceShim { .. } | |
2351 | | ty::InstanceDef::DropGlue(..) | |
f9f354fc | 2352 | | ty::InstanceDef::CloneShim(..) => self.mir_shims(instance), |
cc61c64b XL |
2353 | } |
2354 | } | |
2355 | ||
04454e1e FG |
2356 | // FIXME(@lcnr): Remove this function. |
2357 | pub fn get_attrs_unchecked(self, did: DefId) -> &'tcx [ast::Attribute] { | |
f9f354fc | 2358 | if let Some(did) = did.as_local() { |
3dfed10e | 2359 | self.hir().attrs(self.hir().local_def_id_to_hir_id(did)) |
e9174d1e | 2360 | } else { |
ba9703b0 | 2361 | self.item_attrs(did) |
e9174d1e SL |
2362 | } |
2363 | } | |
2364 | ||
04454e1e FG |
2365 | /// Gets all attributes with the given name. |
2366 | pub fn get_attrs(self, did: DefId, attr: Symbol) -> ty::Attributes<'tcx> { | |
2367 | let filter_fn = move |a: &&ast::Attribute| a.has_name(attr); | |
2368 | if let Some(did) = did.as_local() { | |
2369 | self.hir().attrs(self.hir().local_def_id_to_hir_id(did)).iter().filter(filter_fn) | |
2370 | } else if cfg!(debug_assertions) && rustc_feature::is_builtin_only_local(attr) { | |
2371 | bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr); | |
2372 | } else { | |
2373 | self.item_attrs(did).iter().filter(filter_fn) | |
2374 | } | |
2375 | } | |
2376 | ||
2377 | pub fn get_attr(self, did: DefId, attr: Symbol) -> Option<&'tcx ast::Attribute> { | |
f2b60f7d FG |
2378 | if cfg!(debug_assertions) && !rustc_feature::is_valid_for_get_attr(attr) { |
2379 | bug!("get_attr: unexpected called with DefId `{:?}`, attr `{:?}`", did, attr); | |
2380 | } else { | |
2381 | self.get_attrs(did, attr).next() | |
2382 | } | |
04454e1e FG |
2383 | } |
2384 | ||
9fa01778 | 2385 | /// Determines whether an item is annotated with an attribute. |
48663c56 | 2386 | pub fn has_attr(self, did: DefId, attr: Symbol) -> bool { |
04454e1e FG |
2387 | if cfg!(debug_assertions) && !did.is_local() && rustc_feature::is_builtin_only_local(attr) { |
2388 | bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr); | |
2389 | } else { | |
2390 | self.get_attrs(did, attr).next().is_some() | |
2391 | } | |
e9174d1e SL |
2392 | } |
2393 | ||
a1dfa0c6 | 2394 | /// Returns `true` if this is an `auto trait`. |
abe05a73 XL |
2395 | pub fn trait_is_auto(self, trait_def_id: DefId) -> bool { |
2396 | self.trait_def(trait_def_id).has_auto_impl | |
b039eaaf SL |
2397 | } |
2398 | ||
9ffffee4 FG |
2399 | /// Returns `true` if this is coinductive, either because it is |
2400 | /// an auto trait or because it has the `#[rustc_coinductive]` attribute. | |
2401 | pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool { | |
2402 | self.trait_def(trait_def_id).is_coinductive | |
2403 | } | |
2404 | ||
9c376795 FG |
2405 | /// Returns `true` if this is a trait alias. |
2406 | pub fn trait_is_alias(self, trait_def_id: DefId) -> bool { | |
2407 | self.def_kind(trait_def_id) == DefKind::TraitAlias | |
2408 | } | |
2409 | ||
5869c6ff XL |
2410 | /// Returns layout of a generator. Layout might be unavailable if the |
2411 | /// generator is tainted by errors. | |
2412 | pub fn generator_layout(self, def_id: DefId) -> Option<&'tcx GeneratorLayout<'tcx>> { | |
6a06907d | 2413 | self.optimized_mir(def_id).generator_layout() |
ea8adc8c XL |
2414 | } |
2415 | ||
9fa01778 XL |
2416 | /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. |
2417 | /// If it implements no trait, returns `None`. | |
a7813a04 | 2418 | pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> { |
9c376795 | 2419 | self.impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id) |
e9174d1e SL |
2420 | } |
2421 | ||
064997fb FG |
2422 | /// If the given `DefId` describes an item belonging to a trait, |
2423 | /// returns the `DefId` of the trait that the trait item belongs to; | |
2424 | /// otherwise, returns `None`. | |
2425 | pub fn trait_of_item(self, def_id: DefId) -> Option<DefId> { | |
2426 | if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { | |
2427 | let parent = self.parent(def_id); | |
2428 | if let DefKind::Trait | DefKind::TraitAlias = self.def_kind(parent) { | |
2429 | return Some(parent); | |
2430 | } | |
2431 | } | |
2432 | None | |
2433 | } | |
2434 | ||
04454e1e | 2435 | /// If the given `DefId` describes a method belonging to an impl, returns the |
9fa01778 | 2436 | /// `DefId` of the impl that the method belongs to; otherwise, returns `None`. |
a7813a04 | 2437 | pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> { |
064997fb FG |
2438 | if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { |
2439 | let parent = self.parent(def_id); | |
9ffffee4 | 2440 | if let DefKind::Impl { .. } = self.def_kind(parent) { |
064997fb FG |
2441 | return Some(parent); |
2442 | } | |
2443 | } | |
2444 | None | |
e9174d1e SL |
2445 | } |
2446 | ||
9ffffee4 FG |
2447 | /// Check if the given `DefId` is `#\[automatically_derived\]`, *and* |
2448 | /// whether it was produced by expanding a builtin derive macro. | |
2449 | pub fn is_builtin_derived(self, def_id: DefId) -> bool { | |
2450 | if self.is_automatically_derived(def_id) | |
2451 | && let Some(def_id) = def_id.as_local() | |
2452 | && let outer = self.def_span(def_id).ctxt().outer_expn_data() | |
2453 | && matches!(outer.kind, ExpnKind::Macro(MacroKind::Derive, _)) | |
2454 | && self.has_attr(outer.macro_def_id.unwrap(), sym::rustc_builtin_macro) | |
2455 | { | |
2456 | true | |
2457 | } else { | |
2458 | false | |
2459 | } | |
2460 | } | |
2461 | ||
2462 | /// Check if the given `DefId` is `#\[automatically_derived\]`. | |
2463 | pub fn is_automatically_derived(self, def_id: DefId) -> bool { | |
04454e1e FG |
2464 | self.has_attr(def_id, sym::automatically_derived) |
2465 | } | |
2466 | ||
54a0048b SL |
2467 | /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err` |
2468 | /// with the name of the crate containing the impl. | |
487cf647 FG |
2469 | pub fn span_of_impl(self, impl_def_id: DefId) -> Result<Span, Symbol> { |
2470 | if let Some(impl_def_id) = impl_def_id.as_local() { | |
2471 | Ok(self.def_span(impl_def_id)) | |
54a0048b | 2472 | } else { |
487cf647 | 2473 | Err(self.crate_name(impl_def_id.krate)) |
54a0048b SL |
2474 | } |
2475 | } | |
7cac9316 | 2476 | |
9fa01778 XL |
2477 | /// Hygienically compares a use-site name (`use_name`) for a field or an associated item with |
2478 | /// its supposed definition name (`def_name`). The method also needs `DefId` of the supposed | |
2479 | /// definition's parent/scope to perform comparison. | |
8faf50e0 | 2480 | pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool { |
dc9dc135 XL |
2481 | // We could use `Ident::eq` here, but we deliberately don't. The name |
2482 | // comparison fails frequently, and we want to avoid the expensive | |
ba9703b0 | 2483 | // `normalize_to_macros_2_0()` calls required for the span comparison whenever possible. |
dfeec247 XL |
2484 | use_name.name == def_name.name |
2485 | && use_name | |
2486 | .span | |
2487 | .ctxt() | |
17df50a5 | 2488 | .hygienic_eq(def_name.span.ctxt(), self.expn_that_defined(def_parent_def_id)) |
dc9dc135 XL |
2489 | } |
2490 | ||
2491 | pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident { | |
17df50a5 | 2492 | ident.span.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)); |
dc9dc135 XL |
2493 | ident |
2494 | } | |
2495 | ||
9ffffee4 | 2496 | // FIXME(vincenzoapalzzo): move the HirId to a LocalDefId |
dfeec247 XL |
2497 | pub fn adjust_ident_and_get_scope( |
2498 | self, | |
2499 | mut ident: Ident, | |
2500 | scope: DefId, | |
2501 | block: hir::HirId, | |
2502 | ) -> (Ident, DefId) { | |
136023e0 XL |
2503 | let scope = ident |
2504 | .span | |
2505 | .normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)) | |
2506 | .and_then(|actual_expansion| actual_expansion.expn_data().parent_module) | |
2507 | .unwrap_or_else(|| self.parent_module(block).to_def_id()); | |
7cac9316 XL |
2508 | (ident, scope) |
2509 | } | |
a1dfa0c6 | 2510 | |
f2b60f7d FG |
2511 | /// Returns `true` if the debuginfo for `span` should be collapsed to the outermost expansion |
2512 | /// site. Only applies when `Span` is the result of macro expansion. | |
2513 | /// | |
2514 | /// - If the `collapse_debuginfo` feature is enabled then debuginfo is not collapsed by default | |
2515 | /// and only when a macro definition is annotated with `#[collapse_debuginfo]`. | |
2516 | /// - If `collapse_debuginfo` is not enabled, then debuginfo is collapsed by default. | |
2517 | /// | |
2518 | /// When `-Zdebug-macros` is provided then debuginfo will never be collapsed. | |
2519 | pub fn should_collapse_debuginfo(self, span: Span) -> bool { | |
2520 | !self.sess.opts.unstable_opts.debug_macros | |
2521 | && if self.features().collapse_debuginfo { | |
2522 | span.in_macro_expansion_with_collapse_debuginfo() | |
2523 | } else { | |
2524 | // Inlined spans should not be collapsed as that leads to all of the | |
2525 | // inlined code being attributed to the inline callsite. | |
2526 | span.from_expansion() && !span.is_inlined() | |
2527 | } | |
2528 | } | |
2529 | ||
5e7ed085 FG |
2530 | #[inline] |
2531 | pub fn is_const_fn_raw(self, def_id: DefId) -> bool { | |
9c376795 FG |
2532 | matches!( |
2533 | self.def_kind(def_id), | |
2534 | DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure | |
2535 | ) && self.constness(def_id) == hir::Constness::Const | |
923072b8 FG |
2536 | } |
2537 | ||
2538 | #[inline] | |
2539 | pub fn is_const_default_method(self, def_id: DefId) -> bool { | |
2540 | matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait)) | |
5e7ed085 | 2541 | } |
f2b60f7d FG |
2542 | |
2543 | pub fn impl_trait_in_trait_parent(self, mut def_id: DefId) -> DefId { | |
2544 | while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn { | |
2545 | debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder); | |
2546 | def_id = self.parent(def_id); | |
2547 | } | |
2548 | def_id | |
2549 | } | |
9ffffee4 FG |
2550 | |
2551 | pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool { | |
2552 | if self.def_kind(def_id) != DefKind::AssocFn { | |
2553 | return false; | |
2554 | } | |
2555 | ||
2556 | let Some(item) = self.opt_associated_item(def_id) else { return false; }; | |
2557 | if item.container != ty::AssocItemContainer::ImplContainer { | |
2558 | return false; | |
2559 | } | |
2560 | ||
2561 | let Some(trait_item_def_id) = item.trait_item_def_id else { return false; }; | |
2562 | ||
2563 | // FIXME(RPITIT): This does a somewhat manual walk through the signature | |
2564 | // of the trait fn to look for any RPITITs, but that's kinda doing a lot | |
2565 | // of work. We can probably remove this when we refactor RPITITs to be | |
2566 | // associated types. | |
2567 | self.fn_sig(trait_item_def_id).subst_identity().skip_binder().output().walk().any(|arg| { | |
2568 | if let ty::GenericArgKind::Type(ty) = arg.unpack() | |
2569 | && let ty::Alias(ty::Projection, data) = ty.kind() | |
2570 | && self.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder | |
2571 | { | |
2572 | true | |
2573 | } else { | |
2574 | false | |
2575 | } | |
2576 | }) | |
2577 | } | |
a1dfa0c6 XL |
2578 | } |
2579 | ||
a2a8927a XL |
2580 | /// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition. |
2581 | pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<LocalDefId> { | |
2582 | let def_id = def_id.as_local()?; | |
5099ac24 | 2583 | if let Node::Item(item) = tcx.hir().get_by_def_id(def_id) { |
a2a8927a XL |
2584 | if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { |
2585 | return match opaque_ty.origin { | |
2586 | hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => { | |
2587 | Some(parent) | |
2588 | } | |
2589 | hir::OpaqueTyOrigin::TyAlias => None, | |
2590 | }; | |
8faf50e0 XL |
2591 | } |
2592 | } | |
2593 | None | |
2594 | } | |
2595 | ||
5869c6ff XL |
2596 | pub fn int_ty(ity: ast::IntTy) -> IntTy { |
2597 | match ity { | |
2598 | ast::IntTy::Isize => IntTy::Isize, | |
2599 | ast::IntTy::I8 => IntTy::I8, | |
2600 | ast::IntTy::I16 => IntTy::I16, | |
2601 | ast::IntTy::I32 => IntTy::I32, | |
2602 | ast::IntTy::I64 => IntTy::I64, | |
2603 | ast::IntTy::I128 => IntTy::I128, | |
2604 | } | |
2605 | } | |
2606 | ||
2607 | pub fn uint_ty(uty: ast::UintTy) -> UintTy { | |
2608 | match uty { | |
2609 | ast::UintTy::Usize => UintTy::Usize, | |
2610 | ast::UintTy::U8 => UintTy::U8, | |
2611 | ast::UintTy::U16 => UintTy::U16, | |
2612 | ast::UintTy::U32 => UintTy::U32, | |
2613 | ast::UintTy::U64 => UintTy::U64, | |
2614 | ast::UintTy::U128 => UintTy::U128, | |
2615 | } | |
2616 | } | |
2617 | ||
2618 | pub fn float_ty(fty: ast::FloatTy) -> FloatTy { | |
2619 | match fty { | |
2620 | ast::FloatTy::F32 => FloatTy::F32, | |
2621 | ast::FloatTy::F64 => FloatTy::F64, | |
2622 | } | |
2623 | } | |
2624 | ||
2625 | pub fn ast_int_ty(ity: IntTy) -> ast::IntTy { | |
2626 | match ity { | |
2627 | IntTy::Isize => ast::IntTy::Isize, | |
2628 | IntTy::I8 => ast::IntTy::I8, | |
2629 | IntTy::I16 => ast::IntTy::I16, | |
2630 | IntTy::I32 => ast::IntTy::I32, | |
2631 | IntTy::I64 => ast::IntTy::I64, | |
2632 | IntTy::I128 => ast::IntTy::I128, | |
2633 | } | |
2634 | } | |
2635 | ||
2636 | pub fn ast_uint_ty(uty: UintTy) -> ast::UintTy { | |
2637 | match uty { | |
2638 | UintTy::Usize => ast::UintTy::Usize, | |
2639 | UintTy::U8 => ast::UintTy::U8, | |
2640 | UintTy::U16 => ast::UintTy::U16, | |
2641 | UintTy::U32 => ast::UintTy::U32, | |
2642 | UintTy::U64 => ast::UintTy::U64, | |
2643 | UintTy::U128 => ast::UintTy::U128, | |
2644 | } | |
2645 | } | |
2646 | ||
f035d41b | 2647 | pub fn provide(providers: &mut ty::query::Providers) { |
94222f64 | 2648 | closure::provide(providers); |
ea8adc8c | 2649 | context::provide(providers); |
abe05a73 | 2650 | erase_regions::provide(providers); |
2b03887a | 2651 | inhabitedness::provide(providers); |
3dfed10e | 2652 | util::provide(providers); |
1b1a35ee | 2653 | print::provide(providers); |
ba9703b0 | 2654 | super::util::bug::provide(providers); |
136023e0 | 2655 | super::middle::provide(providers); |
ba9703b0 XL |
2656 | *providers = ty::query::Providers { |
2657 | trait_impls_of: trait_def::trait_impls_of_provider, | |
5e7ed085 | 2658 | incoherent_impls: trait_def::incoherent_impls_provider, |
cdc7bbd5 | 2659 | const_param_default: consts::const_param_default, |
dc3f5686 | 2660 | vtable_allocation: vtable::vtable_allocation_provider, |
ba9703b0 XL |
2661 | ..*providers |
2662 | }; | |
cc61c64b XL |
2663 | } |
2664 | ||
cc61c64b XL |
2665 | /// A map for the local crate mapping each type to a vector of its |
2666 | /// inherent impls. This is not meant to be used outside of coherence; | |
2667 | /// rather, you should request the vector for a specific type via | |
7cac9316 XL |
2668 | /// `tcx.inherent_impls(def_id)` so as to minimize your dependencies |
2669 | /// (constructing this map requires touching the entire crate). | |
532ac7d7 | 2670 | #[derive(Clone, Debug, Default, HashStable)] |
cc61c64b | 2671 | pub struct CrateInherentImpls { |
17df50a5 | 2672 | pub inherent_impls: LocalDefIdMap<Vec<DefId>>, |
5e7ed085 | 2673 | pub incoherent_impls: FxHashMap<SimplifiedType, Vec<LocalDefId>>, |
cc61c64b XL |
2674 | } |
2675 | ||
3dfed10e XL |
2676 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)] |
2677 | pub struct SymbolName<'tcx> { | |
2678 | /// `&str` gives a consistent ordering, which ensures reproducible builds. | |
2679 | pub name: &'tcx str, | |
7cac9316 XL |
2680 | } |
2681 | ||
3dfed10e XL |
2682 | impl<'tcx> SymbolName<'tcx> { |
2683 | pub fn new(tcx: TyCtxt<'tcx>, name: &str) -> SymbolName<'tcx> { | |
2684 | SymbolName { | |
2685 | name: unsafe { str::from_utf8_unchecked(tcx.arena.alloc_slice(name.as_bytes())) }, | |
2686 | } | |
e74abb32 XL |
2687 | } |
2688 | } | |
2689 | ||
3dfed10e | 2690 | impl<'tcx> fmt::Display for SymbolName<'tcx> { |
0bf4aa26 | 2691 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
7cac9316 XL |
2692 | fmt::Display::fmt(&self.name, fmt) |
2693 | } | |
2694 | } | |
0531ce1d | 2695 | |
3dfed10e | 2696 | impl<'tcx> fmt::Debug for SymbolName<'tcx> { |
0bf4aa26 | 2697 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
0531ce1d XL |
2698 | fmt::Display::fmt(&self.name, fmt) |
2699 | } | |
2700 | } | |
c295e0f8 XL |
2701 | |
2702 | #[derive(Debug, Default, Copy, Clone)] | |
9ffffee4 | 2703 | pub struct InferVarInfo { |
c295e0f8 XL |
2704 | /// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo` |
2705 | /// obligation, where: | |
2706 | /// | |
2707 | /// * `Foo` is not `Sized` | |
2708 | /// * `(): Foo` may be satisfied | |
2709 | pub self_in_trait: bool, | |
2710 | /// This is true if we identified that this Ty (`?T`) is found in a `<_ as | |
2711 | /// _>::AssocType = ?T` | |
2712 | pub output: bool, | |
2713 | } | |
923072b8 FG |
2714 | |
2715 | /// The constituent parts of a type level constant of kind ADT or array. | |
2716 | #[derive(Copy, Clone, Debug, HashStable)] | |
2717 | pub struct DestructuredConst<'tcx> { | |
2718 | pub variant: Option<VariantIdx>, | |
2719 | pub fields: &'tcx [ty::Const<'tcx>], | |
2720 | } | |
f2b60f7d FG |
2721 | |
2722 | // Some types are used a lot. Make sure they don't unintentionally get bigger. | |
2723 | #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] | |
2724 | mod size_asserts { | |
2725 | use super::*; | |
2726 | use rustc_data_structures::static_assert_size; | |
2b03887a | 2727 | // tidy-alphabetical-start |
487cf647 FG |
2728 | static_assert_size!(PredicateKind<'_>, 32); |
2729 | static_assert_size!(WithCachedTypeInfo<TyKind<'_>>, 56); | |
2b03887a | 2730 | // tidy-alphabetical-end |
f2b60f7d | 2731 | } |