| 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) => self.is_accessible_from(module:id, tcx), |
| 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| addr | tag), marker: PhantomData } |
| 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- >
= env.caller_bounds().iter().filter_map(|clause: Clause<'tcx>| { |
| 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 | |