1 | //! Defines how the compiler represents types internally. |
---|---|
2 | //! |
3 | //! Two important entities in this module are: |
4 | //! |
5 | //! - [`rustc_middle::ty::Ty`], used to represent the semantics of a type. |
6 | //! - [`rustc_middle::ty::TyCtxt`], the central data structure in the compiler. |
7 | //! |
8 | //! For more information, see ["The `ty` module: representing types"] in the rustc-dev-guide. |
9 | //! |
10 | //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html |
11 | |
12 | #![allow(rustc::usage_of_ty_tykind)] |
13 | |
14 | use std::assert_matches::assert_matches; |
15 | use std::fmt::Debug; |
16 | use std::hash::{Hash, Hasher}; |
17 | use std::marker::PhantomData; |
18 | use std::num::NonZero; |
19 | use std::ptr::NonNull; |
20 | use std::{fmt, str}; |
21 | |
22 | pub use adt::*; |
23 | pub use assoc::*; |
24 | pub use generic_args::{GenericArgKind, TermKind, *}; |
25 | pub use generics::*; |
26 | pub use intrinsic::IntrinsicDef; |
27 | use rustc_abi::{Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, VariantIdx}; |
28 | use rustc_ast::expand::StrippedCfgItem; |
29 | use rustc_ast::node_id::NodeMap; |
30 | pub use rustc_ast_ir::{Movability, Mutability, try_visit}; |
31 | use rustc_attr_data_structures::AttributeKind; |
32 | use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; |
33 | use rustc_data_structures::intern::Interned; |
34 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; |
35 | use rustc_data_structures::steal::Steal; |
36 | use rustc_data_structures::unord::UnordMap; |
37 | use rustc_errors::{Diag, ErrorGuaranteed}; |
38 | use rustc_hir::LangItem; |
39 | use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; |
40 | use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; |
41 | use rustc_index::IndexVec; |
42 | use rustc_macros::{ |
43 | Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, |
44 | extension, |
45 | }; |
46 | use rustc_query_system::ich::StableHashingContext; |
47 | use rustc_serialize::{Decodable, Encodable}; |
48 | use rustc_session::lint::LintBuffer; |
49 | pub use rustc_session::lint::RegisteredTools; |
50 | use rustc_span::hygiene::MacroKind; |
51 | use rustc_span::{ExpnId, ExpnKind, Ident, Span, Symbol, kw, sym}; |
52 | pub use rustc_type_ir::relate::VarianceDiagInfo; |
53 | pub use rustc_type_ir::*; |
54 | use tracing::{debug, instrument}; |
55 | pub use vtable::*; |
56 | use {rustc_ast as ast, rustc_attr_data_structures as attr, rustc_hir as hir}; |
57 | |
58 | pub use self::closure::{ |
59 | BorrowKind, CAPTURE_STRUCT_LOCAL, CaptureInfo, CapturedPlace, ClosureTypeInfo, |
60 | MinCaptureInformationMap, MinCaptureList, RootVariableMinCaptureList, UpvarCapture, UpvarId, |
61 | UpvarPath, analyze_coroutine_closure_captures, is_ancestor_or_same_capture, |
62 | place_to_string_for_capture, |
63 | }; |
64 | pub use self::consts::{ |
65 | Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, ValTreeKind, |
66 | Value, |
67 | }; |
68 | pub use self::context::{ |
69 | CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, |
70 | TyCtxtFeed, tls, |
71 | }; |
72 | pub use self::fold::*; |
73 | pub use self::instance::{Instance, InstanceKind, ReifyReason, ShortInstance, UnusedGenericParams}; |
74 | pub use self::list::{List, ListWithCachedTypeInfo}; |
75 | pub use self::opaque_types::OpaqueTypeKey; |
76 | pub use self::parameterized::ParameterizedOverTcx; |
77 | pub use self::pattern::{Pattern, PatternKind}; |
78 | pub use self::predicate::{ |
79 | AliasTerm, Clause, ClauseKind, CoercePredicate, ExistentialPredicate, |
80 | ExistentialPredicateStableCmpExt, ExistentialProjection, ExistentialTraitRef, |
81 | HostEffectPredicate, NormalizesTo, OutlivesPredicate, PolyCoercePredicate, |
82 | PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef, |
83 | PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate, |
84 | PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate, |
85 | RegionOutlivesPredicate, SubtypePredicate, TraitPredicate, TraitRef, TypeOutlivesPredicate, |
86 | }; |
87 | pub use self::region::{ |
88 | BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, |
89 | RegionKind, RegionVid, |
90 | }; |
91 | pub use self::rvalue_scopes::RvalueScopes; |
92 | pub use self::sty::{ |
93 | AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, |
94 | CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst, |
95 | ParamTy, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs, |
96 | }; |
97 | pub use self::trait_def::TraitDef; |
98 | pub use self::typeck_results::{ |
99 | CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, IsIdentity, |
100 | Rust2024IncompatiblePatInfo, TypeckResults, UserType, UserTypeAnnotationIndex, UserTypeKind, |
101 | }; |
102 | pub use self::visit::*; |
103 | use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; |
104 | use crate::metadata::ModChild; |
105 | use crate::middle::privacy::EffectiveVisibilities; |
106 | use crate::mir::{Body, CoroutineLayout}; |
107 | use crate::query::{IntoQueryParam, Providers}; |
108 | use crate::ty; |
109 | use crate::ty::codec::{TyDecoder, TyEncoder}; |
110 | pub use crate::ty::diagnostics::*; |
111 | use crate::ty::fast_reject::SimplifiedType; |
112 | use crate::ty::util::Discr; |
113 | |
114 | pub mod abstract_const; |
115 | pub mod adjustment; |
116 | pub mod cast; |
117 | pub mod codec; |
118 | pub mod error; |
119 | pub mod fast_reject; |
120 | pub mod flags; |
121 | pub mod inhabitedness; |
122 | pub mod layout; |
123 | pub mod normalize_erasing_regions; |
124 | pub mod pattern; |
125 | pub mod print; |
126 | pub mod relate; |
127 | pub mod significant_drop_order; |
128 | pub mod trait_def; |
129 | pub mod util; |
130 | pub mod vtable; |
131 | pub mod walk; |
132 | |
133 | mod adt; |
134 | mod assoc; |
135 | mod closure; |
136 | mod consts; |
137 | mod context; |
138 | mod diagnostics; |
139 | mod elaborate_impl; |
140 | mod erase_regions; |
141 | mod fold; |
142 | mod generic_args; |
143 | mod generics; |
144 | mod impls_ty; |
145 | mod instance; |
146 | mod intrinsic; |
147 | mod list; |
148 | mod opaque_types; |
149 | mod parameterized; |
150 | mod predicate; |
151 | mod region; |
152 | mod rvalue_scopes; |
153 | mod structural_impls; |
154 | #[allow(hidden_glob_reexports)] |
155 | mod sty; |
156 | mod typeck_results; |
157 | mod visit; |
158 | |
159 | // Data types |
160 | |
161 | pub struct ResolverOutputs { |
162 | pub global_ctxt: ResolverGlobalCtxt, |
163 | pub ast_lowering: ResolverAstLowering, |
164 | } |
165 | |
166 | #[derive(Debug)] |
167 | pub struct ResolverGlobalCtxt { |
168 | pub visibilities_for_hashing: Vec<(LocalDefId, Visibility)>, |
169 | /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. |
170 | pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>, |
171 | pub effective_visibilities: EffectiveVisibilities, |
172 | pub extern_crate_map: UnordMap<LocalDefId, CrateNum>, |
173 | pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>, |
174 | pub module_children: LocalDefIdMap<Vec<ModChild>>, |
175 | pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>, |
176 | pub main_def: Option<MainDefinition>, |
177 | pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>, |
178 | /// A list of proc macro LocalDefIds, written out in the order in which |
179 | /// they are declared in the static array generated by proc_macro_harness. |
180 | pub proc_macros: Vec<LocalDefId>, |
181 | /// Mapping from ident span to path span for paths that don't exist as written, but that |
182 | /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. |
183 | pub confused_type_with_std_module: FxIndexMap<Span, Span>, |
184 | pub doc_link_resolutions: FxIndexMap<LocalDefId, DocLinkResMap>, |
185 | pub doc_link_traits_in_scope: FxIndexMap<LocalDefId, Vec<DefId>>, |
186 | pub all_macro_rules: FxHashSet<Symbol>, |
187 | pub stripped_cfg_items: Steal<Vec<StrippedCfgItem>>, |
188 | } |
189 | |
190 | /// Resolutions that should only be used for lowering. |
191 | /// This struct is meant to be consumed by lowering. |
192 | #[derive(Debug)] |
193 | pub struct ResolverAstLowering { |
194 | pub legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>, |
195 | |
196 | /// Resolutions for nodes that have a single resolution. |
197 | pub partial_res_map: NodeMap<hir::def::PartialRes>, |
198 | /// Resolutions for import nodes, which have multiple resolutions in different namespaces. |
199 | pub import_res_map: NodeMap<hir::def::PerNS<Option<Res<ast::NodeId>>>>, |
200 | /// Resolutions for labels (node IDs of their corresponding blocks or loops). |
201 | pub label_res_map: NodeMap<ast::NodeId>, |
202 | /// Resolutions for lifetimes. |
203 | pub lifetimes_res_map: NodeMap<LifetimeRes>, |
204 | /// Lifetime parameters that lowering will have to introduce. |
205 | pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, LifetimeRes)>>, |
206 | |
207 | pub next_node_id: ast::NodeId, |
208 | |
209 | pub node_id_to_def_id: NodeMap<LocalDefId>, |
210 | |
211 | pub trait_map: NodeMap<Vec<hir::TraitCandidate>>, |
212 | /// List functions and methods for which lifetime elision was successful. |
213 | pub lifetime_elision_allowed: FxHashSet<ast::NodeId>, |
214 | |
215 | /// Lints that were emitted by the resolver and early lints. |
216 | pub lint_buffer: Steal<LintBuffer>, |
217 | |
218 | /// Information about functions signatures for delegation items expansion |
219 | pub delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>, |
220 | } |
221 | |
222 | #[derive(Debug)] |
223 | pub struct DelegationFnSig { |
224 | pub header: ast::FnHeader, |
225 | pub param_count: usize, |
226 | pub has_self: bool, |
227 | pub c_variadic: bool, |
228 | pub target_feature: bool, |
229 | } |
230 | |
231 | #[derive(Clone, Copy, Debug)] |
232 | pub struct MainDefinition { |
233 | pub res: Res<ast::NodeId>, |
234 | pub is_import: bool, |
235 | pub span: Span, |
236 | } |
237 | |
238 | impl MainDefinition { |
239 | pub fn opt_fn_def_id(self) -> Option<DefId> { |
240 | if let Res::Def(DefKind::Fn, def_id: DefId) = self.res { Some(def_id) } else { None } |
241 | } |
242 | } |
243 | |
244 | /// The "header" of an impl is everything outside the body: a Self type, a trait |
245 | /// ref (in the case of a trait impl), and a set of predicates (from the |
246 | /// bounds / where-clauses). |
247 | #[derive(Clone, Debug, TypeFoldable, TypeVisitable)] |
248 | pub struct ImplHeader<'tcx> { |
249 | pub impl_def_id: DefId, |
250 | pub impl_args: ty::GenericArgsRef<'tcx>, |
251 | pub self_ty: Ty<'tcx>, |
252 | pub trait_ref: Option<TraitRef<'tcx>>, |
253 | pub predicates: Vec<Predicate<'tcx>>, |
254 | } |
255 | |
256 | #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] |
257 | pub struct ImplTraitHeader<'tcx> { |
258 | pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>, |
259 | pub polarity: ImplPolarity, |
260 | pub safety: hir::Safety, |
261 | pub constness: hir::Constness, |
262 | } |
263 | |
264 | #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] |
265 | pub enum ImplSubject<'tcx> { |
266 | Trait(TraitRef<'tcx>), |
267 | Inherent(Ty<'tcx>), |
268 | } |
269 | |
270 | #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] |
271 | #[derive(TypeFoldable, TypeVisitable)] |
272 | pub enum Asyncness { |
273 | Yes, |
274 | No, |
275 | } |
276 | |
277 | impl Asyncness { |
278 | pub fn is_async(self) -> bool { |
279 | matches!(self, Asyncness::Yes) |
280 | } |
281 | } |
282 | |
283 | #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Encodable, Decodable, HashStable)] |
284 | pub enum Visibility<Id = LocalDefId> { |
285 | /// Visible everywhere (including in other crates). |
286 | Public, |
287 | /// Visible only in the given crate-local module. |
288 | Restricted(Id), |
289 | } |
290 | |
291 | impl Visibility { |
292 | pub fn to_string(self, def_id: LocalDefId, tcx: TyCtxt<'_>) -> String { |
293 | match self { |
294 | ty::Visibility::Restricted(restricted_id: LocalDefId) => { |
295 | if restricted_id.is_top_level_module() { |
296 | "pub(crate)".to_string() |
297 | } else if restricted_id == tcx.parent_module_from_def_id(def_id).to_local_def_id() { |
298 | "pub(self)".to_string() |
299 | } else { |
300 | format!("pub({} )", tcx.item_name(restricted_id.to_def_id())) |
301 | } |
302 | } |
303 | ty::Visibility::Public => "pub".to_string(), |
304 | } |
305 | } |
306 | } |
307 | |
308 | #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)] |
309 | #[derive(TypeFoldable, TypeVisitable)] |
310 | pub struct ClosureSizeProfileData<'tcx> { |
311 | /// Tuple containing the types of closure captures before the feature `capture_disjoint_fields` |
312 | pub before_feature_tys: Ty<'tcx>, |
313 | /// Tuple containing the types of closure captures after the feature `capture_disjoint_fields` |
314 | pub after_feature_tys: Ty<'tcx>, |
315 | } |
316 | |
317 | impl TyCtxt<'_> { |
318 | #[inline] |
319 | pub fn opt_parent(self, id: DefId) -> Option<DefId> { |
320 | self.def_key(id).parent.map(|index| DefId { index, ..id }) |
321 | } |
322 | |
323 | #[inline] |
324 | #[track_caller] |
325 | pub fn parent(self, id: DefId) -> DefId { |
326 | match self.opt_parent(id) { |
327 | Some(id) => id, |
328 | // not `unwrap_or_else` to avoid breaking caller tracking |
329 | None => bug!("{id:?} doesn't have a parent"), |
330 | } |
331 | } |
332 | |
333 | #[inline] |
334 | #[track_caller] |
335 | pub fn opt_local_parent(self, id: LocalDefId) -> Option<LocalDefId> { |
336 | self.opt_parent(id.to_def_id()).map(DefId::expect_local) |
337 | } |
338 | |
339 | #[inline] |
340 | #[track_caller] |
341 | pub fn local_parent(self, id: impl Into<LocalDefId>) -> LocalDefId { |
342 | self.parent(id.into().to_def_id()).expect_local() |
343 | } |
344 | |
345 | pub fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool { |
346 | if descendant.krate != ancestor.krate { |
347 | return false; |
348 | } |
349 | |
350 | while descendant != ancestor { |
351 | match self.opt_parent(descendant) { |
352 | Some(parent) => descendant = parent, |
353 | None => return false, |
354 | } |
355 | } |
356 | true |
357 | } |
358 | } |
359 | |
360 | impl<Id> Visibility<Id> { |
361 | pub fn is_public(self) -> bool { |
362 | matches!(self, Visibility::Public) |
363 | } |
364 | |
365 | pub fn map_id<OutId>(self, f: impl FnOnce(Id) -> OutId) -> Visibility<OutId> { |
366 | match self { |
367 | Visibility::Public => Visibility::Public, |
368 | Visibility::Restricted(id: Id) => Visibility::Restricted(f(id)), |
369 | } |
370 | } |
371 | } |
372 | |
373 | impl<Id: Into<DefId>> Visibility<Id> { |
374 | pub fn to_def_id(self) -> Visibility<DefId> { |
375 | self.map_id(Into::into) |
376 | } |
377 | |
378 | /// Returns `true` if an item with this visibility is accessible from the given module. |
379 | pub fn is_accessible_from(self, module: impl Into<DefId>, tcx: TyCtxt<'_>) -> bool { |
380 | match self { |
381 | // Public items are visible everywhere. |
382 | Visibility::Public => true, |
383 | Visibility::Restricted(id: Id) => tcx.is_descendant_of(descendant:module.into(), ancestor:id.into()), |
384 | } |
385 | } |
386 | |
387 | /// Returns `true` if this visibility is at least as accessible as the given visibility |
388 | pub fn is_at_least(self, vis: Visibility<impl Into<DefId>>, tcx: TyCtxt<'_>) -> bool { |
389 | match vis { |
390 | Visibility::Public => self.is_public(), |
391 | Visibility::Restricted(id: impl Into |
392 | } |
393 | } |
394 | } |
395 | |
396 | impl Visibility<DefId> { |
397 | pub fn expect_local(self) -> Visibility { |
398 | self.map_id(|id: DefId| id.expect_local()) |
399 | } |
400 | |
401 | /// Returns `true` if this item is visible anywhere in the local crate. |
402 | pub fn is_visible_locally(self) -> bool { |
403 | match self { |
404 | Visibility::Public => true, |
405 | Visibility::Restricted(def_id: DefId) => def_id.is_local(), |
406 | } |
407 | } |
408 | } |
409 | |
410 | /// The crate variances map is computed during typeck and contains the |
411 | /// variance of every item in the local crate. You should not use it |
412 | /// directly, because to do so will make your pass dependent on the |
413 | /// HIR of every item in the local crate. Instead, use |
414 | /// `tcx.variances_of()` to get the variance for a *particular* |
415 | /// item. |
416 | #[derive(HashStable, Debug)] |
417 | pub struct CrateVariancesMap<'tcx> { |
418 | /// For each item with generics, maps to a vector of the variance |
419 | /// of its generics. If an item has no generics, it will have no |
420 | /// entry. |
421 | pub variances: DefIdMap<&'tcx [ty::Variance]>, |
422 | } |
423 | |
424 | // Contains information needed to resolve types and (in the future) look up |
425 | // the types of AST nodes. |
426 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] |
427 | pub struct CReaderCacheKey { |
428 | pub cnum: Option<CrateNum>, |
429 | pub pos: usize, |
430 | } |
431 | |
432 | /// Use this rather than `TyKind`, whenever possible. |
433 | #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] |
434 | #[rustc_diagnostic_item= "Ty"] |
435 | #[rustc_pass_by_value] |
436 | pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>); |
437 | |
438 | impl<'tcx> rustc_type_ir::inherent::IntoKind for Ty<'tcx> { |
439 | type Kind = TyKind<'tcx>; |
440 | |
441 | fn kind(self) -> TyKind<'tcx> { |
442 | *self.kind() |
443 | } |
444 | } |
445 | |
446 | impl<'tcx> rustc_type_ir::Flags for Ty<'tcx> { |
447 | fn flags(&self) -> TypeFlags { |
448 | self.0.flags |
449 | } |
450 | |
451 | fn outer_exclusive_binder(&self) -> DebruijnIndex { |
452 | self.0.outer_exclusive_binder |
453 | } |
454 | } |
455 | |
456 | impl EarlyParamRegion { |
457 | /// Does this early bound region have a name? Early bound regions normally |
458 | /// always have names except when using anonymous lifetimes (`'_`). |
459 | pub fn has_name(&self) -> bool { |
460 | self.name != kw::UnderscoreLifetime |
461 | } |
462 | } |
463 | |
464 | /// The crate outlives map is computed during typeck and contains the |
465 | /// outlives of every item in the local crate. You should not use it |
466 | /// directly, because to do so will make your pass dependent on the |
467 | /// HIR of every item in the local crate. Instead, use |
468 | /// `tcx.inferred_outlives_of()` to get the outlives for a *particular* |
469 | /// item. |
470 | #[derive(HashStable, Debug)] |
471 | pub struct CratePredicatesMap<'tcx> { |
472 | /// For each struct with outlive bounds, maps to a vector of the |
473 | /// predicate of its outlive bounds. If an item has no outlives |
474 | /// bounds, it will have no entry. |
475 | pub predicates: DefIdMap<&'tcx [(Clause<'tcx>, Span)]>, |
476 | } |
477 | |
478 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
479 | pub struct Term<'tcx> { |
480 | ptr: NonNull<()>, |
481 | marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>, |
482 | } |
483 | |
484 | impl<'tcx> rustc_type_ir::inherent::Term<TyCtxt<'tcx>> for Term<'tcx> {} |
485 | |
486 | impl<'tcx> rustc_type_ir::inherent::IntoKind for Term<'tcx> { |
487 | type Kind = TermKind<'tcx>; |
488 | |
489 | fn kind(self) -> Self::Kind { |
490 | self.unpack() |
491 | } |
492 | } |
493 | |
494 | unsafe impl<'tcx> rustc_data_structures::sync::DynSend for Term<'tcx> where |
495 | &'tcx (Ty<'tcx>, Const<'tcx>): rustc_data_structures::sync::DynSend |
496 | { |
497 | } |
498 | unsafe impl<'tcx> rustc_data_structures::sync::DynSync for Term<'tcx> where |
499 | &'tcx (Ty<'tcx>, Const<'tcx>): rustc_data_structures::sync::DynSync |
500 | { |
501 | } |
502 | unsafe impl<'tcx> Send for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): Send {} |
503 | unsafe impl<'tcx> Sync for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): Sync {} |
504 | |
505 | impl Debug for Term<'_> { |
506 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
507 | match self.unpack() { |
508 | TermKind::Ty(ty: Ty<'_>) => write!(f, "Term::Ty({ty:?} )"), |
509 | TermKind::Const(ct: Const<'_>) => write!(f, "Term::Const({ct:?} )"), |
510 | } |
511 | } |
512 | } |
513 | |
514 | impl<'tcx> From<Ty<'tcx>> for Term<'tcx> { |
515 | fn from(ty: Ty<'tcx>) -> Self { |
516 | TermKind::Ty(ty).pack() |
517 | } |
518 | } |
519 | |
520 | impl<'tcx> From<Const<'tcx>> for Term<'tcx> { |
521 | fn from(c: Const<'tcx>) -> Self { |
522 | TermKind::Const(c).pack() |
523 | } |
524 | } |
525 | |
526 | impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Term<'tcx> { |
527 | fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
528 | self.unpack().hash_stable(hcx, hasher); |
529 | } |
530 | } |
531 | |
532 | impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> { |
533 | fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( |
534 | self, |
535 | folder: &mut F, |
536 | ) -> Result<Self, F::Error> { |
537 | match self.unpack() { |
538 | ty::TermKind::Ty(ty: Ty<'_>) => ty.try_fold_with(folder).map(op:Into::into), |
539 | ty::TermKind::Const(ct: Const<'_>) => ct.try_fold_with(folder).map(op:Into::into), |
540 | } |
541 | } |
542 | } |
543 | |
544 | impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> { |
545 | fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result { |
546 | match self.unpack() { |
547 | ty::TermKind::Ty(ty: Ty<'_>) => ty.visit_with(visitor), |
548 | ty::TermKind::Const(ct: Const<'_>) => ct.visit_with(visitor), |
549 | } |
550 | } |
551 | } |
552 | |
553 | impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Term<'tcx> { |
554 | fn encode(&self, e: &mut E) { |
555 | self.unpack().encode(e) |
556 | } |
557 | } |
558 | |
559 | impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Term<'tcx> { |
560 | fn decode(d: &mut D) -> Self { |
561 | let res: TermKind<'tcx> = Decodable::decode(d); |
562 | res.pack() |
563 | } |
564 | } |
565 | |
566 | impl<'tcx> Term<'tcx> { |
567 | #[inline] |
568 | pub fn unpack(self) -> TermKind<'tcx> { |
569 | let ptr = |
570 | unsafe { self.ptr.map_addr(|addr| NonZero::new_unchecked(addr.get() & !TAG_MASK)) }; |
571 | // SAFETY: use of `Interned::new_unchecked` here is ok because these |
572 | // pointers were originally created from `Interned` types in `pack()`, |
573 | // and this is just going in the other direction. |
574 | unsafe { |
575 | match self.ptr.addr().get() & TAG_MASK { |
576 | TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( |
577 | ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(), |
578 | ))), |
579 | CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( |
580 | ptr.cast::<WithCachedTypeInfo<ty::ConstKind<'tcx>>>().as_ref(), |
581 | ))), |
582 | _ => core::intrinsics::unreachable(), |
583 | } |
584 | } |
585 | } |
586 | |
587 | pub fn as_type(&self) -> Option<Ty<'tcx>> { |
588 | if let TermKind::Ty(ty) = self.unpack() { Some(ty) } else { None } |
589 | } |
590 | |
591 | pub fn expect_type(&self) -> Ty<'tcx> { |
592 | self.as_type().expect("expected a type, but found a const") |
593 | } |
594 | |
595 | pub fn as_const(&self) -> Option<Const<'tcx>> { |
596 | if let TermKind::Const(c) = self.unpack() { Some(c) } else { None } |
597 | } |
598 | |
599 | pub fn expect_const(&self) -> Const<'tcx> { |
600 | self.as_const().expect("expected a const, but found a type") |
601 | } |
602 | |
603 | pub fn into_arg(self) -> GenericArg<'tcx> { |
604 | match self.unpack() { |
605 | TermKind::Ty(ty) => ty.into(), |
606 | TermKind::Const(c) => c.into(), |
607 | } |
608 | } |
609 | |
610 | pub fn to_alias_term(self) -> Option<AliasTerm<'tcx>> { |
611 | match self.unpack() { |
612 | TermKind::Ty(ty) => match *ty.kind() { |
613 | ty::Alias(_kind, alias_ty) => Some(alias_ty.into()), |
614 | _ => None, |
615 | }, |
616 | TermKind::Const(ct) => match ct.kind() { |
617 | ConstKind::Unevaluated(uv) => Some(uv.into()), |
618 | _ => None, |
619 | }, |
620 | } |
621 | } |
622 | |
623 | pub fn is_infer(&self) -> bool { |
624 | match self.unpack() { |
625 | TermKind::Ty(ty) => ty.is_ty_var(), |
626 | TermKind::Const(ct) => ct.is_ct_infer(), |
627 | } |
628 | } |
629 | } |
630 | |
631 | const TAG_MASK: usize = 0b11; |
632 | const TYPE_TAG: usize = 0b00; |
633 | const CONST_TAG: usize = 0b01; |
634 | |
635 | #[extension(pub trait TermKindPackExt<'tcx>)] |
636 | impl<'tcx> TermKind<'tcx> { |
637 | #[inline] |
638 | fn pack(self) -> Term<'tcx> { |
639 | let (tag: usize, ptr: NonNull<()>) = match self { |
640 | TermKind::Ty(ty: Ty<'_>) => { |
641 | // Ensure we can use the tag bits. |
642 | assert_eq!(align_of_val(&*ty.0.0) & TAG_MASK, 0); |
643 | (TYPE_TAG, NonNull::from(ty.0.0).cast()) |
644 | } |
645 | TermKind::Const(ct: Const<'_>) => { |
646 | // Ensure we can use the tag bits. |
647 | assert_eq!(align_of_val(&*ct.0.0) & TAG_MASK, 0); |
648 | (CONST_TAG, NonNull::from(ct.0.0).cast()) |
649 | } |
650 | }; |
651 | |
652 | Term { ptr: ptr.map_addr(|addr: NonZero |
653 | } |
654 | } |
655 | |
656 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
657 | pub enum ParamTerm { |
658 | Ty(ParamTy), |
659 | Const(ParamConst), |
660 | } |
661 | |
662 | impl ParamTerm { |
663 | pub fn index(self) -> usize { |
664 | match self { |
665 | ParamTerm::Ty(ty: ParamTy) => ty.index as usize, |
666 | ParamTerm::Const(ct: ParamConst) => ct.index as usize, |
667 | } |
668 | } |
669 | } |
670 | |
671 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] |
672 | pub enum TermVid { |
673 | Ty(ty::TyVid), |
674 | Const(ty::ConstVid), |
675 | } |
676 | |
677 | impl From<ty::TyVid> for TermVid { |
678 | fn from(value: ty::TyVid) -> Self { |
679 | TermVid::Ty(value) |
680 | } |
681 | } |
682 | |
683 | impl From<ty::ConstVid> for TermVid { |
684 | fn from(value: ty::ConstVid) -> Self { |
685 | TermVid::Const(value) |
686 | } |
687 | } |
688 | |
689 | /// Represents the bounds declared on a particular set of type |
690 | /// parameters. Should eventually be generalized into a flag list of |
691 | /// where-clauses. You can obtain an `InstantiatedPredicates` list from a |
692 | /// `GenericPredicates` by using the `instantiate` method. Note that this method |
693 | /// reflects an important semantic invariant of `InstantiatedPredicates`: while |
694 | /// the `GenericPredicates` are expressed in terms of the bound type |
695 | /// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance |
696 | /// represented a set of bounds for some particular instantiation, |
697 | /// meaning that the generic parameters have been instantiated with |
698 | /// their values. |
699 | /// |
700 | /// Example: |
701 | /// ```ignore (illustrative) |
702 | /// struct Foo<T, U: Bar<T>> { ... } |
703 | /// ``` |
704 | /// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like |
705 | /// `[[], [U:Bar<T>]]`. Now if there were some particular reference |
706 | /// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[], |
707 | /// [usize:Bar<isize>]]`. |
708 | #[derive(Clone, Debug, TypeFoldable, TypeVisitable)] |
709 | pub struct InstantiatedPredicates<'tcx> { |
710 | pub predicates: Vec<Clause<'tcx>>, |
711 | pub spans: Vec<Span>, |
712 | } |
713 | |
714 | impl<'tcx> InstantiatedPredicates<'tcx> { |
715 | pub fn empty() -> InstantiatedPredicates<'tcx> { |
716 | InstantiatedPredicates { predicates: vec![], spans: vec![] } |
717 | } |
718 | |
719 | pub fn is_empty(&self) -> bool { |
720 | self.predicates.is_empty() |
721 | } |
722 | |
723 | pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter { |
724 | self.into_iter() |
725 | } |
726 | } |
727 | |
728 | impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> { |
729 | type Item = (Clause<'tcx>, Span); |
730 | |
731 | type IntoIter = std::iter::Zip<std::vec::IntoIter<Clause<'tcx>>, std::vec::IntoIter<Span>>; |
732 | |
733 | fn into_iter(self) -> Self::IntoIter { |
734 | debug_assert_eq!(self.predicates.len(), self.spans.len()); |
735 | std::iter::zip(self.predicates, self.spans) |
736 | } |
737 | } |
738 | |
739 | impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> { |
740 | type Item = (Clause<'tcx>, Span); |
741 | |
742 | type IntoIter = std::iter::Zip< |
743 | std::iter::Copied<std::slice::Iter<'a, Clause<'tcx>>>, |
744 | std::iter::Copied<std::slice::Iter<'a, Span>>, |
745 | >; |
746 | |
747 | fn into_iter(self) -> Self::IntoIter { |
748 | debug_assert_eq!(self.predicates.len(), self.spans.len()); |
749 | std::iter::zip(self.predicates.iter().copied(), self.spans.iter().copied()) |
750 | } |
751 | } |
752 | |
753 | #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)] |
754 | pub struct OpaqueHiddenType<'tcx> { |
755 | /// The span of this particular definition of the opaque type. So |
756 | /// for example: |
757 | /// |
758 | /// ```ignore (incomplete snippet) |
759 | /// type Foo = impl Baz; |
760 | /// fn bar() -> Foo { |
761 | /// // ^^^ This is the span we are looking for! |
762 | /// } |
763 | /// ``` |
764 | /// |
765 | /// In cases where the fn returns `(impl Trait, impl Trait)` or |
766 | /// other such combinations, the result is currently |
767 | /// over-approximated, but better than nothing. |
768 | pub span: Span, |
769 | |
770 | /// The type variable that represents the value of the opaque type |
771 | /// that we require. In other words, after we compile this function, |
772 | /// we will be created a constraint like: |
773 | /// ```ignore (pseudo-rust) |
774 | /// Foo<'a, T> = ?C |
775 | /// ``` |
776 | /// where `?C` is the value of this type variable. =) It may |
777 | /// naturally refer to the type and lifetime parameters in scope |
778 | /// in this function, though ultimately it should only reference |
779 | /// those that are arguments to `Foo` in the constraint above. (In |
780 | /// other words, `?C` should not include `'b`, even though it's a |
781 | /// lifetime parameter on `foo`.) |
782 | pub ty: Ty<'tcx>, |
783 | } |
784 | |
785 | impl<'tcx> OpaqueHiddenType<'tcx> { |
786 | pub fn build_mismatch_error( |
787 | &self, |
788 | other: &Self, |
789 | tcx: TyCtxt<'tcx>, |
790 | ) -> Result<Diag<'tcx>, ErrorGuaranteed> { |
791 | (self.ty, other.ty).error_reported()?; |
792 | // Found different concrete types for the opaque type. |
793 | let sub_diag = if self.span == other.span { |
794 | TypeMismatchReason::ConflictType { span: self.span } |
795 | } else { |
796 | TypeMismatchReason::PreviousUse { span: self.span } |
797 | }; |
798 | Ok(tcx.dcx().create_err(OpaqueHiddenTypeMismatch { |
799 | self_ty: self.ty, |
800 | other_ty: other.ty, |
801 | other_span: other.span, |
802 | sub: sub_diag, |
803 | })) |
804 | } |
805 | |
806 | #[instrument(level = "debug", skip(tcx), ret)] |
807 | pub fn remap_generic_params_to_declaration_params( |
808 | self, |
809 | opaque_type_key: OpaqueTypeKey<'tcx>, |
810 | tcx: TyCtxt<'tcx>, |
811 | // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck. |
812 | ignore_errors: bool, |
813 | ) -> Self { |
814 | let OpaqueTypeKey { def_id, args } = opaque_type_key; |
815 | |
816 | // Use args to build up a reverse map from regions to their |
817 | // identity mappings. This is necessary because of `impl |
818 | // Trait` lifetimes are computed by replacing existing |
819 | // lifetimes with 'static and remapping only those used in the |
820 | // `impl Trait` return type, resulting in the parameters |
821 | // shifting. |
822 | let id_args = GenericArgs::identity_for_item(tcx, def_id); |
823 | debug!(?id_args); |
824 | |
825 | // This zip may have several times the same lifetime in `args` paired with a different |
826 | // lifetime from `id_args`. Simply `collect`ing the iterator is the correct behaviour: |
827 | // it will pick the last one, which is the one we introduced in the impl-trait desugaring. |
828 | let map = args.iter().zip(id_args).collect(); |
829 | debug!("map ={:#?} ", map); |
830 | |
831 | // Convert the type from the function into a type valid outside |
832 | // the function, by replacing invalid regions with 'static, |
833 | // after producing an error for each of them. |
834 | self.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span, ignore_errors)) |
835 | } |
836 | } |
837 | |
838 | /// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are |
839 | /// identified by both a universe, as well as a name residing within that universe. Distinct bound |
840 | /// regions/types/consts within the same universe simply have an unknown relationship to one |
841 | /// another. |
842 | #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
843 | #[derive(HashStable, TyEncodable, TyDecodable)] |
844 | pub struct Placeholder<T> { |
845 | pub universe: UniverseIndex, |
846 | pub bound: T, |
847 | } |
848 | impl Placeholder<BoundVar> { |
849 | pub fn find_const_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> { |
850 | let mut candidates: impl Iterator |
851 | // `ConstArgHasType` are never desugared to be higher ranked. |
852 | match clause.kind().skip_binder() { |
853 | ty::ClauseKind::ConstArgHasType(placeholder_ct: Const<'_>, ty: Ty<'_>) => { |
854 | assert!(!(placeholder_ct, ty).has_escaping_bound_vars()); |
855 | |
856 | match placeholder_ct.kind() { |
857 | ty::ConstKind::Placeholder(placeholder_ct: Placeholder<{unknown}>) if placeholder_ct == self => { |
858 | Some(ty) |
859 | } |
860 | _ => None, |
861 | } |
862 | } |
863 | _ => None, |
864 | } |
865 | }); |
866 | |
867 | let ty: Ty<'_> = candidates.next().unwrap(); |
868 | assert!(candidates.next().is_none()); |
869 | ty |
870 | } |
871 | } |
872 | |
873 | pub type PlaceholderRegion = Placeholder<BoundRegion>; |
874 | |
875 | impl rustc_type_ir::inherent::PlaceholderLike for PlaceholderRegion { |
876 | fn universe(self) -> UniverseIndex { |
877 | self.universe |
878 | } |
879 | |
880 | fn var(self) -> BoundVar { |
881 | self.bound.var |
882 | } |
883 | |
884 | fn with_updated_universe(self, ui: UniverseIndex) -> Self { |
885 | Placeholder { universe: ui, ..self } |
886 | } |
887 | |
888 | fn new(ui: UniverseIndex, var: BoundVar) -> Self { |
889 | Placeholder { universe: ui, bound: BoundRegion { var, kind: BoundRegionKind::Anon } } |
890 | } |
891 | } |
892 | |
893 | pub type PlaceholderType = Placeholder<BoundTy>; |
894 | |
895 | impl rustc_type_ir::inherent::PlaceholderLike for PlaceholderType { |
896 | fn universe(self) -> UniverseIndex { |
897 | self.universe |
898 | } |
899 | |
900 | fn var(self) -> BoundVar { |
901 | self.bound.var |
902 | } |
903 | |
904 | fn with_updated_universe(self, ui: UniverseIndex) -> Self { |
905 | Placeholder { universe: ui, ..self } |
906 | } |
907 | |
908 | fn new(ui: UniverseIndex, var: BoundVar) -> Self { |
909 | Placeholder { universe: ui, bound: BoundTy { var, kind: BoundTyKind::Anon } } |
910 | } |
911 | } |
912 | |
913 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] |
914 | #[derive(TyEncodable, TyDecodable)] |
915 | pub struct BoundConst<'tcx> { |
916 | pub var: BoundVar, |
917 | pub ty: Ty<'tcx>, |
918 | } |
919 | |
920 | pub type PlaceholderConst = Placeholder<BoundVar>; |
921 | |
922 | impl rustc_type_ir::inherent::PlaceholderLike for PlaceholderConst { |
923 | fn universe(self) -> UniverseIndex { |
924 | self.universe |
925 | } |
926 | |
927 | fn var(self) -> BoundVar { |
928 | self.bound |
929 | } |
930 | |
931 | fn with_updated_universe(self, ui: UniverseIndex) -> Self { |
932 | Placeholder { universe: ui, ..self } |
933 | } |
934 | |
935 | fn new(ui: UniverseIndex, var: BoundVar) -> Self { |
936 | Placeholder { universe: ui, bound: var } |
937 | } |
938 | } |
939 | |
940 | pub type Clauses<'tcx> = &'tcx ListWithCachedTypeInfo<Clause<'tcx>>; |
941 | |
942 | impl<'tcx> rustc_type_ir::Flags for Clauses<'tcx> { |
943 | fn flags(&self) -> TypeFlags { |
944 | (**self).flags() |
945 | } |
946 | |
947 | fn outer_exclusive_binder(&self) -> DebruijnIndex { |
948 | (**self).outer_exclusive_binder() |
949 | } |
950 | } |
951 | |
952 | /// When interacting with the type system we must provide information about the |
953 | /// environment. `ParamEnv` is the type that represents this information. See the |
954 | /// [dev guide chapter][param_env_guide] for more information. |
955 | /// |
956 | /// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/param_env/param_env_summary.html |
957 | #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] |
958 | #[derive(HashStable, TypeVisitable, TypeFoldable)] |
959 | pub struct ParamEnv<'tcx> { |
960 | /// Caller bounds are `Obligation`s that the caller must satisfy. This is |
961 | /// basically the set of bounds on the in-scope type parameters, translated |
962 | /// into `Obligation`s, and elaborated and normalized. |
963 | /// |
964 | /// Use the `caller_bounds()` method to access. |
965 | caller_bounds: Clauses<'tcx>, |
966 | } |
967 | |
968 | impl<'tcx> rustc_type_ir::inherent::ParamEnv<TyCtxt<'tcx>> for ParamEnv<'tcx> { |
969 | fn caller_bounds(self) -> impl inherent::SliceLike<Item = ty::Clause<'tcx>> { |
970 | self.caller_bounds() |
971 | } |
972 | } |
973 | |
974 | impl<'tcx> ParamEnv<'tcx> { |
975 | /// Construct a trait environment suitable for contexts where there are |
976 | /// no where-clauses in scope. In the majority of cases it is incorrect |
977 | /// to use an empty environment. See the [dev guide section][param_env_guide] |
978 | /// for information on what a `ParamEnv` is and how to acquire one. |
979 | /// |
980 | /// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/param_env/param_env_summary.html |
981 | #[inline] |
982 | pub fn empty() -> Self { |
983 | Self::new(ListWithCachedTypeInfo::empty()) |
984 | } |
985 | |
986 | #[inline] |
987 | pub fn caller_bounds(self) -> Clauses<'tcx> { |
988 | self.caller_bounds |
989 | } |
990 | |
991 | /// Construct a trait environment with the given set of predicates. |
992 | #[inline] |
993 | pub fn new(caller_bounds: Clauses<'tcx>) -> Self { |
994 | ParamEnv { caller_bounds } |
995 | } |
996 | |
997 | /// Creates a pair of param-env and value for use in queries. |
998 | pub fn and<T: TypeVisitable<TyCtxt<'tcx>>>(self, value: T) -> ParamEnvAnd<'tcx, T> { |
999 | ParamEnvAnd { param_env: self, value } |
1000 | } |
1001 | } |
1002 | |
1003 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] |
1004 | #[derive(HashStable)] |
1005 | pub struct ParamEnvAnd<'tcx, T> { |
1006 | pub param_env: ParamEnv<'tcx>, |
1007 | pub value: T, |
1008 | } |
1009 | |
1010 | impl<'tcx, T> ParamEnvAnd<'tcx, T> { |
1011 | pub fn into_parts(self) -> (ParamEnv<'tcx>, T) { |
1012 | (self.param_env, self.value) |
1013 | } |
1014 | } |
1015 | |
1016 | /// The environment in which to do trait solving. |
1017 | /// |
1018 | /// Most of the time you only need to care about the `ParamEnv` |
1019 | /// as the `TypingMode` is simply stored in the `InferCtxt`. |
1020 | /// |
1021 | /// However, there are some places which rely on trait solving |
1022 | /// without using an `InferCtxt` themselves. For these to be |
1023 | /// able to use the trait system they have to be able to initialize |
1024 | /// such an `InferCtxt` with the right `typing_mode`, so they need |
1025 | /// to track both. |
1026 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] |
1027 | #[derive(TypeVisitable, TypeFoldable)] |
1028 | pub struct TypingEnv<'tcx> { |
1029 | pub typing_mode: TypingMode<'tcx>, |
1030 | pub param_env: ParamEnv<'tcx>, |
1031 | } |
1032 | |
1033 | impl<'tcx> TypingEnv<'tcx> { |
1034 | /// Create a typing environment with no where-clauses in scope |
1035 | /// where all opaque types and default associated items are revealed. |
1036 | /// |
1037 | /// This is only suitable for monomorphized, post-typeck environments. |
1038 | /// Do not use this for MIR optimizations, as even though they also |
1039 | /// use `TypingMode::PostAnalysis`, they may still have where-clauses |
1040 | /// in scope. |
1041 | pub fn fully_monomorphized() -> TypingEnv<'tcx> { |
1042 | TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env: ParamEnv::empty() } |
1043 | } |
1044 | |
1045 | /// Create a typing environment for use during analysis outside of a body. |
1046 | /// |
1047 | /// Using a typing environment inside of bodies is not supported as the body |
1048 | /// may define opaque types. In this case the used functions have to be |
1049 | /// converted to use proper canonical inputs instead. |
1050 | pub fn non_body_analysis( |
1051 | tcx: TyCtxt<'tcx>, |
1052 | def_id: impl IntoQueryParam<DefId>, |
1053 | ) -> TypingEnv<'tcx> { |
1054 | TypingEnv { typing_mode: TypingMode::non_body_analysis(), param_env: tcx.param_env(def_id) } |
1055 | } |
1056 | |
1057 | pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryParam<DefId>) -> TypingEnv<'tcx> { |
1058 | TypingEnv { |
1059 | typing_mode: TypingMode::PostAnalysis, |
1060 | param_env: tcx.param_env_normalized_for_post_analysis(def_id), |
1061 | } |
1062 | } |
1063 | |
1064 | /// Modify the `typing_mode` to `PostAnalysis` and eagerly reveal all |
1065 | /// opaque types in the `param_env`. |
1066 | pub fn with_post_analysis_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> { |
1067 | let TypingEnv { typing_mode, param_env } = self; |
1068 | if let TypingMode::PostAnalysis = typing_mode { |
1069 | return self; |
1070 | } |
1071 | |
1072 | // No need to reveal opaques with the new solver enabled, |
1073 | // since we have lazy norm. |
1074 | let param_env = if tcx.next_trait_solver_globally() { |
1075 | ParamEnv::new(param_env.caller_bounds()) |
1076 | } else { |
1077 | ParamEnv::new(tcx.reveal_opaque_types_in_bounds(param_env.caller_bounds())) |
1078 | }; |
1079 | TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env } |
1080 | } |
1081 | |
1082 | /// Combine this typing environment with the given `value` to be used by |
1083 | /// not (yet) canonicalized queries. This only works if the value does not |
1084 | /// contain anything local to some `InferCtxt`, i.e. inference variables or |
1085 | /// placeholders. |
1086 | pub fn as_query_input<T>(self, value: T) -> PseudoCanonicalInput<'tcx, T> |
1087 | where |
1088 | T: TypeVisitable<TyCtxt<'tcx>>, |
1089 | { |
1090 | // FIXME(#132279): We should assert that the value does not contain any placeholders |
1091 | // as these placeholders are also local to the current inference context. However, we |
1092 | // currently use pseudo-canonical queries in the trait solver which replaces params with |
1093 | // placeholders. We should also simply not use pseudo-canonical queries in the trait |
1094 | // solver, at which point we can readd this assert. As of writing this comment, this is |
1095 | // only used by `fn layout_is_pointer_like` when calling `layout_of`. |
1096 | // |
1097 | // debug_assert!(!value.has_placeholders()); |
1098 | PseudoCanonicalInput { typing_env: self, value } |
1099 | } |
1100 | } |
1101 | |
1102 | /// Similar to `CanonicalInput`, this carries the `typing_mode` and the environment |
1103 | /// necessary to do any kind of trait solving inside of nested queries. |
1104 | /// |
1105 | /// Unlike proper canonicalization, this requires the `param_env` and the `value` to not |
1106 | /// contain anything local to the `infcx` of the caller, so we don't actually canonicalize |
1107 | /// anything. |
1108 | /// |
1109 | /// This should be created by using `infcx.pseudo_canonicalize_query(param_env, value)` |
1110 | /// or by using `typing_env.as_query_input(value)`. |
1111 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] |
1112 | #[derive(HashStable, TypeVisitable, TypeFoldable)] |
1113 | pub struct PseudoCanonicalInput<'tcx, T> { |
1114 | pub typing_env: TypingEnv<'tcx>, |
1115 | pub value: T, |
1116 | } |
1117 | |
1118 | #[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] |
1119 | pub struct Destructor { |
1120 | /// The `DefId` of the destructor method |
1121 | pub did: DefId, |
1122 | /// The constness of the destructor method |
1123 | pub constness: hir::Constness, |
1124 | } |
1125 | |
1126 | // FIXME: consider combining this definition with regular `Destructor` |
1127 | #[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] |
1128 | pub struct AsyncDestructor { |
1129 | /// The `DefId` of the async destructor future constructor |
1130 | pub ctor: DefId, |
1131 | /// The `DefId` of the async destructor future type |
1132 | pub future: DefId, |
1133 | } |
1134 | |
1135 | #[derive(Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] |
1136 | pub struct VariantFlags(u8); |
1137 | bitflags::bitflags! { |
1138 | impl VariantFlags: u8 { |
1139 | const NO_VARIANT_FLAGS = 0; |
1140 | /// Indicates whether the field list of this variant is `#[non_exhaustive]`. |
1141 | const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0; |
1142 | } |
1143 | } |
1144 | rustc_data_structures::external_bitflags_debug! { VariantFlags } |
1145 | |
1146 | /// Definition of a variant -- a struct's fields or an enum variant. |
1147 | #[derive(Debug, HashStable, TyEncodable, TyDecodable)] |
1148 | pub struct VariantDef { |
1149 | /// `DefId` that identifies the variant itself. |
1150 | /// If this variant belongs to a struct or union, then this is a copy of its `DefId`. |
1151 | pub def_id: DefId, |
1152 | /// `DefId` that identifies the variant's constructor. |
1153 | /// If this variant is a struct variant, then this is `None`. |
1154 | pub ctor: Option<(CtorKind, DefId)>, |
1155 | /// Variant or struct name. |
1156 | pub name: Symbol, |
1157 | /// Discriminant of this variant. |
1158 | pub discr: VariantDiscr, |
1159 | /// Fields of this variant. |
1160 | pub fields: IndexVec<FieldIdx, FieldDef>, |
1161 | /// The error guarantees from parser, if any. |
1162 | tainted: Option<ErrorGuaranteed>, |
1163 | /// Flags of the variant (e.g. is field list non-exhaustive)? |
1164 | flags: VariantFlags, |
1165 | } |
1166 | |
1167 | impl VariantDef { |
1168 | /// Creates a new `VariantDef`. |
1169 | /// |
1170 | /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef` |
1171 | /// represents an enum variant). |
1172 | /// |
1173 | /// `ctor_did` is the `DefId` that identifies the constructor of unit or |
1174 | /// tuple-variants/structs. If this is a `struct`-variant then this should be `None`. |
1175 | /// |
1176 | /// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that |
1177 | /// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having |
1178 | /// to go through the redirect of checking the ctor's attributes - but compiling a small crate |
1179 | /// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any |
1180 | /// built-in trait), and we do not want to load attributes twice. |
1181 | /// |
1182 | /// If someone speeds up attribute loading to not be a performance concern, they can |
1183 | /// remove this hack and use the constructor `DefId` everywhere. |
1184 | #[instrument(level = "debug")] |
1185 | pub fn new( |
1186 | name: Symbol, |
1187 | variant_did: Option<DefId>, |
1188 | ctor: Option<(CtorKind, DefId)>, |
1189 | discr: VariantDiscr, |
1190 | fields: IndexVec<FieldIdx, FieldDef>, |
1191 | parent_did: DefId, |
1192 | recover_tainted: Option<ErrorGuaranteed>, |
1193 | is_field_list_non_exhaustive: bool, |
1194 | ) -> Self { |
1195 | let mut flags = VariantFlags::NO_VARIANT_FLAGS; |
1196 | if is_field_list_non_exhaustive { |
1197 | flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; |
1198 | } |
1199 | |
1200 | VariantDef { |
1201 | def_id: variant_did.unwrap_or(parent_did), |
1202 | ctor, |
1203 | name, |
1204 | discr, |
1205 | fields, |
1206 | flags, |
1207 | tainted: recover_tainted, |
1208 | } |
1209 | } |
1210 | |
1211 | /// Returns `true` if the field list of this variant is `#[non_exhaustive]`. |
1212 | /// |
1213 | /// Note that this function will return `true` even if the type has been |
1214 | /// defined in the crate currently being compiled. If that's not what you |
1215 | /// want, see [`Self::field_list_has_applicable_non_exhaustive`]. |
1216 | #[inline] |
1217 | pub fn is_field_list_non_exhaustive(&self) -> bool { |
1218 | self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE) |
1219 | } |
1220 | |
1221 | /// Returns `true` if the field list of this variant is `#[non_exhaustive]` |
1222 | /// and the type has been defined in another crate. |
1223 | #[inline] |
1224 | pub fn field_list_has_applicable_non_exhaustive(&self) -> bool { |
1225 | self.is_field_list_non_exhaustive() && !self.def_id.is_local() |
1226 | } |
1227 | |
1228 | /// Computes the `Ident` of this variant by looking up the `Span` |
1229 | pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { |
1230 | Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) |
1231 | } |
1232 | |
1233 | /// Was this variant obtained as part of recovering from a syntactic error? |
1234 | #[inline] |
1235 | pub fn has_errors(&self) -> Result<(), ErrorGuaranteed> { |
1236 | self.tainted.map_or(Ok(()), Err) |
1237 | } |
1238 | |
1239 | #[inline] |
1240 | pub fn ctor_kind(&self) -> Option<CtorKind> { |
1241 | self.ctor.map(|(kind, _)| kind) |
1242 | } |
1243 | |
1244 | #[inline] |
1245 | pub fn ctor_def_id(&self) -> Option<DefId> { |
1246 | self.ctor.map(|(_, def_id)| def_id) |
1247 | } |
1248 | |
1249 | /// Returns the one field in this variant. |
1250 | /// |
1251 | /// `panic!`s if there are no fields or multiple fields. |
1252 | #[inline] |
1253 | pub fn single_field(&self) -> &FieldDef { |
1254 | assert!(self.fields.len() == 1); |
1255 | |
1256 | &self.fields[FieldIdx::ZERO] |
1257 | } |
1258 | |
1259 | /// Returns the last field in this variant, if present. |
1260 | #[inline] |
1261 | pub fn tail_opt(&self) -> Option<&FieldDef> { |
1262 | self.fields.raw.last() |
1263 | } |
1264 | |
1265 | /// Returns the last field in this variant. |
1266 | /// |
1267 | /// # Panics |
1268 | /// |
1269 | /// Panics, if the variant has no fields. |
1270 | #[inline] |
1271 | pub fn tail(&self) -> &FieldDef { |
1272 | self.tail_opt().expect("expected unsized ADT to have a tail field") |
1273 | } |
1274 | |
1275 | /// Returns whether this variant has unsafe fields. |
1276 | pub fn has_unsafe_fields(&self) -> bool { |
1277 | self.fields.iter().any(|x| x.safety.is_unsafe()) |
1278 | } |
1279 | } |
1280 | |
1281 | impl PartialEq for VariantDef { |
1282 | #[inline] |
1283 | fn eq(&self, other: &Self) -> bool { |
1284 | // There should be only one `VariantDef` for each `def_id`, therefore |
1285 | // it is fine to implement `PartialEq` only based on `def_id`. |
1286 | // |
1287 | // Below, we exhaustively destructure `self` and `other` so that if the |
1288 | // definition of `VariantDef` changes, a compile-error will be produced, |
1289 | // reminding us to revisit this assumption. |
1290 | |
1291 | let Self { |
1292 | def_id: lhs_def_id, |
1293 | ctor: _, |
1294 | name: _, |
1295 | discr: _, |
1296 | fields: _, |
1297 | flags: _, |
1298 | tainted: _, |
1299 | } = &self; |
1300 | let Self { |
1301 | def_id: rhs_def_id, |
1302 | ctor: _, |
1303 | name: _, |
1304 | discr: _, |
1305 | fields: _, |
1306 | flags: _, |
1307 | tainted: _, |
1308 | } = other; |
1309 | |
1310 | let res = lhs_def_id == rhs_def_id; |
1311 | |
1312 | // Double check that implicit assumption detailed above. |
1313 | if cfg!(debug_assertions) && res { |
1314 | let deep = self.ctor == other.ctor |
1315 | && self.name == other.name |
1316 | && self.discr == other.discr |
1317 | && self.fields == other.fields |
1318 | && self.flags == other.flags; |
1319 | assert!(deep, "VariantDef for the same def-id has differing data"); |
1320 | } |
1321 | |
1322 | res |
1323 | } |
1324 | } |
1325 | |
1326 | impl Eq for VariantDef {} |
1327 | |
1328 | impl Hash for VariantDef { |
1329 | #[inline] |
1330 | fn hash<H: Hasher>(&self, s: &mut H) { |
1331 | // There should be only one `VariantDef` for each `def_id`, therefore |
1332 | // it is fine to implement `Hash` only based on `def_id`. |
1333 | // |
1334 | // Below, we exhaustively destructure `self` so that if the definition |
1335 | // of `VariantDef` changes, a compile-error will be produced, reminding |
1336 | // us to revisit this assumption. |
1337 | |
1338 | let Self { def_id: &DefId, ctor: _, name: _, discr: _, fields: _, flags: _, tainted: _ } = &self; |
1339 | def_id.hash(state:s) |
1340 | } |
1341 | } |
1342 | |
1343 | #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] |
1344 | pub enum VariantDiscr { |
1345 | /// Explicit value for this variant, i.e., `X = 123`. |
1346 | /// The `DefId` corresponds to the embedded constant. |
1347 | Explicit(DefId), |
1348 | |
1349 | /// The previous variant's discriminant plus one. |
1350 | /// For efficiency reasons, the distance from the |
1351 | /// last `Explicit` discriminant is being stored, |
1352 | /// or `0` for the first variant, if it has none. |
1353 | Relative(u32), |
1354 | } |
1355 | |
1356 | #[derive(Debug, HashStable, TyEncodable, TyDecodable)] |
1357 | pub struct FieldDef { |
1358 | pub did: DefId, |
1359 | pub name: Symbol, |
1360 | pub vis: Visibility<DefId>, |
1361 | pub safety: hir::Safety, |
1362 | pub value: Option<DefId>, |
1363 | } |
1364 | |
1365 | impl PartialEq for FieldDef { |
1366 | #[inline] |
1367 | fn eq(&self, other: &Self) -> bool { |
1368 | // There should be only one `FieldDef` for each `did`, therefore it is |
1369 | // fine to implement `PartialEq` only based on `did`. |
1370 | // |
1371 | // Below, we exhaustively destructure `self` so that if the definition |
1372 | // of `FieldDef` changes, a compile-error will be produced, reminding |
1373 | // us to revisit this assumption. |
1374 | |
1375 | let Self { did: lhs_did, name: _, vis: _, safety: _, value: _ } = &self; |
1376 | |
1377 | let Self { did: rhs_did, name: _, vis: _, safety: _, value: _ } = other; |
1378 | |
1379 | let res = lhs_did == rhs_did; |
1380 | |
1381 | // Double check that implicit assumption detailed above. |
1382 | if cfg!(debug_assertions) && res { |
1383 | let deep = |
1384 | self.name == other.name && self.vis == other.vis && self.safety == other.safety; |
1385 | assert!(deep, "FieldDef for the same def-id has differing data"); |
1386 | } |
1387 | |
1388 | res |
1389 | } |
1390 | } |
1391 | |
1392 | impl Eq for FieldDef {} |
1393 | |
1394 | impl Hash for FieldDef { |
1395 | #[inline] |
1396 | fn hash<H: Hasher>(&self, s: &mut H) { |
1397 | // There should be only one `FieldDef` for each `did`, therefore it is |
1398 | // fine to implement `Hash` only based on `did`. |
1399 | // |
1400 | // Below, we exhaustively destructure `self` so that if the definition |
1401 | // of `FieldDef` changes, a compile-error will be produced, reminding |
1402 | // us to revisit this assumption. |
1403 | |
1404 | let Self { did: &DefId, name: _, vis: _, safety: _, value: _ } = &self; |
1405 | |
1406 | did.hash(state:s) |
1407 | } |
1408 | } |
1409 | |
1410 | impl<'tcx> FieldDef { |
1411 | /// Returns the type of this field. The resulting type is not normalized. The `arg` is |
1412 | /// typically obtained via the second field of [`TyKind::Adt`]. |
1413 | pub fn ty(&self, tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> { |
1414 | tcx.type_of(self.did).instantiate(cx:tcx, args) |
1415 | } |
1416 | |
1417 | /// Computes the `Ident` of this variant by looking up the `Span` |
1418 | pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { |
1419 | Ident::new(self.name, span:tcx.def_ident_span(self.did).unwrap()) |
1420 | } |
1421 | } |
1422 | |
1423 | #[derive(Debug, PartialEq, Eq)] |
1424 | pub enum ImplOverlapKind { |
1425 | /// These impls are always allowed to overlap. |
1426 | Permitted { |
1427 | /// Whether or not the impl is permitted due to the trait being a `#[marker]` trait |
1428 | marker: bool, |
1429 | }, |
1430 | } |
1431 | |
1432 | /// Useful source information about where a desugared associated type for an |
1433 | /// RPITIT originated from. |
1434 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable)] |
1435 | pub enum ImplTraitInTraitData { |
1436 | Trait { fn_def_id: DefId, opaque_def_id: DefId }, |
1437 | Impl { fn_def_id: DefId }, |
1438 | } |
1439 | |
1440 | impl<'tcx> TyCtxt<'tcx> { |
1441 | pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> { |
1442 | self.typeck(self.hir_body_owner_def_id(body)) |
1443 | } |
1444 | |
1445 | pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'tcx AssocItem> { |
1446 | self.associated_items(id) |
1447 | .in_definition_order() |
1448 | .filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value()) |
1449 | } |
1450 | |
1451 | pub fn repr_options_of_def(self, did: LocalDefId) -> ReprOptions { |
1452 | let mut flags = ReprFlags::empty(); |
1453 | let mut size = None; |
1454 | let mut max_align: Option<Align> = None; |
1455 | let mut min_pack: Option<Align> = None; |
1456 | |
1457 | // Generate a deterministically-derived seed from the item's path hash |
1458 | // to allow for cross-crate compilation to actually work |
1459 | let mut field_shuffle_seed = self.def_path_hash(did.to_def_id()).0.to_smaller_hash(); |
1460 | |
1461 | // If the user defined a custom seed for layout randomization, xor the item's |
1462 | // path hash with the user defined seed, this will allowing determinism while |
1463 | // still allowing users to further randomize layout generation for e.g. fuzzing |
1464 | if let Some(user_seed) = self.sess.opts.unstable_opts.layout_seed { |
1465 | field_shuffle_seed ^= user_seed; |
1466 | } |
1467 | |
1468 | if let Some(reprs) = attr::find_attr!(self.get_all_attrs(did), AttributeKind::Repr(r) => r) |
1469 | { |
1470 | for (r, _) in reprs { |
1471 | flags.insert(match *r { |
1472 | attr::ReprRust => ReprFlags::empty(), |
1473 | attr::ReprC => ReprFlags::IS_C, |
1474 | attr::ReprPacked(pack) => { |
1475 | min_pack = Some(if let Some(min_pack) = min_pack { |
1476 | min_pack.min(pack) |
1477 | } else { |
1478 | pack |
1479 | }); |
1480 | ReprFlags::empty() |
1481 | } |
1482 | attr::ReprTransparent => ReprFlags::IS_TRANSPARENT, |
1483 | attr::ReprSimd => ReprFlags::IS_SIMD, |
1484 | attr::ReprInt(i) => { |
1485 | size = Some(match i { |
1486 | attr::IntType::SignedInt(x) => match x { |
1487 | ast::IntTy::Isize => IntegerType::Pointer(true), |
1488 | ast::IntTy::I8 => IntegerType::Fixed(Integer::I8, true), |
1489 | ast::IntTy::I16 => IntegerType::Fixed(Integer::I16, true), |
1490 | ast::IntTy::I32 => IntegerType::Fixed(Integer::I32, true), |
1491 | ast::IntTy::I64 => IntegerType::Fixed(Integer::I64, true), |
1492 | ast::IntTy::I128 => IntegerType::Fixed(Integer::I128, true), |
1493 | }, |
1494 | attr::IntType::UnsignedInt(x) => match x { |
1495 | ast::UintTy::Usize => IntegerType::Pointer(false), |
1496 | ast::UintTy::U8 => IntegerType::Fixed(Integer::I8, false), |
1497 | ast::UintTy::U16 => IntegerType::Fixed(Integer::I16, false), |
1498 | ast::UintTy::U32 => IntegerType::Fixed(Integer::I32, false), |
1499 | ast::UintTy::U64 => IntegerType::Fixed(Integer::I64, false), |
1500 | ast::UintTy::U128 => IntegerType::Fixed(Integer::I128, false), |
1501 | }, |
1502 | }); |
1503 | ReprFlags::empty() |
1504 | } |
1505 | attr::ReprAlign(align) => { |
1506 | max_align = max_align.max(Some(align)); |
1507 | ReprFlags::empty() |
1508 | } |
1509 | attr::ReprEmpty => { |
1510 | /* skip these, they're just for diagnostics */ |
1511 | ReprFlags::empty() |
1512 | } |
1513 | }); |
1514 | } |
1515 | } |
1516 | |
1517 | // If `-Z randomize-layout` was enabled for the type definition then we can |
1518 | // consider performing layout randomization |
1519 | if self.sess.opts.unstable_opts.randomize_layout { |
1520 | flags.insert(ReprFlags::RANDOMIZE_LAYOUT); |
1521 | } |
1522 | |
1523 | // box is special, on the one hand the compiler assumes an ordered layout, with the pointer |
1524 | // always at offset zero. On the other hand we want scalar abi optimizations. |
1525 | let is_box = self.is_lang_item(did.to_def_id(), LangItem::OwnedBox); |
1526 | |
1527 | // This is here instead of layout because the choice must make it into metadata. |
1528 | if is_box { |
1529 | flags.insert(ReprFlags::IS_LINEAR); |
1530 | } |
1531 | |
1532 | ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed } |
1533 | } |
1534 | |
1535 | /// Look up the name of a definition across crates. This does not look at HIR. |
1536 | pub fn opt_item_name(self, def_id: DefId) -> Option<Symbol> { |
1537 | if let Some(cnum) = def_id.as_crate_root() { |
1538 | Some(self.crate_name(cnum)) |
1539 | } else { |
1540 | let def_key = self.def_key(def_id); |
1541 | match def_key.disambiguated_data.data { |
1542 | // The name of a constructor is that of its parent. |
1543 | rustc_hir::definitions::DefPathData::Ctor => self |
1544 | .opt_item_name(DefId { krate: def_id.krate, index: def_key.parent.unwrap() }), |
1545 | _ => def_key.get_opt_name(), |
1546 | } |
1547 | } |
1548 | } |
1549 | |
1550 | /// Look up the name of a definition across crates. This does not look at HIR. |
1551 | /// |
1552 | /// This method will ICE if the corresponding item does not have a name. In these cases, use |
1553 | /// [`opt_item_name`] instead. |
1554 | /// |
1555 | /// [`opt_item_name`]: Self::opt_item_name |
1556 | pub fn item_name(self, id: DefId) -> Symbol { |
1557 | self.opt_item_name(id).unwrap_or_else(|| { |
1558 | bug!("item_name: no name for{:?} ", self.def_path(id)); |
1559 | }) |
1560 | } |
1561 | |
1562 | /// Look up the name and span of a definition. |
1563 | /// |
1564 | /// See [`item_name`][Self::item_name] for more information. |
1565 | pub fn opt_item_ident(self, def_id: DefId) -> Option<Ident> { |
1566 | let def = self.opt_item_name(def_id)?; |
1567 | let span = self |
1568 | .def_ident_span(def_id) |
1569 | .unwrap_or_else(|| bug!("missing ident span for{def_id:?} ")); |
1570 | Some(Ident::new(def, span)) |
1571 | } |
1572 | |
1573 | /// Look up the name and span of a definition. |
1574 | /// |
1575 | /// See [`item_name`][Self::item_name] for more information. |
1576 | pub fn item_ident(self, def_id: DefId) -> Ident { |
1577 | self.opt_item_ident(def_id).unwrap_or_else(|| { |
1578 | bug!("item_ident: no name for{:?} ", self.def_path(def_id)); |
1579 | }) |
1580 | } |
1581 | |
1582 | pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> { |
1583 | if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { |
1584 | Some(self.associated_item(def_id)) |
1585 | } else { |
1586 | None |
1587 | } |
1588 | } |
1589 | |
1590 | /// If the `def_id` is an associated type that was desugared from a |
1591 | /// return-position `impl Trait` from a trait, then provide the source info |
1592 | /// about where that RPITIT came from. |
1593 | pub fn opt_rpitit_info(self, def_id: DefId) -> Option<ImplTraitInTraitData> { |
1594 | if let DefKind::AssocTy = self.def_kind(def_id) { |
1595 | self.associated_item(def_id).opt_rpitit_info |
1596 | } else { |
1597 | None |
1598 | } |
1599 | } |
1600 | |
1601 | pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<FieldIdx> { |
1602 | variant.fields.iter_enumerated().find_map(|(i, field)| { |
1603 | self.hygienic_eq(ident, field.ident(self), variant.def_id).then_some(i) |
1604 | }) |
1605 | } |
1606 | |
1607 | /// Returns `Some` if the impls are the same polarity and the trait either |
1608 | /// has no items or is annotated `#[marker]` and prevents item overrides. |
1609 | #[instrument(level = "debug", skip(self), ret)] |
1610 | pub fn impls_are_allowed_to_overlap( |
1611 | self, |
1612 | def_id1: DefId, |
1613 | def_id2: DefId, |
1614 | ) -> Option<ImplOverlapKind> { |
1615 | let impl1 = self.impl_trait_header(def_id1).unwrap(); |
1616 | let impl2 = self.impl_trait_header(def_id2).unwrap(); |
1617 | |
1618 | let trait_ref1 = impl1.trait_ref.skip_binder(); |
1619 | let trait_ref2 = impl2.trait_ref.skip_binder(); |
1620 | |
1621 | // If either trait impl references an error, they're allowed to overlap, |
1622 | // as one of them essentially doesn't exist. |
1623 | if trait_ref1.references_error() || trait_ref2.references_error() { |
1624 | return Some(ImplOverlapKind::Permitted { marker: false }); |
1625 | } |
1626 | |
1627 | match (impl1.polarity, impl2.polarity) { |
1628 | (ImplPolarity::Reservation, _) | (_, ImplPolarity::Reservation) => { |
1629 | // `#[rustc_reservation_impl]` impls don't overlap with anything |
1630 | return Some(ImplOverlapKind::Permitted { marker: false }); |
1631 | } |
1632 | (ImplPolarity::Positive, ImplPolarity::Negative) |
1633 | | (ImplPolarity::Negative, ImplPolarity::Positive) => { |
1634 | // `impl AutoTrait for Type` + `impl !AutoTrait for Type` |
1635 | return None; |
1636 | } |
1637 | (ImplPolarity::Positive, ImplPolarity::Positive) |
1638 | | (ImplPolarity::Negative, ImplPolarity::Negative) => {} |
1639 | }; |
1640 | |
1641 | let is_marker_impl = |trait_ref: TraitRef<'_>| self.trait_def(trait_ref.def_id).is_marker; |
1642 | let is_marker_overlap = is_marker_impl(trait_ref1) && is_marker_impl(trait_ref2); |
1643 | |
1644 | if is_marker_overlap { |
1645 | return Some(ImplOverlapKind::Permitted { marker: true }); |
1646 | } |
1647 | |
1648 | None |
1649 | } |
1650 | |
1651 | /// Returns `ty::VariantDef` if `res` refers to a struct, |
1652 | /// or variant or their constructors, panics otherwise. |
1653 | pub fn expect_variant_res(self, res: Res) -> &'tcx VariantDef { |
1654 | match res { |
1655 | Res::Def(DefKind::Variant, did) => { |
1656 | let enum_did = self.parent(did); |
1657 | self.adt_def(enum_did).variant_with_id(did) |
1658 | } |
1659 | Res::Def(DefKind::Struct | DefKind::Union, did) => self.adt_def(did).non_enum_variant(), |
1660 | Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_did) => { |
1661 | let variant_did = self.parent(variant_ctor_did); |
1662 | let enum_did = self.parent(variant_did); |
1663 | self.adt_def(enum_did).variant_with_ctor_id(variant_ctor_did) |
1664 | } |
1665 | Res::Def(DefKind::Ctor(CtorOf::Struct, ..), ctor_did) => { |
1666 | let struct_did = self.parent(ctor_did); |
1667 | self.adt_def(struct_did).non_enum_variant() |
1668 | } |
1669 | _ => bug!("expect_variant_res used with unexpected res{:?} ", res), |
1670 | } |
1671 | } |
1672 | |
1673 | /// Returns the possibly-auto-generated MIR of a [`ty::InstanceKind`]. |
1674 | #[instrument(skip(self), level = "debug")] |
1675 | pub fn instance_mir(self, instance: ty::InstanceKind<'tcx>) -> &'tcx Body<'tcx> { |
1676 | match instance { |
1677 | ty::InstanceKind::Item(def) => { |
1678 | debug!("calling def_kind on def:{:?} ", def); |
1679 | let def_kind = self.def_kind(def); |
1680 | debug!("returned from def_kind:{:?} ", def_kind); |
1681 | match def_kind { |
1682 | DefKind::Const |
1683 | | DefKind::Static { .. } |
1684 | | DefKind::AssocConst |
1685 | | DefKind::Ctor(..) |
1686 | | DefKind::AnonConst |
1687 | | DefKind::InlineConst => self.mir_for_ctfe(def), |
1688 | // If the caller wants `mir_for_ctfe` of a function they should not be using |
1689 | // `instance_mir`, so we'll assume const fn also wants the optimized version. |
1690 | _ => self.optimized_mir(def), |
1691 | } |
1692 | } |
1693 | ty::InstanceKind::VTableShim(..) |
1694 | | ty::InstanceKind::ReifyShim(..) |
1695 | | ty::InstanceKind::Intrinsic(..) |
1696 | | ty::InstanceKind::FnPtrShim(..) |
1697 | | ty::InstanceKind::Virtual(..) |
1698 | | ty::InstanceKind::ClosureOnceShim { .. } |
1699 | | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } |
1700 | | ty::InstanceKind::DropGlue(..) |
1701 | | ty::InstanceKind::CloneShim(..) |
1702 | | ty::InstanceKind::ThreadLocalShim(..) |
1703 | | ty::InstanceKind::FnPtrAddrShim(..) |
1704 | | ty::InstanceKind::AsyncDropGlueCtorShim(..) => self.mir_shims(instance), |
1705 | } |
1706 | } |
1707 | |
1708 | // FIXME(@lcnr): Remove this function. |
1709 | pub fn get_attrs_unchecked(self, did: DefId) -> &'tcx [hir::Attribute] { |
1710 | if let Some(did) = did.as_local() { |
1711 | self.hir_attrs(self.local_def_id_to_hir_id(did)) |
1712 | } else { |
1713 | self.attrs_for_def(did) |
1714 | } |
1715 | } |
1716 | |
1717 | /// Gets all attributes with the given name. |
1718 | pub fn get_attrs( |
1719 | self, |
1720 | did: impl Into<DefId>, |
1721 | attr: Symbol, |
1722 | ) -> impl Iterator<Item = &'tcx hir::Attribute> { |
1723 | self.get_all_attrs(did).filter(move |a: &&hir::Attribute| a.has_name(attr)) |
1724 | } |
1725 | |
1726 | /// Gets all attributes. |
1727 | /// |
1728 | /// To see if an item has a specific attribute, you should use [`rustc_attr_data_structures::find_attr!`] so you can use matching. |
1729 | pub fn get_all_attrs( |
1730 | self, |
1731 | did: impl Into<DefId>, |
1732 | ) -> impl Iterator<Item = &'tcx hir::Attribute> { |
1733 | let did: DefId = did.into(); |
1734 | if let Some(did) = did.as_local() { |
1735 | self.hir_attrs(self.local_def_id_to_hir_id(did)).iter() |
1736 | } else { |
1737 | self.attrs_for_def(did).iter() |
1738 | } |
1739 | } |
1740 | |
1741 | /// Get an attribute from the diagnostic attribute namespace |
1742 | /// |
1743 | /// This function requests an attribute with the following structure: |
1744 | /// |
1745 | /// `#[diagnostic::$attr]` |
1746 | /// |
1747 | /// This function performs feature checking, so if an attribute is returned |
1748 | /// it can be used by the consumer |
1749 | pub fn get_diagnostic_attr( |
1750 | self, |
1751 | did: impl Into<DefId>, |
1752 | attr: Symbol, |
1753 | ) -> Option<&'tcx hir::Attribute> { |
1754 | let did: DefId = did.into(); |
1755 | if did.as_local().is_some() { |
1756 | // it's a crate local item, we need to check feature flags |
1757 | if rustc_feature::is_stable_diagnostic_attribute(attr, self.features()) { |
1758 | self.get_attrs_by_path(did, &[sym::diagnostic, sym::do_not_recommend]).next() |
1759 | } else { |
1760 | None |
1761 | } |
1762 | } else { |
1763 | // we filter out unstable diagnostic attributes before |
1764 | // encoding attributes |
1765 | debug_assert!(rustc_feature::encode_cross_crate(attr)); |
1766 | self.attrs_for_def(did) |
1767 | .iter() |
1768 | .find(|a| matches!(a.path().as_ref(), [sym::diagnostic, a] if *a == attr)) |
1769 | } |
1770 | } |
1771 | |
1772 | pub fn get_attrs_by_path( |
1773 | self, |
1774 | did: DefId, |
1775 | attr: &[Symbol], |
1776 | ) -> impl Iterator<Item = &'tcx hir::Attribute> { |
1777 | let filter_fn = move |a: &&hir::Attribute| a.path_matches(attr); |
1778 | if let Some(did) = did.as_local() { |
1779 | self.hir_attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn) |
1780 | } else { |
1781 | self.attrs_for_def(did).iter().filter(filter_fn) |
1782 | } |
1783 | } |
1784 | |
1785 | pub fn get_attr(self, did: impl Into<DefId>, attr: Symbol) -> Option<&'tcx hir::Attribute> { |
1786 | if cfg!(debug_assertions) && !rustc_feature::is_valid_for_get_attr(attr) { |
1787 | let did: DefId = did.into(); |
1788 | bug!("get_attr: unexpected called with DefId `{:?} `, attr `{:?} `", did, attr); |
1789 | } else { |
1790 | self.get_attrs(did, attr).next() |
1791 | } |
1792 | } |
1793 | |
1794 | /// Determines whether an item is annotated with an attribute. |
1795 | pub fn has_attr(self, did: impl Into<DefId>, attr: Symbol) -> bool { |
1796 | self.get_attrs(did, attr).next().is_some() |
1797 | } |
1798 | |
1799 | /// Determines whether an item is annotated with a multi-segment attribute |
1800 | pub fn has_attrs_with_path(self, did: impl Into<DefId>, attrs: &[Symbol]) -> bool { |
1801 | self.get_attrs_by_path(did.into(), attrs).next().is_some() |
1802 | } |
1803 | |
1804 | /// Returns `true` if this is an `auto trait`. |
1805 | pub fn trait_is_auto(self, trait_def_id: DefId) -> bool { |
1806 | self.trait_def(trait_def_id).has_auto_impl |
1807 | } |
1808 | |
1809 | /// Returns `true` if this is coinductive, either because it is |
1810 | /// an auto trait or because it has the `#[rustc_coinductive]` attribute. |
1811 | pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool { |
1812 | self.trait_def(trait_def_id).is_coinductive |
1813 | } |
1814 | |
1815 | /// Returns `true` if this is a trait alias. |
1816 | pub fn trait_is_alias(self, trait_def_id: DefId) -> bool { |
1817 | self.def_kind(trait_def_id) == DefKind::TraitAlias |
1818 | } |
1819 | |
1820 | /// Returns layout of a coroutine. Layout might be unavailable if the |
1821 | /// coroutine is tainted by errors. |
1822 | /// |
1823 | /// Takes `coroutine_kind` which can be acquired from the `CoroutineArgs::kind_ty`, |
1824 | /// e.g. `args.as_coroutine().kind_ty()`. |
1825 | pub fn coroutine_layout( |
1826 | self, |
1827 | def_id: DefId, |
1828 | coroutine_kind_ty: Ty<'tcx>, |
1829 | ) -> Option<&'tcx CoroutineLayout<'tcx>> { |
1830 | let mir = self.optimized_mir(def_id); |
1831 | // Regular coroutine |
1832 | if coroutine_kind_ty.is_unit() { |
1833 | mir.coroutine_layout_raw() |
1834 | } else { |
1835 | // If we have a `Coroutine` that comes from an coroutine-closure, |
1836 | // then it may be a by-move or by-ref body. |
1837 | let ty::Coroutine(_, identity_args) = |
1838 | *self.type_of(def_id).instantiate_identity().kind() |
1839 | else { |
1840 | unreachable!(); |
1841 | }; |
1842 | let identity_kind_ty = identity_args.as_coroutine().kind_ty(); |
1843 | // If the types differ, then we must be getting the by-move body of |
1844 | // a by-ref coroutine. |
1845 | if identity_kind_ty == coroutine_kind_ty { |
1846 | mir.coroutine_layout_raw() |
1847 | } else { |
1848 | assert_matches!(coroutine_kind_ty.to_opt_closure_kind(), Some(ClosureKind::FnOnce)); |
1849 | assert_matches!( |
1850 | identity_kind_ty.to_opt_closure_kind(), |
1851 | Some(ClosureKind::Fn | ClosureKind::FnMut) |
1852 | ); |
1853 | self.optimized_mir(self.coroutine_by_move_body_def_id(def_id)) |
1854 | .coroutine_layout_raw() |
1855 | } |
1856 | } |
1857 | } |
1858 | |
1859 | /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. |
1860 | /// If it implements no trait, returns `None`. |
1861 | pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> { |
1862 | self.impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id) |
1863 | } |
1864 | |
1865 | /// If the given `DefId` describes an item belonging to a trait, |
1866 | /// returns the `DefId` of the trait that the trait item belongs to; |
1867 | /// otherwise, returns `None`. |
1868 | pub fn trait_of_item(self, def_id: DefId) -> Option<DefId> { |
1869 | if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { |
1870 | let parent = self.parent(def_id); |
1871 | if let DefKind::Trait | DefKind::TraitAlias = self.def_kind(parent) { |
1872 | return Some(parent); |
1873 | } |
1874 | } |
1875 | None |
1876 | } |
1877 | |
1878 | /// If the given `DefId` describes a method belonging to an impl, returns the |
1879 | /// `DefId` of the impl that the method belongs to; otherwise, returns `None`. |
1880 | pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> { |
1881 | if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { |
1882 | let parent = self.parent(def_id); |
1883 | if let DefKind::Impl { .. } = self.def_kind(parent) { |
1884 | return Some(parent); |
1885 | } |
1886 | } |
1887 | None |
1888 | } |
1889 | |
1890 | /// Check if the given `DefId` is `#\[automatically_derived\]`, *and* |
1891 | /// whether it was produced by expanding a builtin derive macro. |
1892 | pub fn is_builtin_derived(self, def_id: DefId) -> bool { |
1893 | if self.is_automatically_derived(def_id) |
1894 | && let Some(def_id) = def_id.as_local() |
1895 | && let outer = self.def_span(def_id).ctxt().outer_expn_data() |
1896 | && matches!(outer.kind, ExpnKind::Macro(MacroKind::Derive, _)) |
1897 | && self.has_attr(outer.macro_def_id.unwrap(), sym::rustc_builtin_macro) |
1898 | { |
1899 | true |
1900 | } else { |
1901 | false |
1902 | } |
1903 | } |
1904 | |
1905 | /// Check if the given `DefId` is `#\[automatically_derived\]`. |
1906 | pub fn is_automatically_derived(self, def_id: DefId) -> bool { |
1907 | self.has_attr(def_id, sym::automatically_derived) |
1908 | } |
1909 | |
1910 | /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err` |
1911 | /// with the name of the crate containing the impl. |
1912 | pub fn span_of_impl(self, impl_def_id: DefId) -> Result<Span, Symbol> { |
1913 | if let Some(impl_def_id) = impl_def_id.as_local() { |
1914 | Ok(self.def_span(impl_def_id)) |
1915 | } else { |
1916 | Err(self.crate_name(impl_def_id.krate)) |
1917 | } |
1918 | } |
1919 | |
1920 | /// Hygienically compares a use-site name (`use_name`) for a field or an associated item with |
1921 | /// its supposed definition name (`def_name`). The method also needs `DefId` of the supposed |
1922 | /// definition's parent/scope to perform comparison. |
1923 | pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool { |
1924 | // We could use `Ident::eq` here, but we deliberately don't. The name |
1925 | // comparison fails frequently, and we want to avoid the expensive |
1926 | // `normalize_to_macros_2_0()` calls required for the span comparison whenever possible. |
1927 | use_name.name == def_name.name |
1928 | && use_name |
1929 | .span |
1930 | .ctxt() |
1931 | .hygienic_eq(def_name.span.ctxt(), self.expn_that_defined(def_parent_def_id)) |
1932 | } |
1933 | |
1934 | pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident { |
1935 | ident.span.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)); |
1936 | ident |
1937 | } |
1938 | |
1939 | // FIXME(vincenzopalazzo): move the HirId to a LocalDefId |
1940 | pub fn adjust_ident_and_get_scope( |
1941 | self, |
1942 | mut ident: Ident, |
1943 | scope: DefId, |
1944 | block: hir::HirId, |
1945 | ) -> (Ident, DefId) { |
1946 | let scope = ident |
1947 | .span |
1948 | .normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)) |
1949 | .and_then(|actual_expansion| actual_expansion.expn_data().parent_module) |
1950 | .unwrap_or_else(|| self.parent_module(block).to_def_id()); |
1951 | (ident, scope) |
1952 | } |
1953 | |
1954 | /// Checks whether this is a `const fn`. Returns `false` for non-functions. |
1955 | /// |
1956 | /// Even if this returns `true`, constness may still be unstable! |
1957 | #[inline] |
1958 | pub fn is_const_fn(self, def_id: DefId) -> bool { |
1959 | matches!( |
1960 | self.def_kind(def_id), |
1961 | DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Closure |
1962 | ) && self.constness(def_id) == hir::Constness::Const |
1963 | } |
1964 | |
1965 | /// Whether this item is conditionally constant for the purposes of the |
1966 | /// effects implementation. |
1967 | /// |
1968 | /// This roughly corresponds to all const functions and other callable |
1969 | /// items, along with const impls and traits, and associated types within |
1970 | /// those impls and traits. |
1971 | pub fn is_conditionally_const(self, def_id: impl Into<DefId>) -> bool { |
1972 | let def_id: DefId = def_id.into(); |
1973 | match self.def_kind(def_id) { |
1974 | DefKind::Impl { of_trait: true } => { |
1975 | let header = self.impl_trait_header(def_id).unwrap(); |
1976 | header.constness == hir::Constness::Const |
1977 | && self.is_const_trait(header.trait_ref.skip_binder().def_id) |
1978 | } |
1979 | DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => { |
1980 | self.constness(def_id) == hir::Constness::Const |
1981 | } |
1982 | DefKind::Trait => self.is_const_trait(def_id), |
1983 | DefKind::AssocTy => { |
1984 | let parent_def_id = self.parent(def_id); |
1985 | match self.def_kind(parent_def_id) { |
1986 | DefKind::Impl { of_trait: false } => false, |
1987 | DefKind::Impl { of_trait: true } | DefKind::Trait => { |
1988 | self.is_conditionally_const(parent_def_id) |
1989 | } |
1990 | _ => bug!("unexpected parent item of associated type:{parent_def_id:?} "), |
1991 | } |
1992 | } |
1993 | DefKind::AssocFn => { |
1994 | let parent_def_id = self.parent(def_id); |
1995 | match self.def_kind(parent_def_id) { |
1996 | DefKind::Impl { of_trait: false } => { |
1997 | self.constness(def_id) == hir::Constness::Const |
1998 | } |
1999 | DefKind::Impl { of_trait: true } | DefKind::Trait => { |
2000 | self.is_conditionally_const(parent_def_id) |
2001 | } |
2002 | _ => bug!("unexpected parent item of associated fn:{parent_def_id:?} "), |
2003 | } |
2004 | } |
2005 | DefKind::OpaqueTy => match self.opaque_ty_origin(def_id) { |
2006 | hir::OpaqueTyOrigin::FnReturn { parent, .. } => self.is_conditionally_const(parent), |
2007 | hir::OpaqueTyOrigin::AsyncFn { .. } => false, |
2008 | // FIXME(const_trait_impl): ATPITs could be conditionally const? |
2009 | hir::OpaqueTyOrigin::TyAlias { .. } => false, |
2010 | }, |
2011 | DefKind::Closure => { |
2012 | // Closures and RPITs will eventually have const conditions |
2013 | // for `~const` bounds. |
2014 | false |
2015 | } |
2016 | DefKind::Ctor(_, CtorKind::Const) |
2017 | | DefKind::Impl { of_trait: false } |
2018 | | DefKind::Mod |
2019 | | DefKind::Struct |
2020 | | DefKind::Union |
2021 | | DefKind::Enum |
2022 | | DefKind::Variant |
2023 | | DefKind::TyAlias |
2024 | | DefKind::ForeignTy |
2025 | | DefKind::TraitAlias |
2026 | | DefKind::TyParam |
2027 | | DefKind::Const |
2028 | | DefKind::ConstParam |
2029 | | DefKind::Static { .. } |
2030 | | DefKind::AssocConst |
2031 | | DefKind::Macro(_) |
2032 | | DefKind::ExternCrate |
2033 | | DefKind::Use |
2034 | | DefKind::ForeignMod |
2035 | | DefKind::AnonConst |
2036 | | DefKind::InlineConst |
2037 | | DefKind::Field |
2038 | | DefKind::LifetimeParam |
2039 | | DefKind::GlobalAsm |
2040 | | DefKind::SyntheticCoroutineBody => false, |
2041 | } |
2042 | } |
2043 | |
2044 | #[inline] |
2045 | pub fn is_const_trait(self, def_id: DefId) -> bool { |
2046 | self.trait_def(def_id).constness == hir::Constness::Const |
2047 | } |
2048 | |
2049 | #[inline] |
2050 | pub fn is_const_default_method(self, def_id: DefId) -> bool { |
2051 | matches!(self.trait_of_item(def_id), Some(trait_id) if self.is_const_trait(trait_id)) |
2052 | } |
2053 | |
2054 | pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool { |
2055 | if self.def_kind(def_id) != DefKind::AssocFn { |
2056 | return false; |
2057 | } |
2058 | |
2059 | let Some(item) = self.opt_associated_item(def_id) else { |
2060 | return false; |
2061 | }; |
2062 | if item.container != ty::AssocItemContainer::Impl { |
2063 | return false; |
2064 | } |
2065 | |
2066 | let Some(trait_item_def_id) = item.trait_item_def_id else { |
2067 | return false; |
2068 | }; |
2069 | |
2070 | return !self |
2071 | .associated_types_for_impl_traits_in_associated_fn(trait_item_def_id) |
2072 | .is_empty(); |
2073 | } |
2074 | } |
2075 | |
2076 | pub fn int_ty(ity: ast::IntTy) -> IntTy { |
2077 | match ity { |
2078 | ast::IntTy::Isize => IntTy::Isize, |
2079 | ast::IntTy::I8 => IntTy::I8, |
2080 | ast::IntTy::I16 => IntTy::I16, |
2081 | ast::IntTy::I32 => IntTy::I32, |
2082 | ast::IntTy::I64 => IntTy::I64, |
2083 | ast::IntTy::I128 => IntTy::I128, |
2084 | } |
2085 | } |
2086 | |
2087 | pub fn uint_ty(uty: ast::UintTy) -> UintTy { |
2088 | match uty { |
2089 | ast::UintTy::Usize => UintTy::Usize, |
2090 | ast::UintTy::U8 => UintTy::U8, |
2091 | ast::UintTy::U16 => UintTy::U16, |
2092 | ast::UintTy::U32 => UintTy::U32, |
2093 | ast::UintTy::U64 => UintTy::U64, |
2094 | ast::UintTy::U128 => UintTy::U128, |
2095 | } |
2096 | } |
2097 | |
2098 | pub fn float_ty(fty: ast::FloatTy) -> FloatTy { |
2099 | match fty { |
2100 | ast::FloatTy::F16 => FloatTy::F16, |
2101 | ast::FloatTy::F32 => FloatTy::F32, |
2102 | ast::FloatTy::F64 => FloatTy::F64, |
2103 | ast::FloatTy::F128 => FloatTy::F128, |
2104 | } |
2105 | } |
2106 | |
2107 | pub fn ast_int_ty(ity: IntTy) -> ast::IntTy { |
2108 | match ity { |
2109 | IntTy::Isize => ast::IntTy::Isize, |
2110 | IntTy::I8 => ast::IntTy::I8, |
2111 | IntTy::I16 => ast::IntTy::I16, |
2112 | IntTy::I32 => ast::IntTy::I32, |
2113 | IntTy::I64 => ast::IntTy::I64, |
2114 | IntTy::I128 => ast::IntTy::I128, |
2115 | } |
2116 | } |
2117 | |
2118 | pub fn ast_uint_ty(uty: UintTy) -> ast::UintTy { |
2119 | match uty { |
2120 | UintTy::Usize => ast::UintTy::Usize, |
2121 | UintTy::U8 => ast::UintTy::U8, |
2122 | UintTy::U16 => ast::UintTy::U16, |
2123 | UintTy::U32 => ast::UintTy::U32, |
2124 | UintTy::U64 => ast::UintTy::U64, |
2125 | UintTy::U128 => ast::UintTy::U128, |
2126 | } |
2127 | } |
2128 | |
2129 | pub fn provide(providers: &mut Providers) { |
2130 | closure::provide(providers); |
2131 | context::provide(providers); |
2132 | erase_regions::provide(providers); |
2133 | inhabitedness::provide(providers); |
2134 | util::provide(providers); |
2135 | print::provide(providers); |
2136 | super::util::bug::provide(providers); |
2137 | *providers = Providers { |
2138 | trait_impls_of: trait_def::trait_impls_of_provider, |
2139 | incoherent_impls: trait_def::incoherent_impls_provider, |
2140 | trait_impls_in_crate: trait_def::trait_impls_in_crate_provider, |
2141 | traits: trait_def::traits_provider, |
2142 | vtable_allocation: vtable::vtable_allocation_provider, |
2143 | ..*providers |
2144 | }; |
2145 | } |
2146 | |
2147 | /// A map for the local crate mapping each type to a vector of its |
2148 | /// inherent impls. This is not meant to be used outside of coherence; |
2149 | /// rather, you should request the vector for a specific type via |
2150 | /// `tcx.inherent_impls(def_id)` so as to minimize your dependencies |
2151 | /// (constructing this map requires touching the entire crate). |
2152 | #[derive(Clone, Debug, Default, HashStable)] |
2153 | pub struct CrateInherentImpls { |
2154 | pub inherent_impls: FxIndexMap<LocalDefId, Vec<DefId>>, |
2155 | pub incoherent_impls: FxIndexMap<SimplifiedType, Vec<LocalDefId>>, |
2156 | } |
2157 | |
2158 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)] |
2159 | pub struct SymbolName<'tcx> { |
2160 | /// `&str` gives a consistent ordering, which ensures reproducible builds. |
2161 | pub name: &'tcx str, |
2162 | } |
2163 | |
2164 | impl<'tcx> SymbolName<'tcx> { |
2165 | pub fn new(tcx: TyCtxt<'tcx>, name: &str) -> SymbolName<'tcx> { |
2166 | SymbolName { name: tcx.arena.alloc_str(string:name) } |
2167 | } |
2168 | } |
2169 | |
2170 | impl<'tcx> fmt::Display for SymbolName<'tcx> { |
2171 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
2172 | fmt::Display::fmt(&self.name, f:fmt) |
2173 | } |
2174 | } |
2175 | |
2176 | impl<'tcx> fmt::Debug for SymbolName<'tcx> { |
2177 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
2178 | fmt::Display::fmt(&self.name, f:fmt) |
2179 | } |
2180 | } |
2181 | |
2182 | #[derive(Debug, Default, Copy, Clone)] |
2183 | pub struct InferVarInfo { |
2184 | /// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo` |
2185 | /// obligation, where: |
2186 | /// |
2187 | /// * `Foo` is not `Sized` |
2188 | /// * `(): Foo` may be satisfied |
2189 | pub self_in_trait: bool, |
2190 | /// This is true if we identified that this Ty (`?T`) is found in a `<_ as |
2191 | /// _>::AssocType = ?T` |
2192 | pub output: bool, |
2193 | } |
2194 | |
2195 | /// The constituent parts of a type level constant of kind ADT or array. |
2196 | #[derive(Copy, Clone, Debug, HashStable)] |
2197 | pub struct DestructuredConst<'tcx> { |
2198 | pub variant: Option<VariantIdx>, |
2199 | pub fields: &'tcx [ty::Const<'tcx>], |
2200 | } |
2201 | |
2202 | // Some types are used a lot. Make sure they don't unintentionally get bigger. |
2203 | #[cfg(target_pointer_width = "64")] |
2204 | mod size_asserts { |
2205 | use rustc_data_structures::static_assert_size; |
2206 | |
2207 | use super::*; |
2208 | // tidy-alphabetical-start |
2209 | static_assert_size!(PredicateKind<'_>, 32); |
2210 | static_assert_size!(WithCachedTypeInfo<TyKind<'_>>, 48); |
2211 | // tidy-alphabetical-end |
2212 | } |
2213 |
Definitions
- ResolverOutputs
- global_ctxt
- ast_lowering
- ResolverGlobalCtxt
- visibilities_for_hashing
- expn_that_defined
- effective_visibilities
- extern_crate_map
- maybe_unused_trait_imports
- module_children
- glob_map
- main_def
- trait_impls
- proc_macros
- confused_type_with_std_module
- doc_link_resolutions
- doc_link_traits_in_scope
- all_macro_rules
- stripped_cfg_items
- ResolverAstLowering
- legacy_const_generic_args
- partial_res_map
- import_res_map
- label_res_map
- lifetimes_res_map
- extra_lifetime_params_map
- next_node_id
- node_id_to_def_id
- trait_map
- lifetime_elision_allowed
- lint_buffer
- delegation_fn_sigs
- DelegationFnSig
- header
- param_count
- has_self
- c_variadic
- target_feature
- MainDefinition
- res
- is_import
- span
- opt_fn_def_id
- ImplHeader
- impl_def_id
- impl_args
- self_ty
- trait_ref
- predicates
- ImplTraitHeader
- trait_ref
- polarity
- safety
- constness
- ImplSubject
- Trait
- Inherent
- Asyncness
- Yes
- No
- is_async
- Visibility
- Public
- Restricted
- to_string
- ClosureSizeProfileData
- before_feature_tys
- after_feature_tys
- opt_parent
- parent
- opt_local_parent
- local_parent
- is_descendant_of
- is_public
- map_id
- to_def_id
- is_accessible_from
- is_at_least
- expect_local
- is_visible_locally
- CrateVariancesMap
- variances
- CReaderCacheKey
- cnum
- pos
- Ty
- Kind
- kind
- flags
- outer_exclusive_binder
- has_name
- CratePredicatesMap
- predicates
- Term
- ptr
- marker
- Kind
- kind
- fmt
- from
- from
- hash_stable
- try_fold_with
- visit_with
- encode
- decode
- unpack
- as_type
- expect_type
- as_const
- expect_const
- into_arg
- to_alias_term
- is_infer
- pack
- ParamTerm
- Ty
- Const
- index
- TermVid
- Ty
- Const
- from
- from
- InstantiatedPredicates
- predicates
- spans
- empty
- is_empty
- iter
- Item
- IntoIter
- into_iter
- Item
- IntoIter
- into_iter
- OpaqueHiddenType
- span
- ty
- build_mismatch_error
- remap_generic_params_to_declaration_params
- def_id
- args
- Placeholder
- universe
- bound
- find_const_ty_from_env
- PlaceholderRegion
- universe
- var
- with_updated_universe
- new
- PlaceholderType
- universe
- var
- with_updated_universe
- new
- BoundConst
- var
- ty
- PlaceholderConst
- universe
- var
- with_updated_universe
- new
- Clauses
- flags
- outer_exclusive_binder
- ParamEnv
- caller_bounds
- caller_bounds
- empty
- caller_bounds
- new
- and
- ParamEnvAnd
- param_env
- value
- into_parts
- TypingEnv
- typing_mode
- param_env
- fully_monomorphized
- non_body_analysis
- post_analysis
- with_post_analysis_normalized
- typing_mode
- param_env
- as_query_input
- PseudoCanonicalInput
- typing_env
- value
- Destructor
- did
- constness
- AsyncDestructor
- ctor
- future
- VariantFlags
- VariantDef
- def_id
- ctor
- name
- discr
- fields
- tainted
- flags
- new
- is_field_list_non_exhaustive
- field_list_has_applicable_non_exhaustive
- ident
- has_errors
- ctor_kind
- ctor_def_id
- single_field
- tail_opt
- tail
- has_unsafe_fields
- eq
- hash
- def_id
- VariantDiscr
- Explicit
- Relative
- FieldDef
- did
- name
- vis
- safety
- value
- eq
- hash
- did
- ty
- ident
- ImplOverlapKind
- Permitted
- marker
- ImplTraitInTraitData
- Trait
- fn_def_id
- opaque_def_id
- Impl
- fn_def_id
- typeck_body
- provided_trait_methods
- repr_options_of_def
- opt_item_name
- item_name
- opt_item_ident
- item_ident
- opt_associated_item
- opt_rpitit_info
- find_field_index
- impls_are_allowed_to_overlap
- expect_variant_res
- instance_mir
- get_attrs_unchecked
- get_attrs
- get_all_attrs
- get_diagnostic_attr
- get_attrs_by_path
- get_attr
- has_attr
- has_attrs_with_path
- trait_is_auto
- trait_is_coinductive
- trait_is_alias
- coroutine_layout
- trait_id_of_impl
- trait_of_item
- impl_of_method
- is_builtin_derived
- is_automatically_derived
- span_of_impl
- hygienic_eq
- adjust_ident
- adjust_ident_and_get_scope
- is_const_fn
- is_conditionally_const
- parent
- is_const_trait
- is_const_default_method
- impl_method_has_trait_impl_trait_tys
- int_ty
- uint_ty
- float_ty
- ast_int_ty
- ast_uint_ty
- provide
- CrateInherentImpls
- inherent_impls
- incoherent_impls
- SymbolName
- name
- new
- fmt
- fmt
- InferVarInfo
- self_in_trait
- output
- DestructuredConst
- variant
Learn Rust with the experts
Find out more