2020-12-20 00:08:27 -08:00
|
|
|
//! Defines how the compiler represents types internally.
|
|
|
|
|
//!
|
|
|
|
|
//! Two important entities in this module are:
|
|
|
|
|
//!
|
|
|
|
|
//! - [`rustc_middle::ty::Ty`], used to represent the semantics of a type.
|
|
|
|
|
//! - [`rustc_middle::ty::TyCtxt`], the central data structure in the compiler.
|
|
|
|
|
//!
|
2022-03-30 15:14:15 -04:00
|
|
|
//! For more information, see ["The `ty` module: representing types"] in the rustc-dev-guide.
|
2020-12-20 00:08:27 -08:00
|
|
|
//!
|
|
|
|
|
//! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html
|
|
|
|
|
|
2022-11-25 16:55:25 +00:00
|
|
|
#![allow(rustc::usage_of_ty_tykind)]
|
|
|
|
|
|
2022-08-31 20:16:02 +08:00
|
|
|
use std::assert_matches::assert_matches;
|
|
|
|
|
use std::fmt::Debug;
|
|
|
|
|
use std::hash::{Hash, Hasher};
|
2021-12-21 11:24:43 +08:00
|
|
|
use std::marker::PhantomData;
|
2023-05-15 06:24:45 +02:00
|
|
|
use std::num::NonZero;
|
2019-02-05 11:20:45 -06:00
|
|
|
use std::ptr::NonNull;
|
2024-08-26 16:45:15 +03:00
|
|
|
use std::{fmt, iter, str};
|
2024-07-29 08:13:50 +10:00
|
|
|
|
2022-05-02 09:31:56 +02:00
|
|
|
pub use adt::*;
|
|
|
|
|
pub use assoc::*;
|
2024-05-19 13:44:50 -04:00
|
|
|
pub use generic_args::{GenericArgKind, TermKind, *};
|
2022-05-02 09:31:56 +02:00
|
|
|
pub use generics::*;
|
2024-02-19 17:35:12 +00:00
|
|
|
pub use intrinsic::IntrinsicDef;
|
2024-11-02 19:33:00 -07:00
|
|
|
use rustc_abi::{Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, VariantIdx};
|
2025-08-23 20:17:32 +00:00
|
|
|
use rustc_ast::expand::typetree::{FncTree, Kind, Type, TypeTree};
|
2021-07-05 22:26:23 +02:00
|
|
|
use rustc_ast::node_id::NodeMap;
|
2025-02-12 15:04:26 +01:00
|
|
|
pub use rustc_ast_ir::{Movability, Mutability, try_visit};
|
2022-05-31 16:59:28 -07:00
|
|
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
|
2022-11-25 16:38:16 +00:00
|
|
|
use rustc_data_structures::intern::Interned;
|
2022-03-01 14:51:08 +00:00
|
|
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
2023-03-06 10:56:53 +00:00
|
|
|
use rustc_data_structures::steal::Steal;
|
2023-08-09 19:54:58 +00:00
|
|
|
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
2025-08-21 20:30:28 -07:00
|
|
|
use rustc_errors::{Diag, ErrorGuaranteed, LintBuffer};
|
2025-07-31 11:00:40 +02:00
|
|
|
use rustc_hir::attrs::{AttributeKind, StrippedCfgItem};
|
2022-02-01 20:30:32 +08:00
|
|
|
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
|
2024-03-14 15:42:14 +03:00
|
|
|
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
|
2025-07-31 11:00:40 +02:00
|
|
|
use rustc_hir::{LangItem, attrs as attr, find_attr};
|
2023-04-19 10:57:17 +00:00
|
|
|
use rustc_index::IndexVec;
|
2024-08-26 16:45:15 +03:00
|
|
|
use rustc_index::bit_set::BitMatrix;
|
2024-04-29 11:14:55 +10:00
|
|
|
use rustc_macros::{
|
2024-05-19 13:44:50 -04:00
|
|
|
Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable,
|
|
|
|
|
extension,
|
2024-04-29 11:14:55 +10:00
|
|
|
};
|
2020-11-14 16:48:54 +01:00
|
|
|
use rustc_query_system::ich::StableHashingContext;
|
2022-09-05 14:03:53 +10:00
|
|
|
use rustc_serialize::{Decodable, Encodable};
|
2023-03-06 10:56:23 +00:00
|
|
|
pub use rustc_session::lint::RegisteredTools;
|
2021-07-05 22:26:23 +02:00
|
|
|
use rustc_span::hygiene::MacroKind;
|
2025-07-30 08:54:12 +10:00
|
|
|
use rustc_span::{DUMMY_SP, ExpnId, ExpnKind, Ident, Span, Symbol, sym};
|
2025-05-01 18:40:38 +02:00
|
|
|
pub use rustc_type_ir::data_structures::{DelayedMap, DelayedSet};
|
2025-05-13 07:33:51 +00:00
|
|
|
pub use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
2025-05-01 18:40:38 +02:00
|
|
|
#[allow(
|
|
|
|
|
hidden_glob_reexports,
|
|
|
|
|
rustc::usage_of_type_ir_inherent,
|
|
|
|
|
rustc::non_glob_import_of_type_ir_inherent
|
|
|
|
|
)]
|
|
|
|
|
use rustc_type_ir::inherent;
|
2024-06-04 16:02:36 -04:00
|
|
|
pub use rustc_type_ir::relate::VarianceDiagInfo;
|
2025-07-17 09:21:51 +00:00
|
|
|
pub use rustc_type_ir::solve::{CandidatePreferenceMode, SizedTraitKind};
|
2025-02-24 09:30:42 +11:00
|
|
|
pub use rustc_type_ir::*;
|
2025-05-01 18:40:38 +02:00
|
|
|
#[allow(hidden_glob_reexports, unused_imports)]
|
|
|
|
|
use rustc_type_ir::{InferCtxtLike, Interner};
|
2025-09-12 06:11:18 +00:00
|
|
|
use tracing::{debug, instrument, trace};
|
2022-05-02 09:31:56 +02:00
|
|
|
pub use vtable::*;
|
2025-07-31 11:00:40 +02:00
|
|
|
use {rustc_ast as ast, rustc_hir as hir};
|
2015-09-06 21:51:58 +03:00
|
|
|
|
2021-07-09 22:40:51 +08:00
|
|
|
pub use self::closure::{
|
2024-04-09 11:11:17 -04:00
|
|
|
BorrowKind, CAPTURE_STRUCT_LOCAL, CaptureInfo, CapturedPlace, ClosureTypeInfo,
|
|
|
|
|
MinCaptureInformationMap, MinCaptureList, RootVariableMinCaptureList, UpvarCapture, UpvarId,
|
|
|
|
|
UpvarPath, analyze_coroutine_closure_captures, is_ancestor_or_same_capture,
|
|
|
|
|
place_to_string_for_capture,
|
2021-07-09 22:40:51 +08:00
|
|
|
};
|
2024-01-30 15:53:07 +00:00
|
|
|
pub use self::consts::{
|
2025-05-12 13:34:46 +02:00
|
|
|
AnonConstKind, AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr,
|
|
|
|
|
ExprKind, ScalarInt, UnevaluatedConst, ValTree, ValTreeKind, Value,
|
2024-01-30 15:53:07 +00:00
|
|
|
};
|
2018-11-16 22:56:18 +01:00
|
|
|
pub use self::context::{
|
2025-10-17 15:50:26 +00:00
|
|
|
CtxtInterners, CurrentGcx, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls,
|
2018-11-16 22:56:18 +01:00
|
|
|
};
|
2025-03-13 16:59:55 +00:00
|
|
|
pub use self::fold::*;
|
2025-07-29 01:13:50 +00:00
|
|
|
pub use self::instance::{Instance, InstanceKind, ReifyReason, UnusedGenericParams};
|
2024-03-24 22:49:31 +01:00
|
|
|
pub use self::list::{List, ListWithCachedTypeInfo};
|
2024-06-15 17:41:49 -04:00
|
|
|
pub use self::opaque_types::OpaqueTypeKey;
|
2023-02-02 13:57:36 +00:00
|
|
|
pub use self::pattern::{Pattern, PatternKind};
|
2024-01-30 15:53:07 +00:00
|
|
|
pub use self::predicate::{
|
2025-07-15 16:01:43 +00:00
|
|
|
AliasTerm, ArgOutlivesPredicate, Clause, ClauseKind, CoercePredicate, ExistentialPredicate,
|
2024-10-20 19:49:11 +00:00
|
|
|
ExistentialPredicateStableCmpExt, ExistentialProjection, ExistentialTraitRef,
|
|
|
|
|
HostEffectPredicate, NormalizesTo, OutlivesPredicate, PolyCoercePredicate,
|
|
|
|
|
PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef,
|
|
|
|
|
PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
|
|
|
|
|
PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
|
2025-01-18 18:47:11 +00:00
|
|
|
RegionOutlivesPredicate, SubtypePredicate, TraitPredicate, TraitRef, TypeOutlivesPredicate,
|
2024-01-30 15:53:07 +00:00
|
|
|
};
|
|
|
|
|
pub use self::region::{
|
2024-12-06 14:46:28 +01:00
|
|
|
BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region,
|
|
|
|
|
RegionKind, RegionVid,
|
2024-01-30 15:53:07 +00:00
|
|
|
};
|
2022-04-01 21:12:18 +08:00
|
|
|
pub use self::rvalue_scopes::RvalueScopes;
|
2021-03-09 20:53:48 -08:00
|
|
|
pub use self::sty::{
|
2024-05-13 12:40:08 -04:00
|
|
|
AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
|
2024-05-31 14:13:46 -04:00
|
|
|
CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst,
|
2024-10-18 00:28:43 +02:00
|
|
|
ParamTy, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs,
|
2021-03-09 20:53:48 -08:00
|
|
|
};
|
2017-05-11 16:01:19 +02:00
|
|
|
pub use self::trait_def::TraitDef;
|
2022-12-15 20:40:16 +01:00
|
|
|
pub use self::typeck_results::{
|
2023-10-23 16:11:48 -04:00
|
|
|
CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, IsIdentity,
|
2025-02-03 01:50:14 -08:00
|
|
|
Rust2024IncompatiblePatInfo, TypeckResults, UserType, UserTypeAnnotationIndex, UserTypeKind,
|
2022-12-15 20:40:16 +01:00
|
|
|
};
|
2022-08-31 20:16:02 +08:00
|
|
|
use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
|
2021-12-21 11:24:43 +08:00
|
|
|
use crate::metadata::ModChild;
|
2022-09-22 16:19:53 +03:00
|
|
|
use crate::middle::privacy::EffectiveVisibilities;
|
2024-08-26 16:45:15 +03:00
|
|
|
use crate::mir::{Body, CoroutineLayout, CoroutineSavedLocal, SourceInfo};
|
2024-11-15 13:53:31 +01:00
|
|
|
use crate::query::{IntoQueryParam, Providers};
|
2019-02-05 11:20:45 -06:00
|
|
|
use crate::ty;
|
2025-03-13 17:53:36 +00:00
|
|
|
use crate::ty::codec::{TyDecoder, TyEncoder};
|
2019-11-18 10:33:05 -08:00
|
|
|
pub use crate::ty::diagnostics::*;
|
2022-03-15 16:30:30 +01:00
|
|
|
use crate::ty::fast_reject::SimplifiedType;
|
2025-05-11 20:58:52 +07:00
|
|
|
use crate::ty::layout::LayoutError;
|
2021-03-09 21:47:12 -08:00
|
|
|
use crate::ty::util::Discr;
|
2025-04-26 01:54:09 +00:00
|
|
|
use crate::ty::walk::TypeWalker;
|
2015-12-22 16:39:33 -05:00
|
|
|
|
2022-07-09 09:35:06 +00:00
|
|
|
pub mod abstract_const;
|
2015-09-14 14:55:56 +03:00
|
|
|
pub mod adjustment;
|
2015-09-06 18:32:34 +03:00
|
|
|
pub mod cast;
|
2017-10-18 17:48:36 +02:00
|
|
|
pub mod codec;
|
2015-09-06 21:51:58 +03:00
|
|
|
pub mod error;
|
2015-09-06 18:32:34 +03:00
|
|
|
pub mod fast_reject;
|
2016-12-11 22:30:14 +08:00
|
|
|
pub mod inhabitedness;
|
2016-04-18 16:03:16 +03:00
|
|
|
pub mod layout;
|
2020-01-05 19:43:25 +01:00
|
|
|
pub mod normalize_erasing_regions;
|
2023-02-02 13:57:36 +00:00
|
|
|
pub mod pattern;
|
2018-12-04 19:13:37 +02:00
|
|
|
pub mod print;
|
2015-09-06 18:32:34 +03:00
|
|
|
pub mod relate;
|
2025-02-23 03:34:33 +00:00
|
|
|
pub mod significant_drop_order;
|
2015-12-22 16:39:33 -05:00
|
|
|
pub mod trait_def;
|
2015-09-14 14:55:56 +03:00
|
|
|
pub mod util;
|
2021-06-20 17:43:25 +08:00
|
|
|
pub mod vtable;
|
2015-09-06 18:32:34 +03:00
|
|
|
|
2021-03-09 21:47:12 -08:00
|
|
|
mod adt;
|
2021-03-09 21:27:03 -08:00
|
|
|
mod assoc;
|
2021-03-10 12:55:00 -08:00
|
|
|
mod closure;
|
2020-06-19 18:57:15 +02:00
|
|
|
mod consts;
|
2015-09-06 21:51:58 +03:00
|
|
|
mod context;
|
2019-11-18 10:33:05 -08:00
|
|
|
mod diagnostics;
|
2024-07-06 12:21:00 -04:00
|
|
|
mod elaborate_impl;
|
2021-03-09 20:53:48 -08:00
|
|
|
mod erase_regions;
|
2025-03-13 17:09:25 +00:00
|
|
|
mod fold;
|
2023-07-11 22:35:29 +01:00
|
|
|
mod generic_args;
|
2021-03-09 21:10:07 -08:00
|
|
|
mod generics;
|
2020-11-14 17:04:40 +01:00
|
|
|
mod impls_ty;
|
2017-02-08 18:31:03 +01:00
|
|
|
mod instance;
|
2024-02-19 22:51:45 +00:00
|
|
|
mod intrinsic;
|
2020-05-09 21:02:13 +02:00
|
|
|
mod list;
|
2022-09-27 11:37:10 +00:00
|
|
|
mod opaque_types;
|
2024-01-30 15:53:07 +00:00
|
|
|
mod predicate;
|
|
|
|
|
mod region;
|
2022-04-01 21:12:18 +08:00
|
|
|
mod rvalue_scopes;
|
2015-09-06 21:51:58 +03:00
|
|
|
mod structural_impls;
|
2023-07-12 21:38:55 -04:00
|
|
|
#[allow(hidden_glob_reexports)]
|
2015-09-06 21:51:58 +03:00
|
|
|
mod sty;
|
2022-12-15 20:40:16 +01:00
|
|
|
mod typeck_results;
|
2025-03-13 17:09:25 +00:00
|
|
|
mod visit;
|
2015-09-06 21:51:58 +03:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
// Data types
|
2011-05-09 12:27:03 -07:00
|
|
|
|
2023-08-09 19:54:58 +00:00
|
|
|
#[derive(Debug, HashStable)]
|
2022-10-25 14:45:02 +04:00
|
|
|
pub struct ResolverGlobalCtxt {
|
2023-12-05 23:16:08 +03:00
|
|
|
pub visibilities_for_hashing: Vec<(LocalDefId, Visibility)>,
|
2022-05-30 18:49:17 +02:00
|
|
|
/// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
|
2023-08-09 19:54:58 +00:00
|
|
|
pub expn_that_defined: UnordMap<LocalDefId, ExpnId>,
|
2022-09-22 16:19:53 +03:00
|
|
|
pub effective_visibilities: EffectiveVisibilities,
|
2025-03-14 17:18:41 +03:00
|
|
|
pub extern_crate_map: UnordMap<LocalDefId, CrateNum>,
|
2022-05-31 16:59:28 -07:00
|
|
|
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
|
2023-04-27 18:34:43 +03:00
|
|
|
pub module_children: LocalDefIdMap<Vec<ModChild>>,
|
2025-05-05 16:36:04 +03:00
|
|
|
pub glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
|
2021-04-26 01:09:35 +08:00
|
|
|
pub main_def: Option<MainDefinition>,
|
2022-01-25 17:40:10 -06:00
|
|
|
pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
|
2021-07-16 22:22:08 +02:00
|
|
|
/// A list of proc macro LocalDefIds, written out in the order in which
|
|
|
|
|
/// they are declared in the static array generated by proc_macro_harness.
|
|
|
|
|
pub proc_macros: Vec<LocalDefId>,
|
2021-09-06 11:20:59 -05:00
|
|
|
/// Mapping from ident span to path span for paths that don't exist as written, but that
|
|
|
|
|
/// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
|
2024-10-02 08:25:55 +03:00
|
|
|
pub confused_type_with_std_module: FxIndexMap<Span, Span>,
|
2024-10-03 08:23:30 +03:00
|
|
|
pub doc_link_resolutions: FxIndexMap<LocalDefId, DocLinkResMap>,
|
|
|
|
|
pub doc_link_traits_in_scope: FxIndexMap<LocalDefId, Vec<DefId>>,
|
2023-08-09 19:54:58 +00:00
|
|
|
pub all_macro_rules: UnordSet<Symbol>,
|
|
|
|
|
pub stripped_cfg_items: Vec<StrippedCfgItem>,
|
2022-06-15 19:42:43 +02:00
|
|
|
}
|
2021-07-05 22:26:23 +02:00
|
|
|
|
2022-06-15 19:42:43 +02:00
|
|
|
/// Resolutions that should only be used for lowering.
|
|
|
|
|
/// This struct is meant to be consumed by lowering.
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct ResolverAstLowering {
|
2021-07-05 22:26:23 +02:00
|
|
|
pub legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,
|
|
|
|
|
|
|
|
|
|
/// Resolutions for nodes that have a single resolution.
|
|
|
|
|
pub partial_res_map: NodeMap<hir::def::PartialRes>,
|
|
|
|
|
/// Resolutions for import nodes, which have multiple resolutions in different namespaces.
|
|
|
|
|
pub import_res_map: NodeMap<hir::def::PerNS<Option<Res<ast::NodeId>>>>,
|
|
|
|
|
/// Resolutions for labels (node IDs of their corresponding blocks or loops).
|
|
|
|
|
pub label_res_map: NodeMap<ast::NodeId>,
|
|
|
|
|
/// Resolutions for lifetimes.
|
|
|
|
|
pub lifetimes_res_map: NodeMap<LifetimeRes>,
|
|
|
|
|
/// Lifetime parameters that lowering will have to introduce.
|
|
|
|
|
pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, LifetimeRes)>>,
|
|
|
|
|
|
|
|
|
|
pub next_node_id: ast::NodeId,
|
|
|
|
|
|
2023-12-18 21:02:21 +01:00
|
|
|
pub node_id_to_def_id: NodeMap<LocalDefId>,
|
2021-07-05 22:26:23 +02:00
|
|
|
|
|
|
|
|
pub trait_map: NodeMap<Vec<hir::TraitCandidate>>,
|
2022-11-06 09:33:52 +00:00
|
|
|
/// List functions and methods for which lifetime elision was successful.
|
|
|
|
|
pub lifetime_elision_allowed: FxHashSet<ast::NodeId>,
|
2023-03-06 10:56:53 +00:00
|
|
|
|
|
|
|
|
/// Lints that were emitted by the resolver and early lints.
|
|
|
|
|
pub lint_buffer: Steal<LintBuffer>,
|
2023-11-26 15:57:31 +03:00
|
|
|
|
|
|
|
|
/// Information about functions signatures for delegation items expansion
|
2024-03-14 15:42:14 +03:00
|
|
|
pub delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct DelegationFnSig {
|
|
|
|
|
pub header: ast::FnHeader,
|
|
|
|
|
pub param_count: usize,
|
|
|
|
|
pub has_self: bool,
|
|
|
|
|
pub c_variadic: bool,
|
2024-12-13 12:19:46 +00:00
|
|
|
pub target_feature: bool,
|
2021-04-26 01:09:35 +08:00
|
|
|
}
|
|
|
|
|
|
2023-08-09 19:54:58 +00:00
|
|
|
#[derive(Clone, Copy, Debug, HashStable)]
|
2021-04-26 01:09:35 +08:00
|
|
|
pub struct MainDefinition {
|
|
|
|
|
pub res: Res<ast::NodeId>,
|
|
|
|
|
pub is_import: bool,
|
|
|
|
|
pub span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl MainDefinition {
|
|
|
|
|
pub fn opt_fn_def_id(self) -> Option<DefId> {
|
|
|
|
|
if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None }
|
|
|
|
|
}
|
2016-12-15 11:13:24 +00:00
|
|
|
}
|
|
|
|
|
|
2024-03-05 20:19:05 +01:00
|
|
|
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
2024-02-10 21:46:44 +00:00
|
|
|
pub struct ImplTraitHeader<'tcx> {
|
2024-05-26 20:03:47 -04:00
|
|
|
pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
|
2024-02-10 21:46:44 +00:00
|
|
|
pub polarity: ImplPolarity,
|
2024-05-17 14:17:48 -03:00
|
|
|
pub safety: hir::Safety,
|
2024-12-10 10:12:36 +00:00
|
|
|
pub constness: hir::Constness,
|
2024-02-10 21:46:44 +00:00
|
|
|
}
|
|
|
|
|
|
2022-06-17 10:53:29 +01:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
|
2023-09-14 22:38:07 +00:00
|
|
|
#[derive(TypeFoldable, TypeVisitable)]
|
|
|
|
|
pub enum Asyncness {
|
|
|
|
|
Yes,
|
|
|
|
|
No,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Asyncness {
|
|
|
|
|
pub fn is_async(self) -> bool {
|
|
|
|
|
matches!(self, Asyncness::Yes)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-28 19:53:01 +02:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Encodable, Decodable, HashStable)]
|
2022-08-28 00:10:06 +03:00
|
|
|
pub enum Visibility<Id = LocalDefId> {
|
2016-03-25 06:08:11 +00:00
|
|
|
/// Visible everywhere (including in other crates).
|
|
|
|
|
Public,
|
|
|
|
|
/// Visible only in the given crate-local module.
|
2022-08-28 00:10:06 +03:00
|
|
|
Restricted(Id),
|
2016-03-25 06:08:11 +00:00
|
|
|
}
|
|
|
|
|
|
2023-12-01 10:25:40 +08:00
|
|
|
impl Visibility {
|
|
|
|
|
pub fn to_string(self, def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
|
|
|
|
|
match self {
|
|
|
|
|
ty::Visibility::Restricted(restricted_id) => {
|
|
|
|
|
if restricted_id.is_top_level_module() {
|
|
|
|
|
"pub(crate)".to_string()
|
|
|
|
|
} else if restricted_id == tcx.parent_module_from_def_id(def_id).to_local_def_id() {
|
|
|
|
|
"pub(self)".to_string()
|
|
|
|
|
} else {
|
2025-05-03 20:10:56 +09:00
|
|
|
format!(
|
|
|
|
|
"pub(in crate{})",
|
|
|
|
|
tcx.def_path(restricted_id.to_def_id()).to_string_no_crate_verbose()
|
|
|
|
|
)
|
2023-12-01 10:25:40 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ty::Visibility::Public => "pub".to_string(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 10:53:29 +01:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
|
|
|
|
|
#[derive(TypeFoldable, TypeVisitable)]
|
2021-05-05 15:57:08 -04:00
|
|
|
pub struct ClosureSizeProfileData<'tcx> {
|
|
|
|
|
/// Tuple containing the types of closure captures before the feature `capture_disjoint_fields`
|
|
|
|
|
pub before_feature_tys: Ty<'tcx>,
|
|
|
|
|
/// Tuple containing the types of closure captures after the feature `capture_disjoint_fields`
|
|
|
|
|
pub after_feature_tys: Ty<'tcx>,
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 19:51:17 +04:00
|
|
|
impl TyCtxt<'_> {
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn opt_parent(self, id: DefId) -> Option<DefId> {
|
|
|
|
|
self.def_key(id).parent.map(|index| DefId { index, ..id })
|
|
|
|
|
}
|
2016-12-29 17:08:33 +08:00
|
|
|
|
2022-03-13 11:12:50 +01:00
|
|
|
#[inline]
|
2022-04-25 22:08:45 +03:00
|
|
|
#[track_caller]
|
2023-02-22 19:51:17 +04:00
|
|
|
pub fn parent(self, id: DefId) -> DefId {
|
2022-04-25 22:08:45 +03:00
|
|
|
match self.opt_parent(id) {
|
|
|
|
|
Some(id) => id,
|
|
|
|
|
// not `unwrap_or_else` to avoid breaking caller tracking
|
|
|
|
|
None => bug!("{id:?} doesn't have a parent"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
#[track_caller]
|
2023-02-22 19:51:17 +04:00
|
|
|
pub fn opt_local_parent(self, id: LocalDefId) -> Option<LocalDefId> {
|
2022-04-25 22:08:45 +03:00
|
|
|
self.opt_parent(id.to_def_id()).map(DefId::expect_local)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
#[track_caller]
|
2023-04-26 20:53:51 +02:00
|
|
|
pub fn local_parent(self, id: impl Into<LocalDefId>) -> LocalDefId {
|
|
|
|
|
self.parent(id.into().to_def_id()).expect_local()
|
2022-03-13 11:12:50 +01:00
|
|
|
}
|
|
|
|
|
|
2023-02-22 19:51:17 +04:00
|
|
|
pub fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool {
|
2016-12-29 17:08:33 +08:00
|
|
|
if descendant.krate != ancestor.krate {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while descendant != ancestor {
|
2022-04-25 22:08:45 +03:00
|
|
|
match self.opt_parent(descendant) {
|
2016-12-29 17:08:33 +08:00
|
|
|
Some(parent) => descendant = parent,
|
|
|
|
|
None => return false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
true
|
|
|
|
|
}
|
2016-04-27 02:29:59 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-28 00:10:06 +03:00
|
|
|
impl<Id> Visibility<Id> {
|
|
|
|
|
pub fn is_public(self) -> bool {
|
|
|
|
|
matches!(self, Visibility::Public)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn map_id<OutId>(self, f: impl FnOnce(Id) -> OutId) -> Visibility<OutId> {
|
|
|
|
|
match self {
|
|
|
|
|
Visibility::Public => Visibility::Public,
|
|
|
|
|
Visibility::Restricted(id) => Visibility::Restricted(f(id)),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<Id: Into<DefId>> Visibility<Id> {
|
|
|
|
|
pub fn to_def_id(self) -> Visibility<DefId> {
|
|
|
|
|
self.map_id(Into::into)
|
|
|
|
|
}
|
2016-03-31 07:03:00 +00:00
|
|
|
|
2022-08-28 00:10:06 +03:00
|
|
|
/// Returns `true` if an item with this visibility is accessible from the given module.
|
2023-02-22 19:51:17 +04:00
|
|
|
pub fn is_accessible_from(self, module: impl Into<DefId>, tcx: TyCtxt<'_>) -> bool {
|
2022-08-28 00:10:06 +03:00
|
|
|
match self {
|
|
|
|
|
// Public items are visible everywhere.
|
|
|
|
|
Visibility::Public => true,
|
2023-02-22 19:51:17 +04:00
|
|
|
Visibility::Restricted(id) => tcx.is_descendant_of(module.into(), id.into()),
|
2022-08-28 00:10:06 +03:00
|
|
|
}
|
2016-03-31 07:03:00 +00:00
|
|
|
}
|
2016-04-01 20:16:31 +00:00
|
|
|
|
2018-11-01 19:43:38 +00:00
|
|
|
/// Returns `true` if this visibility is at least as accessible as the given visibility
|
2023-02-22 19:51:17 +04:00
|
|
|
pub fn is_at_least(self, vis: Visibility<impl Into<DefId>>, tcx: TyCtxt<'_>) -> bool {
|
2022-08-28 00:10:06 +03:00
|
|
|
match vis {
|
|
|
|
|
Visibility::Public => self.is_public(),
|
2023-02-22 19:51:17 +04:00
|
|
|
Visibility::Restricted(id) => self.is_accessible_from(id, tcx),
|
2022-08-28 00:10:06 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-01 20:16:31 +00:00
|
|
|
|
2022-08-28 00:10:06 +03:00
|
|
|
impl Visibility<DefId> {
|
|
|
|
|
pub fn expect_local(self) -> Visibility {
|
|
|
|
|
self.map_id(|id| id.expect_local())
|
2016-04-01 20:16:31 +00:00
|
|
|
}
|
2017-11-29 11:20:49 -08:00
|
|
|
|
2022-11-27 11:15:06 +00:00
|
|
|
/// Returns `true` if this item is visible anywhere in the local crate.
|
2017-11-29 11:20:49 -08:00
|
|
|
pub fn is_visible_locally(self) -> bool {
|
|
|
|
|
match self {
|
|
|
|
|
Visibility::Public => true,
|
|
|
|
|
Visibility::Restricted(def_id) => def_id.is_local(),
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-03-25 06:08:11 +00:00
|
|
|
}
|
|
|
|
|
|
2017-04-24 11:15:12 -04:00
|
|
|
/// The crate variances map is computed during typeck and contains the
|
|
|
|
|
/// variance of every item in the local crate. You should not use it
|
|
|
|
|
/// directly, because to do so will make your pass dependent on the
|
|
|
|
|
/// HIR of every item in the local crate. Instead, use
|
2017-05-05 14:34:42 -04:00
|
|
|
/// `tcx.variances_of()` to get the variance for a *particular*
|
2017-04-24 11:15:12 -04:00
|
|
|
/// item.
|
2021-01-03 09:19:16 -05:00
|
|
|
#[derive(HashStable, Debug)]
|
2018-11-30 15:12:41 +01:00
|
|
|
pub struct CrateVariancesMap<'tcx> {
|
2017-04-24 11:15:12 -04:00
|
|
|
/// For each item with generics, maps to a vector of the variance
|
2019-02-08 14:53:55 +01:00
|
|
|
/// of its generics. If an item has no generics, it will have no
|
2017-04-24 11:15:12 -04:00
|
|
|
/// entry.
|
2023-01-17 12:05:01 +01:00
|
|
|
pub variances: DefIdMap<&'tcx [ty::Variance]>,
|
2017-04-24 11:15:12 -04:00
|
|
|
}
|
|
|
|
|
|
2015-05-05 19:36:47 +03:00
|
|
|
// Contains information needed to resolve types and (in the future) look up
|
|
|
|
|
// the types of AST nodes.
|
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
2015-07-08 12:27:32 -07:00
|
|
|
pub struct CReaderCacheKey {
|
2021-05-30 14:06:26 +02:00
|
|
|
pub cnum: Option<CrateNum>,
|
2015-05-05 19:36:47 +03:00
|
|
|
pub pos: usize,
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-28 14:23:49 +00:00
|
|
|
/// Use this rather than `TyKind`, whenever possible.
|
2024-03-21 13:10:28 +00:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 14:13:38 +11:00
|
|
|
#[rustc_diagnostic_item = "Ty"]
|
2022-02-23 08:06:22 -05:00
|
|
|
#[rustc_pass_by_value]
|
2022-11-25 16:55:25 +00:00
|
|
|
pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 14:13:38 +11:00
|
|
|
|
2024-05-10 14:59:56 -04:00
|
|
|
impl<'tcx> rustc_type_ir::inherent::IntoKind for Ty<'tcx> {
|
2023-11-22 23:44:58 +00:00
|
|
|
type Kind = TyKind<'tcx>;
|
|
|
|
|
|
2023-12-05 18:10:23 +00:00
|
|
|
fn kind(self) -> TyKind<'tcx> {
|
2023-12-15 23:19:51 +01:00
|
|
|
*self.kind()
|
2023-11-22 23:44:58 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-13 17:09:25 +00:00
|
|
|
impl<'tcx> rustc_type_ir::Flags for Ty<'tcx> {
|
2024-01-30 15:59:07 +00:00
|
|
|
fn flags(&self) -> TypeFlags {
|
|
|
|
|
self.0.flags
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn outer_exclusive_binder(&self) -> DebruijnIndex {
|
|
|
|
|
self.0.outer_exclusive_binder
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 01:13:56 -04:00
|
|
|
/// The crate outlives map is computed during typeck and contains the
|
|
|
|
|
/// outlives of every item in the local crate. You should not use it
|
|
|
|
|
/// directly, because to do so will make your pass dependent on the
|
|
|
|
|
/// HIR of every item in the local crate. Instead, use
|
|
|
|
|
/// `tcx.inferred_outlives_of()` to get the outlives for a *particular*
|
|
|
|
|
/// item.
|
2021-01-03 09:19:16 -05:00
|
|
|
#[derive(HashStable, Debug)]
|
2017-10-15 01:13:56 -04:00
|
|
|
pub struct CratePredicatesMap<'tcx> {
|
|
|
|
|
/// For each struct with outlive bounds, maps to a vector of the
|
|
|
|
|
/// predicate of its outlive bounds. If an item has no outlives
|
|
|
|
|
/// bounds, it will have no entry.
|
2023-12-21 11:12:37 +01:00
|
|
|
pub predicates: DefIdMap<&'tcx [(Clause<'tcx>, Span)]>,
|
2017-10-15 01:13:56 -04:00
|
|
|
}
|
|
|
|
|
|
2022-09-08 21:09:23 +01:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
2022-09-05 14:03:53 +10:00
|
|
|
pub struct Term<'tcx> {
|
2024-01-14 00:36:27 -05:00
|
|
|
ptr: NonNull<()>,
|
2022-09-05 14:03:53 +10:00
|
|
|
marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>,
|
2022-01-08 09:28:12 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-29 20:15:56 -04:00
|
|
|
impl<'tcx> rustc_type_ir::inherent::Term<TyCtxt<'tcx>> for Term<'tcx> {}
|
|
|
|
|
|
2024-05-19 13:44:50 -04:00
|
|
|
impl<'tcx> rustc_type_ir::inherent::IntoKind for Term<'tcx> {
|
|
|
|
|
type Kind = TermKind<'tcx>;
|
|
|
|
|
|
|
|
|
|
fn kind(self) -> Self::Kind {
|
2025-05-24 12:07:32 +00:00
|
|
|
self.kind()
|
2024-05-19 13:44:50 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-14 00:36:27 -05:00
|
|
|
unsafe impl<'tcx> rustc_data_structures::sync::DynSend for Term<'tcx> where
|
|
|
|
|
&'tcx (Ty<'tcx>, Const<'tcx>): rustc_data_structures::sync::DynSend
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
unsafe impl<'tcx> rustc_data_structures::sync::DynSync for Term<'tcx> where
|
|
|
|
|
&'tcx (Ty<'tcx>, Const<'tcx>): rustc_data_structures::sync::DynSync
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
unsafe impl<'tcx> Send for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): Send {}
|
|
|
|
|
unsafe impl<'tcx> Sync for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): Sync {}
|
|
|
|
|
|
2022-09-08 21:09:23 +01:00
|
|
|
impl Debug for Term<'_> {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2025-05-24 12:07:32 +00:00
|
|
|
match self.kind() {
|
2024-05-19 16:35:34 +02:00
|
|
|
TermKind::Ty(ty) => write!(f, "Term::Ty({ty:?})"),
|
|
|
|
|
TermKind::Const(ct) => write!(f, "Term::Const({ct:?})"),
|
|
|
|
|
}
|
2022-09-08 21:09:23 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-08 09:28:12 +00:00
|
|
|
impl<'tcx> From<Ty<'tcx>> for Term<'tcx> {
|
|
|
|
|
fn from(ty: Ty<'tcx>) -> Self {
|
2022-09-05 14:03:53 +10:00
|
|
|
TermKind::Ty(ty).pack()
|
2022-01-08 09:28:12 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-02 14:24:45 +11:00
|
|
|
impl<'tcx> From<Const<'tcx>> for Term<'tcx> {
|
|
|
|
|
fn from(c: Const<'tcx>) -> Self {
|
2022-09-05 14:03:53 +10:00
|
|
|
TermKind::Const(c).pack()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Term<'tcx> {
|
|
|
|
|
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
2025-05-24 12:07:32 +00:00
|
|
|
self.kind().hash_stable(hcx, hasher);
|
2022-09-05 14:03:53 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-22 02:18:40 +00:00
|
|
|
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> {
|
|
|
|
|
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
|
|
|
|
self,
|
|
|
|
|
folder: &mut F,
|
|
|
|
|
) -> Result<Self, F::Error> {
|
2025-05-24 12:07:32 +00:00
|
|
|
match self.kind() {
|
2024-05-19 13:44:50 -04:00
|
|
|
ty::TermKind::Ty(ty) => ty.try_fold_with(folder).map(Into::into),
|
|
|
|
|
ty::TermKind::Const(ct) => ct.try_fold_with(folder).map(Into::into),
|
|
|
|
|
}
|
2022-09-05 14:03:53 +10:00
|
|
|
}
|
2025-04-14 15:10:43 +00:00
|
|
|
|
|
|
|
|
fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
|
2025-05-24 12:07:32 +00:00
|
|
|
match self.kind() {
|
2025-04-14 15:10:43 +00:00
|
|
|
ty::TermKind::Ty(ty) => ty.fold_with(folder).into(),
|
|
|
|
|
ty::TermKind::Const(ct) => ct.fold_with(folder).into(),
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-09-05 14:03:53 +10:00
|
|
|
}
|
|
|
|
|
|
2023-02-22 02:18:40 +00:00
|
|
|
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
2025-05-24 12:07:32 +00:00
|
|
|
match self.kind() {
|
2024-05-19 13:44:50 -04:00
|
|
|
ty::TermKind::Ty(ty) => ty.visit_with(visitor),
|
|
|
|
|
ty::TermKind::Const(ct) => ct.visit_with(visitor),
|
|
|
|
|
}
|
2022-09-05 14:03:53 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-13 17:53:36 +00:00
|
|
|
impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Term<'tcx> {
|
2022-09-05 14:03:53 +10:00
|
|
|
fn encode(&self, e: &mut E) {
|
2025-05-24 12:07:32 +00:00
|
|
|
self.kind().encode(e)
|
2022-09-05 14:03:53 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-13 17:53:36 +00:00
|
|
|
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Term<'tcx> {
|
2022-09-05 14:03:53 +10:00
|
|
|
fn decode(d: &mut D) -> Self {
|
|
|
|
|
let res: TermKind<'tcx> = Decodable::decode(d);
|
|
|
|
|
res.pack()
|
2022-01-08 09:28:12 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> Term<'tcx> {
|
2022-09-05 14:03:53 +10:00
|
|
|
#[inline]
|
2025-05-24 12:07:32 +00:00
|
|
|
pub fn kind(self) -> TermKind<'tcx> {
|
2024-02-08 23:03:25 +01:00
|
|
|
let ptr =
|
|
|
|
|
unsafe { self.ptr.map_addr(|addr| NonZero::new_unchecked(addr.get() & !TAG_MASK)) };
|
2022-09-05 14:03:53 +10:00
|
|
|
// SAFETY: use of `Interned::new_unchecked` here is ok because these
|
|
|
|
|
// pointers were originally created from `Interned` types in `pack()`,
|
|
|
|
|
// and this is just going in the other direction.
|
|
|
|
|
unsafe {
|
2024-01-14 00:36:27 -05:00
|
|
|
match self.ptr.addr().get() & TAG_MASK {
|
2022-09-05 14:03:53 +10:00
|
|
|
TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked(
|
2024-01-14 00:36:27 -05:00
|
|
|
ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(),
|
2022-09-05 14:03:53 +10:00
|
|
|
))),
|
|
|
|
|
CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
|
2024-06-03 01:10:24 +01:00
|
|
|
ptr.cast::<WithCachedTypeInfo<ty::ConstKind<'tcx>>>().as_ref(),
|
2022-09-05 14:03:53 +10:00
|
|
|
))),
|
|
|
|
|
_ => core::intrinsics::unreachable(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-29 22:23:49 -04:00
|
|
|
pub fn as_type(&self) -> Option<Ty<'tcx>> {
|
2025-05-24 12:07:32 +00:00
|
|
|
if let TermKind::Ty(ty) = self.kind() { Some(ty) } else { None }
|
2022-01-08 09:28:12 +00:00
|
|
|
}
|
2022-06-25 10:42:23 -07:00
|
|
|
|
2024-05-29 22:23:49 -04:00
|
|
|
pub fn expect_type(&self) -> Ty<'tcx> {
|
|
|
|
|
self.as_type().expect("expected a type, but found a const")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn as_const(&self) -> Option<Const<'tcx>> {
|
2025-05-24 12:07:32 +00:00
|
|
|
if let TermKind::Const(c) = self.kind() { Some(c) } else { None }
|
2022-01-27 14:40:38 +00:00
|
|
|
}
|
2022-06-25 10:42:23 -07:00
|
|
|
|
2024-05-29 22:23:49 -04:00
|
|
|
pub fn expect_const(&self) -> Const<'tcx> {
|
|
|
|
|
self.as_const().expect("expected a const, but found a type")
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-25 10:42:23 -07:00
|
|
|
pub fn into_arg(self) -> GenericArg<'tcx> {
|
2025-05-24 12:07:32 +00:00
|
|
|
match self.kind() {
|
2022-09-05 14:03:53 +10:00
|
|
|
TermKind::Ty(ty) => ty.into(),
|
|
|
|
|
TermKind::Const(c) => c.into(),
|
2022-06-25 10:42:23 -07:00
|
|
|
}
|
|
|
|
|
}
|
2023-02-10 14:54:50 +00:00
|
|
|
|
2024-05-13 10:00:38 -04:00
|
|
|
pub fn to_alias_term(self) -> Option<AliasTerm<'tcx>> {
|
2025-05-24 12:07:32 +00:00
|
|
|
match self.kind() {
|
2023-05-09 18:56:43 +00:00
|
|
|
TermKind::Ty(ty) => match *ty.kind() {
|
2024-05-13 10:00:38 -04:00
|
|
|
ty::Alias(_kind, alias_ty) => Some(alias_ty.into()),
|
2023-02-10 14:54:50 +00:00
|
|
|
_ => None,
|
|
|
|
|
},
|
|
|
|
|
TermKind::Const(ct) => match ct.kind() {
|
2024-05-13 10:00:38 -04:00
|
|
|
ConstKind::Unevaluated(uv) => Some(uv.into()),
|
2023-02-10 14:54:50 +00:00
|
|
|
_ => None,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_infer(&self) -> bool {
|
2025-05-24 12:07:32 +00:00
|
|
|
match self.kind() {
|
2023-03-06 19:45:03 +00:00
|
|
|
TermKind::Ty(ty) => ty.is_ty_var(),
|
2023-02-10 14:54:50 +00:00
|
|
|
TermKind::Const(ct) => ct.is_ct_infer(),
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-04-26 01:54:09 +00:00
|
|
|
|
2025-06-13 18:05:11 +00:00
|
|
|
pub fn is_trivially_wf(&self, tcx: TyCtxt<'tcx>) -> bool {
|
|
|
|
|
match self.kind() {
|
|
|
|
|
TermKind::Ty(ty) => ty.is_trivially_wf(tcx),
|
|
|
|
|
TermKind::Const(ct) => ct.is_trivially_wf(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-26 01:54:09 +00:00
|
|
|
/// Iterator that walks `self` and any types reachable from
|
|
|
|
|
/// `self`, in depth-first order. Note that just walks the types
|
|
|
|
|
/// that appear in `self`, it does not descend into the fields of
|
|
|
|
|
/// structs or variants. For example:
|
|
|
|
|
///
|
|
|
|
|
/// ```text
|
|
|
|
|
/// isize => { isize }
|
|
|
|
|
/// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
|
|
|
|
|
/// [isize] => { [isize], isize }
|
|
|
|
|
/// ```
|
|
|
|
|
pub fn walk(self) -> TypeWalker<TyCtxt<'tcx>> {
|
|
|
|
|
TypeWalker::new(self.into())
|
|
|
|
|
}
|
2022-01-08 09:28:12 +00:00
|
|
|
}
|
|
|
|
|
|
2022-09-05 14:03:53 +10:00
|
|
|
const TAG_MASK: usize = 0b11;
|
|
|
|
|
const TYPE_TAG: usize = 0b00;
|
|
|
|
|
const CONST_TAG: usize = 0b01;
|
|
|
|
|
|
2024-05-19 13:44:50 -04:00
|
|
|
#[extension(pub trait TermKindPackExt<'tcx>)]
|
2022-09-05 14:03:53 +10:00
|
|
|
impl<'tcx> TermKind<'tcx> {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn pack(self) -> Term<'tcx> {
|
|
|
|
|
let (tag, ptr) = match self {
|
|
|
|
|
TermKind::Ty(ty) => {
|
|
|
|
|
// Ensure we can use the tag bits.
|
2025-03-04 20:28:38 -08:00
|
|
|
assert_eq!(align_of_val(&*ty.0.0) & TAG_MASK, 0);
|
2024-01-14 00:36:27 -05:00
|
|
|
(TYPE_TAG, NonNull::from(ty.0.0).cast())
|
2022-09-05 14:03:53 +10:00
|
|
|
}
|
|
|
|
|
TermKind::Const(ct) => {
|
|
|
|
|
// Ensure we can use the tag bits.
|
2025-03-04 20:28:38 -08:00
|
|
|
assert_eq!(align_of_val(&*ct.0.0) & TAG_MASK, 0);
|
2024-01-14 00:36:27 -05:00
|
|
|
(CONST_TAG, NonNull::from(ct.0.0).cast())
|
2022-09-05 14:03:53 +10:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-01-14 00:36:27 -05:00
|
|
|
Term { ptr: ptr.map_addr(|addr| addr | tag), marker: PhantomData }
|
2022-09-05 14:03:53 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-24 20:06:06 -05:00
|
|
|
/// Represents the bounds declared on a particular set of type
|
2019-02-08 14:53:55 +01:00
|
|
|
/// parameters. Should eventually be generalized into a flag list of
|
2021-08-22 14:46:15 +02:00
|
|
|
/// where-clauses. You can obtain an `InstantiatedPredicates` list from a
|
2015-02-11 06:54:05 -05:00
|
|
|
/// `GenericPredicates` by using the `instantiate` method. Note that this method
|
|
|
|
|
/// reflects an important semantic invariant of `InstantiatedPredicates`: while
|
|
|
|
|
/// the `GenericPredicates` are expressed in terms of the bound type
|
|
|
|
|
/// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance
|
2014-11-24 20:06:06 -05:00
|
|
|
/// represented a set of bounds for some particular instantiation,
|
2024-02-12 15:39:32 +09:00
|
|
|
/// meaning that the generic parameters have been instantiated with
|
2014-11-24 20:06:06 -05:00
|
|
|
/// their values.
|
|
|
|
|
///
|
|
|
|
|
/// Example:
|
2022-04-15 15:04:34 -07:00
|
|
|
/// ```ignore (illustrative)
|
|
|
|
|
/// struct Foo<T, U: Bar<T>> { ... }
|
|
|
|
|
/// ```
|
2015-02-11 06:54:05 -05:00
|
|
|
/// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like
|
2019-02-08 14:53:55 +01:00
|
|
|
/// `[[], [U:Bar<T>]]`. Now if there were some particular reference
|
2015-03-25 17:06:52 -07:00
|
|
|
/// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[],
|
|
|
|
|
/// [usize:Bar<isize>]]`.
|
2022-06-17 10:53:29 +01:00
|
|
|
#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
|
2015-02-11 06:54:05 -05:00
|
|
|
pub struct InstantiatedPredicates<'tcx> {
|
2023-06-22 18:17:13 +00:00
|
|
|
pub predicates: Vec<Clause<'tcx>>,
|
2020-01-29 16:55:37 -08:00
|
|
|
pub spans: Vec<Span>,
|
2014-11-15 17:25:05 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-11 06:54:05 -05:00
|
|
|
impl<'tcx> InstantiatedPredicates<'tcx> {
|
|
|
|
|
pub fn empty() -> InstantiatedPredicates<'tcx> {
|
2020-01-29 16:55:37 -08:00
|
|
|
InstantiatedPredicates { predicates: vec![], spans: vec![] }
|
2014-11-15 17:25:05 -05:00
|
|
|
}
|
|
|
|
|
|
2014-12-07 11:10:48 -05:00
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
|
self.predicates.is_empty()
|
2014-11-15 17:25:05 -05:00
|
|
|
}
|
2023-01-03 03:32:59 +00:00
|
|
|
|
|
|
|
|
pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter {
|
2023-11-21 20:07:32 +01:00
|
|
|
self.into_iter()
|
2023-01-03 03:32:59 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> {
|
2023-06-22 18:17:13 +00:00
|
|
|
type Item = (Clause<'tcx>, Span);
|
2023-01-03 03:32:59 +00:00
|
|
|
|
2023-06-22 18:17:13 +00:00
|
|
|
type IntoIter = std::iter::Zip<std::vec::IntoIter<Clause<'tcx>>, std::vec::IntoIter<Span>>;
|
2023-01-03 03:32:59 +00:00
|
|
|
|
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
2023-01-03 03:38:06 +00:00
|
|
|
debug_assert_eq!(self.predicates.len(), self.spans.len());
|
2023-01-03 03:32:59 +00:00
|
|
|
std::iter::zip(self.predicates, self.spans)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> {
|
2023-06-22 18:17:13 +00:00
|
|
|
type Item = (Clause<'tcx>, Span);
|
2023-01-03 03:32:59 +00:00
|
|
|
|
|
|
|
|
type IntoIter = std::iter::Zip<
|
2023-06-22 18:17:13 +00:00
|
|
|
std::iter::Copied<std::slice::Iter<'a, Clause<'tcx>>>,
|
2023-01-03 03:32:59 +00:00
|
|
|
std::iter::Copied<std::slice::Iter<'a, Span>>,
|
|
|
|
|
>;
|
|
|
|
|
|
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
2023-01-03 03:38:06 +00:00
|
|
|
debug_assert_eq!(self.predicates.len(), self.spans.len());
|
2023-01-03 03:32:59 +00:00
|
|
|
std::iter::zip(self.predicates.iter().copied(), self.spans.iter().copied())
|
|
|
|
|
}
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-08 22:54:49 -07:00
|
|
|
}
|
|
|
|
|
|
2022-06-17 10:53:29 +01:00
|
|
|
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
|
2022-02-09 16:44:17 +00:00
|
|
|
pub struct OpaqueHiddenType<'tcx> {
|
|
|
|
|
/// The span of this particular definition of the opaque type. So
|
|
|
|
|
/// for example:
|
|
|
|
|
///
|
|
|
|
|
/// ```ignore (incomplete snippet)
|
|
|
|
|
/// type Foo = impl Baz;
|
|
|
|
|
/// fn bar() -> Foo {
|
|
|
|
|
/// // ^^^ This is the span we are looking for!
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// In cases where the fn returns `(impl Trait, impl Trait)` or
|
|
|
|
|
/// other such combinations, the result is currently
|
|
|
|
|
/// over-approximated, but better than nothing.
|
|
|
|
|
pub span: Span,
|
|
|
|
|
|
|
|
|
|
/// The type variable that represents the value of the opaque type
|
|
|
|
|
/// that we require. In other words, after we compile this function,
|
|
|
|
|
/// we will be created a constraint like:
|
2022-04-15 15:04:34 -07:00
|
|
|
/// ```ignore (pseudo-rust)
|
|
|
|
|
/// Foo<'a, T> = ?C
|
|
|
|
|
/// ```
|
2022-02-09 16:44:17 +00:00
|
|
|
/// where `?C` is the value of this type variable. =) It may
|
|
|
|
|
/// naturally refer to the type and lifetime parameters in scope
|
|
|
|
|
/// in this function, though ultimately it should only reference
|
|
|
|
|
/// those that are arguments to `Foo` in the constraint above. (In
|
|
|
|
|
/// other words, `?C` should not include `'b`, even though it's a
|
|
|
|
|
/// lifetime parameter on `foo`.)
|
|
|
|
|
pub ty: Ty<'tcx>,
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-01 23:48:41 +02:00
|
|
|
/// Whether we're currently in HIR typeck or MIR borrowck.
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
|
pub enum DefiningScopeKind {
|
|
|
|
|
/// During writeback in typeck, we don't care about regions and simply
|
|
|
|
|
/// erase them. This means we also don't check whether regions are
|
|
|
|
|
/// universal in the opaque type key. This will only be checked in
|
|
|
|
|
/// MIR borrowck.
|
|
|
|
|
HirTypeck,
|
|
|
|
|
MirBorrowck,
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-07 13:52:59 +00:00
|
|
|
impl<'tcx> OpaqueHiddenType<'tcx> {
|
2025-04-01 23:48:41 +02:00
|
|
|
pub fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> OpaqueHiddenType<'tcx> {
|
|
|
|
|
OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(tcx, guar) }
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-22 14:24:25 +00:00
|
|
|
pub fn build_mismatch_error(
|
2023-05-22 23:33:34 +00:00
|
|
|
&self,
|
|
|
|
|
other: &Self,
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2024-02-23 10:20:45 +11:00
|
|
|
) -> Result<Diag<'tcx>, ErrorGuaranteed> {
|
2024-02-22 09:22:15 +00:00
|
|
|
(self.ty, other.ty).error_reported()?;
|
2022-04-07 13:52:59 +00:00
|
|
|
// Found different concrete types for the opaque type.
|
2022-08-31 20:16:02 +08:00
|
|
|
let sub_diag = if self.span == other.span {
|
|
|
|
|
TypeMismatchReason::ConflictType { span: self.span }
|
2022-04-07 13:52:59 +00:00
|
|
|
} else {
|
2022-08-31 20:16:02 +08:00
|
|
|
TypeMismatchReason::PreviousUse { span: self.span }
|
|
|
|
|
};
|
2024-02-22 09:22:15 +00:00
|
|
|
Ok(tcx.dcx().create_err(OpaqueHiddenTypeMismatch {
|
2022-08-31 20:16:02 +08:00
|
|
|
self_ty: self.ty,
|
|
|
|
|
other_ty: other.ty,
|
|
|
|
|
other_span: other.span,
|
|
|
|
|
sub: sub_diag,
|
2024-02-22 09:22:15 +00:00
|
|
|
}))
|
2022-04-07 13:52:59 +00:00
|
|
|
}
|
2022-09-27 11:37:10 +00:00
|
|
|
|
|
|
|
|
#[instrument(level = "debug", skip(tcx), ret)]
|
|
|
|
|
pub fn remap_generic_params_to_declaration_params(
|
|
|
|
|
self,
|
|
|
|
|
opaque_type_key: OpaqueTypeKey<'tcx>,
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2025-04-01 23:48:41 +02:00
|
|
|
defining_scope_kind: DefiningScopeKind,
|
2022-09-27 11:37:10 +00:00
|
|
|
) -> Self {
|
2023-07-11 22:35:29 +01:00
|
|
|
let OpaqueTypeKey { def_id, args } = opaque_type_key;
|
2022-09-27 11:37:10 +00:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
// Use args to build up a reverse map from regions to their
|
2022-09-27 11:37:10 +00:00
|
|
|
// identity mappings. This is necessary because of `impl
|
|
|
|
|
// Trait` lifetimes are computed by replacing existing
|
|
|
|
|
// lifetimes with 'static and remapping only those used in the
|
|
|
|
|
// `impl Trait` return type, resulting in the parameters
|
|
|
|
|
// shifting.
|
2023-07-11 22:35:29 +01:00
|
|
|
let id_args = GenericArgs::identity_for_item(tcx, def_id);
|
|
|
|
|
debug!(?id_args);
|
2022-09-28 16:01:05 +00:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
// This zip may have several times the same lifetime in `args` paired with a different
|
|
|
|
|
// lifetime from `id_args`. Simply `collect`ing the iterator is the correct behaviour:
|
2022-11-14 21:24:18 +00:00
|
|
|
// it will pick the last one, which is the one we introduced in the impl-trait desugaring.
|
2023-07-11 22:35:29 +01:00
|
|
|
let map = args.iter().zip(id_args).collect();
|
2022-09-27 11:37:10 +00:00
|
|
|
debug!("map = {:#?}", map);
|
|
|
|
|
|
2025-04-01 23:48:41 +02:00
|
|
|
// Convert the type from the function into a type valid outside by mapping generic
|
|
|
|
|
// parameters to into the context of the opaque.
|
|
|
|
|
//
|
2025-08-19 14:10:22 +02:00
|
|
|
// We erase regions when doing this during HIR typeck. We manually use `fold_regions`
|
|
|
|
|
// here as we do not want to anonymize bound variables.
|
2025-04-01 23:48:41 +02:00
|
|
|
let this = match defining_scope_kind {
|
2025-08-19 14:10:22 +02:00
|
|
|
DefiningScopeKind::HirTypeck => fold_regions(tcx, self, |_, _| tcx.lifetimes.re_erased),
|
2025-04-01 23:48:41 +02:00
|
|
|
DefiningScopeKind::MirBorrowck => self,
|
|
|
|
|
};
|
|
|
|
|
let result = this.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span));
|
|
|
|
|
if cfg!(debug_assertions) && matches!(defining_scope_kind, DefiningScopeKind::HirTypeck) {
|
2025-08-19 14:10:22 +02:00
|
|
|
assert_eq!(result.ty, fold_regions(tcx, result.ty, |_, _| tcx.lifetimes.re_erased));
|
2025-04-01 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
result
|
2022-09-27 11:37:10 +00:00
|
|
|
}
|
2022-04-07 13:52:59 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-28 01:11:03 +00:00
|
|
|
/// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are
|
|
|
|
|
/// identified by both a universe, as well as a name residing within that universe. Distinct bound
|
|
|
|
|
/// regions/types/consts within the same universe simply have an unknown relationship to one
|
2018-09-27 17:57:35 -04:00
|
|
|
/// another.
|
2023-05-26 18:54:59 +01:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
2022-07-29 12:48:28 +02:00
|
|
|
#[derive(HashStable, TyEncodable, TyDecodable)]
|
2018-11-02 15:08:51 +01:00
|
|
|
pub struct Placeholder<T> {
|
2018-09-27 17:57:35 -04:00
|
|
|
pub universe: UniverseIndex,
|
2023-04-06 21:12:17 -04:00
|
|
|
pub bound: T,
|
2018-09-27 17:57:35 -04:00
|
|
|
}
|
|
|
|
|
|
2023-04-06 21:12:17 -04:00
|
|
|
pub type PlaceholderRegion = Placeholder<BoundRegion>;
|
2018-11-02 15:08:51 +01:00
|
|
|
|
2025-06-12 22:38:31 +00:00
|
|
|
impl<'tcx> rustc_type_ir::inherent::PlaceholderLike<TyCtxt<'tcx>> for PlaceholderRegion {
|
|
|
|
|
type Bound = BoundRegion;
|
|
|
|
|
|
2023-12-05 18:10:23 +00:00
|
|
|
fn universe(self) -> UniverseIndex {
|
2023-11-04 17:33:11 +00:00
|
|
|
self.universe
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 18:10:23 +00:00
|
|
|
fn var(self) -> BoundVar {
|
2023-11-04 17:33:11 +00:00
|
|
|
self.bound.var
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 18:10:23 +00:00
|
|
|
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
|
|
|
|
Placeholder { universe: ui, ..self }
|
2023-11-22 23:44:58 +00:00
|
|
|
}
|
|
|
|
|
|
2025-06-12 22:38:31 +00:00
|
|
|
fn new(ui: UniverseIndex, bound: BoundRegion) -> Self {
|
|
|
|
|
Placeholder { universe: ui, bound }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn new_anon(ui: UniverseIndex, var: BoundVar) -> Self {
|
2024-11-03 22:06:03 +00:00
|
|
|
Placeholder { universe: ui, bound: BoundRegion { var, kind: BoundRegionKind::Anon } }
|
2023-11-04 17:33:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-06 21:12:17 -04:00
|
|
|
pub type PlaceholderType = Placeholder<BoundTy>;
|
2018-09-27 09:43:22 -04:00
|
|
|
|
2025-06-12 22:38:31 +00:00
|
|
|
impl<'tcx> rustc_type_ir::inherent::PlaceholderLike<TyCtxt<'tcx>> for PlaceholderType {
|
|
|
|
|
type Bound = BoundTy;
|
|
|
|
|
|
2023-12-05 18:10:23 +00:00
|
|
|
fn universe(self) -> UniverseIndex {
|
2023-11-04 17:33:11 +00:00
|
|
|
self.universe
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 18:10:23 +00:00
|
|
|
fn var(self) -> BoundVar {
|
2023-11-04 17:33:11 +00:00
|
|
|
self.bound.var
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 18:10:23 +00:00
|
|
|
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
|
|
|
|
Placeholder { universe: ui, ..self }
|
2023-11-22 23:44:58 +00:00
|
|
|
}
|
|
|
|
|
|
2025-06-12 22:38:31 +00:00
|
|
|
fn new(ui: UniverseIndex, bound: BoundTy) -> Self {
|
|
|
|
|
Placeholder { universe: ui, bound }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn new_anon(ui: UniverseIndex, var: BoundVar) -> Self {
|
2023-11-22 23:44:58 +00:00
|
|
|
Placeholder { universe: ui, bound: BoundTy { var, kind: BoundTyKind::Anon } }
|
2023-11-04 17:33:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-28 01:11:03 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
2024-03-21 13:10:28 +00:00
|
|
|
#[derive(TyEncodable, TyDecodable)]
|
2025-07-30 14:21:00 +10:00
|
|
|
pub struct BoundConst {
|
2020-10-28 01:11:03 +00:00
|
|
|
pub var: BoundVar,
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 14:21:00 +10:00
|
|
|
impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundConst {
|
|
|
|
|
fn var(self) -> BoundVar {
|
|
|
|
|
self.var
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:04:03 +10:00
|
|
|
fn assert_eq(self, var: ty::BoundVariableKind) {
|
|
|
|
|
var.expect_const()
|
2025-07-30 14:21:00 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub type PlaceholderConst = Placeholder<BoundConst>;
|
2019-03-12 20:26:16 +00:00
|
|
|
|
2025-06-12 22:38:31 +00:00
|
|
|
impl<'tcx> rustc_type_ir::inherent::PlaceholderLike<TyCtxt<'tcx>> for PlaceholderConst {
|
2025-07-30 14:21:00 +10:00
|
|
|
type Bound = BoundConst;
|
2025-06-12 22:38:31 +00:00
|
|
|
|
2023-12-05 18:10:23 +00:00
|
|
|
fn universe(self) -> UniverseIndex {
|
2023-11-04 17:33:11 +00:00
|
|
|
self.universe
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 18:10:23 +00:00
|
|
|
fn var(self) -> BoundVar {
|
2025-07-30 14:21:00 +10:00
|
|
|
self.bound.var
|
2023-11-04 17:33:11 +00:00
|
|
|
}
|
|
|
|
|
|
2023-12-05 18:10:23 +00:00
|
|
|
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
|
|
|
|
Placeholder { universe: ui, ..self }
|
2023-11-22 23:44:58 +00:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 14:21:00 +10:00
|
|
|
fn new(ui: UniverseIndex, bound: BoundConst) -> Self {
|
2025-06-12 22:38:31 +00:00
|
|
|
Placeholder { universe: ui, bound }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn new_anon(ui: UniverseIndex, var: BoundVar) -> Self {
|
2025-07-30 14:21:00 +10:00
|
|
|
Placeholder { universe: ui, bound: BoundConst { var } }
|
2023-11-04 17:33:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-24 22:49:31 +01:00
|
|
|
pub type Clauses<'tcx> = &'tcx ListWithCachedTypeInfo<Clause<'tcx>>;
|
|
|
|
|
|
2025-03-13 17:09:25 +00:00
|
|
|
impl<'tcx> rustc_type_ir::Flags for Clauses<'tcx> {
|
2024-03-24 22:49:31 +01:00
|
|
|
fn flags(&self) -> TypeFlags {
|
|
|
|
|
(**self).flags()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn outer_exclusive_binder(&self) -> DebruijnIndex {
|
|
|
|
|
(**self).outer_exclusive_binder()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-01 17:29:34 +01:00
|
|
|
/// When interacting with the type system we must provide information about the
|
|
|
|
|
/// environment. `ParamEnv` is the type that represents this information. See the
|
2024-04-01 19:59:05 +01:00
|
|
|
/// [dev guide chapter][param_env_guide] for more information.
|
2024-04-01 17:29:34 +01:00
|
|
|
///
|
2025-03-31 16:42:01 +00:00
|
|
|
/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html
|
2024-11-20 11:31:49 +01:00
|
|
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
|
|
|
|
#[derive(HashStable, TypeVisitable, TypeFoldable)]
|
2017-05-15 17:57:30 -04:00
|
|
|
pub struct ParamEnv<'tcx> {
|
2020-08-16 11:08:55 -04:00
|
|
|
/// Caller bounds are `Obligation`s that the caller must satisfy. This is
|
|
|
|
|
/// basically the set of bounds on the in-scope type parameters, translated
|
2019-06-17 23:40:24 +01:00
|
|
|
/// into `Obligation`s, and elaborated and normalized.
|
2020-07-02 20:52:40 -04:00
|
|
|
///
|
2020-08-16 11:08:55 -04:00
|
|
|
/// Use the `caller_bounds()` method to access.
|
2024-11-20 11:31:49 +01:00
|
|
|
caller_bounds: Clauses<'tcx>,
|
2021-12-12 12:34:46 +08:00
|
|
|
}
|
|
|
|
|
|
2024-06-17 17:59:08 -04:00
|
|
|
impl<'tcx> rustc_type_ir::inherent::ParamEnv<TyCtxt<'tcx>> for ParamEnv<'tcx> {
|
2024-11-26 12:09:42 +01:00
|
|
|
fn caller_bounds(self) -> impl inherent::SliceLike<Item = ty::Clause<'tcx>> {
|
2024-06-17 17:59:08 -04:00
|
|
|
self.caller_bounds()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-15 17:57:30 -04:00
|
|
|
impl<'tcx> ParamEnv<'tcx> {
|
2024-11-20 11:31:49 +01:00
|
|
|
/// Construct a trait environment suitable for contexts where there are
|
|
|
|
|
/// no where-clauses in scope. In the majority of cases it is incorrect
|
2024-04-01 17:29:34 +01:00
|
|
|
/// to use an empty environment. See the [dev guide section][param_env_guide]
|
|
|
|
|
/// for information on what a `ParamEnv` is and how to acquire one.
|
|
|
|
|
///
|
2025-03-31 16:42:01 +00:00
|
|
|
/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2018-02-14 05:08:02 -05:00
|
|
|
pub fn empty() -> Self {
|
2024-11-20 11:31:49 +01:00
|
|
|
Self::new(ListWithCachedTypeInfo::empty())
|
2018-02-14 05:08:02 -05:00
|
|
|
}
|
|
|
|
|
|
2020-07-02 20:52:40 -04:00
|
|
|
#[inline]
|
2024-03-24 22:49:31 +01:00
|
|
|
pub fn caller_bounds(self) -> Clauses<'tcx> {
|
2024-11-20 11:31:49 +01:00
|
|
|
self.caller_bounds
|
2018-02-14 05:08:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Construct a trait environment with the given set of predicates.
|
2018-11-29 21:13:04 +01:00
|
|
|
#[inline]
|
2024-11-20 11:31:49 +01:00
|
|
|
pub fn new(caller_bounds: Clauses<'tcx>) -> Self {
|
|
|
|
|
ParamEnv { caller_bounds }
|
2018-02-14 05:08:02 -05:00
|
|
|
}
|
|
|
|
|
|
2023-10-04 14:11:38 +03:00
|
|
|
/// Creates a pair of param-env and value for use in queries.
|
2023-02-22 02:18:40 +00:00
|
|
|
pub fn and<T: TypeVisitable<TyCtxt<'tcx>>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
|
2023-10-04 14:11:38 +03:00
|
|
|
ParamEnvAnd { param_env: self, value }
|
2017-05-10 10:28:06 -04:00
|
|
|
}
|
|
|
|
|
}
|
2017-04-17 21:18:56 +03:00
|
|
|
|
2022-06-17 10:53:29 +01:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
|
2023-09-14 09:46:18 +10:00
|
|
|
#[derive(HashStable)]
|
2017-05-15 17:57:30 -04:00
|
|
|
pub struct ParamEnvAnd<'tcx, T> {
|
|
|
|
|
pub param_env: ParamEnv<'tcx>,
|
2017-05-10 10:28:06 -04:00
|
|
|
pub value: T,
|
2013-10-29 06:03:32 -04:00
|
|
|
}
|
|
|
|
|
|
2024-11-15 13:53:31 +01:00
|
|
|
/// The environment in which to do trait solving.
|
|
|
|
|
///
|
|
|
|
|
/// Most of the time you only need to care about the `ParamEnv`
|
|
|
|
|
/// as the `TypingMode` is simply stored in the `InferCtxt`.
|
|
|
|
|
///
|
|
|
|
|
/// However, there are some places which rely on trait solving
|
|
|
|
|
/// without using an `InferCtxt` themselves. For these to be
|
|
|
|
|
/// able to use the trait system they have to be able to initialize
|
|
|
|
|
/// such an `InferCtxt` with the right `typing_mode`, so they need
|
|
|
|
|
/// to track both.
|
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
|
|
|
|
#[derive(TypeVisitable, TypeFoldable)]
|
|
|
|
|
pub struct TypingEnv<'tcx> {
|
2025-08-08 15:29:37 +02:00
|
|
|
#[type_foldable(identity)]
|
|
|
|
|
#[type_visitable(ignore)]
|
2024-11-15 13:53:31 +01:00
|
|
|
pub typing_mode: TypingMode<'tcx>,
|
|
|
|
|
pub param_env: ParamEnv<'tcx>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> TypingEnv<'tcx> {
|
|
|
|
|
/// Create a typing environment with no where-clauses in scope
|
|
|
|
|
/// where all opaque types and default associated items are revealed.
|
|
|
|
|
///
|
|
|
|
|
/// This is only suitable for monomorphized, post-typeck environments.
|
|
|
|
|
/// Do not use this for MIR optimizations, as even though they also
|
|
|
|
|
/// use `TypingMode::PostAnalysis`, they may still have where-clauses
|
|
|
|
|
/// in scope.
|
|
|
|
|
pub fn fully_monomorphized() -> TypingEnv<'tcx> {
|
2024-11-20 11:31:49 +01:00
|
|
|
TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env: ParamEnv::empty() }
|
2024-11-15 13:53:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Create a typing environment for use during analysis outside of a body.
|
|
|
|
|
///
|
|
|
|
|
/// Using a typing environment inside of bodies is not supported as the body
|
|
|
|
|
/// may define opaque types. In this case the used functions have to be
|
|
|
|
|
/// converted to use proper canonical inputs instead.
|
|
|
|
|
pub fn non_body_analysis(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
def_id: impl IntoQueryParam<DefId>,
|
|
|
|
|
) -> TypingEnv<'tcx> {
|
|
|
|
|
TypingEnv { typing_mode: TypingMode::non_body_analysis(), param_env: tcx.param_env(def_id) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryParam<DefId>) -> TypingEnv<'tcx> {
|
2025-06-10 17:01:55 +00:00
|
|
|
tcx.typing_env_normalized_for_post_analysis(def_id)
|
2024-11-15 13:53:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Modify the `typing_mode` to `PostAnalysis` and eagerly reveal all
|
|
|
|
|
/// opaque types in the `param_env`.
|
2024-11-20 11:31:49 +01:00
|
|
|
pub fn with_post_analysis_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> {
|
|
|
|
|
let TypingEnv { typing_mode, param_env } = self;
|
|
|
|
|
if let TypingMode::PostAnalysis = typing_mode {
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// No need to reveal opaques with the new solver enabled,
|
|
|
|
|
// since we have lazy norm.
|
|
|
|
|
let param_env = if tcx.next_trait_solver_globally() {
|
2025-06-10 17:01:55 +00:00
|
|
|
param_env
|
2024-11-20 11:31:49 +01:00
|
|
|
} else {
|
|
|
|
|
ParamEnv::new(tcx.reveal_opaque_types_in_bounds(param_env.caller_bounds()))
|
|
|
|
|
};
|
2024-11-15 13:53:31 +01:00
|
|
|
TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Combine this typing environment with the given `value` to be used by
|
|
|
|
|
/// not (yet) canonicalized queries. This only works if the value does not
|
|
|
|
|
/// contain anything local to some `InferCtxt`, i.e. inference variables or
|
|
|
|
|
/// placeholders.
|
|
|
|
|
pub fn as_query_input<T>(self, value: T) -> PseudoCanonicalInput<'tcx, T>
|
|
|
|
|
where
|
|
|
|
|
T: TypeVisitable<TyCtxt<'tcx>>,
|
|
|
|
|
{
|
|
|
|
|
// FIXME(#132279): We should assert that the value does not contain any placeholders
|
|
|
|
|
// as these placeholders are also local to the current inference context. However, we
|
2025-07-03 20:03:45 +00:00
|
|
|
// currently use pseudo-canonical queries in the trait solver, which replaces params
|
|
|
|
|
// with placeholders during canonicalization. We should also simply not use pseudo-
|
|
|
|
|
// canonical queries in the trait solver, at which point we can readd this assert.
|
2024-11-15 13:53:31 +01:00
|
|
|
//
|
2025-07-03 20:03:45 +00:00
|
|
|
// As of writing this comment, this is only used when normalizing consts that mention
|
|
|
|
|
// params.
|
|
|
|
|
/* debug_assert!(
|
|
|
|
|
!value.has_placeholders(),
|
|
|
|
|
"{value:?} which has placeholder shouldn't be pseudo-canonicalized"
|
|
|
|
|
); */
|
2024-11-15 13:53:31 +01:00
|
|
|
PseudoCanonicalInput { typing_env: self, value }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Similar to `CanonicalInput`, this carries the `typing_mode` and the environment
|
|
|
|
|
/// necessary to do any kind of trait solving inside of nested queries.
|
|
|
|
|
///
|
|
|
|
|
/// Unlike proper canonicalization, this requires the `param_env` and the `value` to not
|
|
|
|
|
/// contain anything local to the `infcx` of the caller, so we don't actually canonicalize
|
|
|
|
|
/// anything.
|
|
|
|
|
///
|
|
|
|
|
/// This should be created by using `infcx.pseudo_canonicalize_query(param_env, value)`
|
|
|
|
|
/// or by using `typing_env.as_query_input(value)`.
|
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
2024-11-19 20:10:42 +01:00
|
|
|
#[derive(HashStable, TypeVisitable, TypeFoldable)]
|
2024-11-15 13:53:31 +01:00
|
|
|
pub struct PseudoCanonicalInput<'tcx, T> {
|
|
|
|
|
pub typing_env: TypingEnv<'tcx>,
|
|
|
|
|
pub value: T,
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-28 19:53:01 +02:00
|
|
|
#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)]
|
2017-03-01 18:42:26 +02:00
|
|
|
pub struct Destructor {
|
2019-02-08 14:53:55 +01:00
|
|
|
/// The `DefId` of the destructor method
|
2017-03-01 18:42:26 +02:00
|
|
|
pub did: DefId,
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-02 17:59:02 +03:00
|
|
|
// FIXME: consider combining this definition with regular `Destructor`
|
|
|
|
|
#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)]
|
|
|
|
|
pub struct AsyncDestructor {
|
2025-04-04 04:56:18 +02:00
|
|
|
/// The `DefId` of the `impl AsyncDrop`
|
2025-05-15 19:03:23 +07:00
|
|
|
pub impl_did: DefId,
|
2024-05-02 17:59:02 +03:00
|
|
|
}
|
|
|
|
|
|
2023-12-30 17:09:02 +01:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
|
|
|
|
pub struct VariantFlags(u8);
|
2024-04-29 16:11:04 +10:00
|
|
|
bitflags::bitflags! {
|
2023-12-30 17:09:02 +01:00
|
|
|
impl VariantFlags: u8 {
|
2018-09-01 19:10:26 +03:00
|
|
|
const NO_VARIANT_FLAGS = 0;
|
|
|
|
|
/// Indicates whether the field list of this variant is `#[non_exhaustive]`.
|
|
|
|
|
const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0;
|
2015-07-20 22:13:36 +03:00
|
|
|
}
|
|
|
|
|
}
|
2023-12-30 17:09:02 +01:00
|
|
|
rustc_data_structures::external_bitflags_debug! { VariantFlags }
|
2015-07-20 22:13:36 +03:00
|
|
|
|
2021-08-22 14:46:15 +02:00
|
|
|
/// Definition of a variant -- a struct's fields or an enum variant.
|
2021-12-14 12:37:04 -05:00
|
|
|
#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
|
2016-11-25 01:33:29 +02:00
|
|
|
pub struct VariantDef {
|
2019-03-24 12:09:44 +03:00
|
|
|
/// `DefId` that identifies the variant itself.
|
|
|
|
|
/// If this variant belongs to a struct or union, then this is a copy of its `DefId`.
|
|
|
|
|
pub def_id: DefId,
|
|
|
|
|
/// `DefId` that identifies the variant's constructor.
|
|
|
|
|
/// If this variant is a struct variant, then this is `None`.
|
2022-10-25 20:15:15 +04:00
|
|
|
pub ctor: Option<(CtorKind, DefId)>,
|
2025-03-10 02:31:16 +00:00
|
|
|
/// Variant or struct name.
|
2022-01-02 22:37:05 -05:00
|
|
|
pub name: Symbol,
|
2019-03-21 23:38:50 +01:00
|
|
|
/// Discriminant of this variant.
|
2017-02-05 07:01:48 +02:00
|
|
|
pub discr: VariantDiscr,
|
2019-03-21 23:38:50 +01:00
|
|
|
/// Fields of this variant.
|
2023-03-28 23:32:25 -07:00
|
|
|
pub fields: IndexVec<FieldIdx, FieldDef>,
|
2024-07-11 00:07:07 +08:00
|
|
|
/// The error guarantees from parser, if any.
|
|
|
|
|
tainted: Option<ErrorGuaranteed>,
|
2019-03-21 23:38:50 +01:00
|
|
|
/// Flags of the variant (e.g. is field list non-exhaustive)?
|
2018-09-01 19:10:26 +03:00
|
|
|
flags: VariantFlags,
|
2015-07-22 20:10:18 +03:00
|
|
|
}
|
|
|
|
|
|
2020-08-03 11:08:03 +01:00
|
|
|
impl VariantDef {
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Creates a new `VariantDef`.
|
2018-09-01 19:10:26 +03:00
|
|
|
///
|
2019-03-21 23:38:50 +01:00
|
|
|
/// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef`
|
|
|
|
|
/// represents an enum variant).
|
2018-09-22 21:53:58 +03:00
|
|
|
///
|
2019-03-21 23:38:50 +01:00
|
|
|
/// `ctor_did` is the `DefId` that identifies the constructor of unit or
|
|
|
|
|
/// tuple-variants/structs. If this is a `struct`-variant then this should be `None`.
|
|
|
|
|
///
|
|
|
|
|
/// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that
|
|
|
|
|
/// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having
|
|
|
|
|
/// to go through the redirect of checking the ctor's attributes - but compiling a small crate
|
|
|
|
|
/// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any
|
2018-09-22 21:53:58 +03:00
|
|
|
/// built-in trait), and we do not want to load attributes twice.
|
|
|
|
|
///
|
|
|
|
|
/// If someone speeds up attribute loading to not be a performance concern, they can
|
2019-02-08 14:53:55 +01:00
|
|
|
/// remove this hack and use the constructor `DefId` everywhere.
|
2025-02-24 12:25:17 +03:00
|
|
|
#[instrument(level = "debug")]
|
2019-03-17 20:09:53 -07:00
|
|
|
pub fn new(
|
2022-01-02 22:37:05 -05:00
|
|
|
name: Symbol,
|
2019-03-21 23:38:50 +01:00
|
|
|
variant_did: Option<DefId>,
|
2022-10-25 20:15:15 +04:00
|
|
|
ctor: Option<(CtorKind, DefId)>,
|
2019-03-17 20:09:53 -07:00
|
|
|
discr: VariantDiscr,
|
2023-03-28 23:32:25 -07:00
|
|
|
fields: IndexVec<FieldIdx, FieldDef>,
|
2019-03-21 23:38:50 +01:00
|
|
|
parent_did: DefId,
|
2024-07-11 00:07:07 +08:00
|
|
|
recover_tainted: Option<ErrorGuaranteed>,
|
2020-07-28 13:31:48 -04:00
|
|
|
is_field_list_non_exhaustive: bool,
|
2019-03-17 20:09:53 -07:00
|
|
|
) -> Self {
|
2018-09-01 19:10:26 +03:00
|
|
|
let mut flags = VariantFlags::NO_VARIANT_FLAGS;
|
2020-07-28 13:31:48 -04:00
|
|
|
if is_field_list_non_exhaustive {
|
|
|
|
|
flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
|
2018-09-01 19:10:26 +03:00
|
|
|
}
|
2019-03-21 23:38:50 +01:00
|
|
|
|
2024-07-11 00:07:07 +08:00
|
|
|
VariantDef {
|
|
|
|
|
def_id: variant_did.unwrap_or(parent_did),
|
|
|
|
|
ctor,
|
|
|
|
|
name,
|
|
|
|
|
discr,
|
|
|
|
|
fields,
|
|
|
|
|
flags,
|
|
|
|
|
tainted: recover_tainted,
|
|
|
|
|
}
|
2018-09-01 19:10:26 +03:00
|
|
|
}
|
|
|
|
|
|
2025-03-03 12:54:26 +01:00
|
|
|
/// Returns `true` if the field list of this variant is `#[non_exhaustive]`.
|
|
|
|
|
///
|
|
|
|
|
/// Note that this function will return `true` even if the type has been
|
|
|
|
|
/// defined in the crate currently being compiled. If that's not what you
|
|
|
|
|
/// want, see [`Self::field_list_has_applicable_non_exhaustive`].
|
2018-09-01 19:10:26 +03:00
|
|
|
#[inline]
|
|
|
|
|
pub fn is_field_list_non_exhaustive(&self) -> bool {
|
|
|
|
|
self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
|
|
|
|
|
}
|
2020-06-12 14:11:45 +01:00
|
|
|
|
2025-03-03 12:54:26 +01:00
|
|
|
/// Returns `true` if the field list of this variant is `#[non_exhaustive]`
|
|
|
|
|
/// and the type has been defined in another crate.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn field_list_has_applicable_non_exhaustive(&self) -> bool {
|
|
|
|
|
self.is_field_list_non_exhaustive() && !self.def_id.is_local()
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-02 22:37:05 -05:00
|
|
|
/// Computes the `Ident` of this variant by looking up the `Span`
|
|
|
|
|
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
|
|
|
|
|
Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
|
|
|
|
|
}
|
2022-10-25 20:15:15 +04:00
|
|
|
|
2024-07-11 00:07:07 +08:00
|
|
|
/// Was this variant obtained as part of recovering from a syntactic error?
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn has_errors(&self) -> Result<(), ErrorGuaranteed> {
|
|
|
|
|
self.tainted.map_or(Ok(()), Err)
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-25 20:15:15 +04:00
|
|
|
#[inline]
|
|
|
|
|
pub fn ctor_kind(&self) -> Option<CtorKind> {
|
|
|
|
|
self.ctor.map(|(kind, _)| kind)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn ctor_def_id(&self) -> Option<DefId> {
|
|
|
|
|
self.ctor.map(|(_, def_id)| def_id)
|
|
|
|
|
}
|
2023-04-16 01:06:55 -07:00
|
|
|
|
|
|
|
|
/// Returns the one field in this variant.
|
|
|
|
|
///
|
|
|
|
|
/// `panic!`s if there are no fields or multiple fields.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn single_field(&self) -> &FieldDef {
|
|
|
|
|
assert!(self.fields.len() == 1);
|
|
|
|
|
|
2024-04-03 17:49:59 +03:00
|
|
|
&self.fields[FieldIdx::ZERO]
|
2023-04-16 01:06:55 -07:00
|
|
|
}
|
2023-07-05 20:44:24 +02:00
|
|
|
|
|
|
|
|
/// Returns the last field in this variant, if present.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn tail_opt(&self) -> Option<&FieldDef> {
|
|
|
|
|
self.fields.raw.last()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the last field in this variant.
|
|
|
|
|
///
|
|
|
|
|
/// # Panics
|
|
|
|
|
///
|
|
|
|
|
/// Panics, if the variant has no fields.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn tail(&self) -> &FieldDef {
|
|
|
|
|
self.tail_opt().expect("expected unsized ADT to have a tail field")
|
|
|
|
|
}
|
2024-10-27 01:35:33 +02:00
|
|
|
|
|
|
|
|
/// Returns whether this variant has unsafe fields.
|
|
|
|
|
pub fn has_unsafe_fields(&self) -> bool {
|
2024-12-13 12:19:46 +00:00
|
|
|
self.fields.iter().any(|x| x.safety.is_unsafe())
|
2024-10-27 01:35:33 +02:00
|
|
|
}
|
2015-07-22 20:10:18 +03:00
|
|
|
}
|
|
|
|
|
|
2021-07-03 12:18:13 -04:00
|
|
|
impl PartialEq for VariantDef {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
2022-07-20 20:21:57 +00:00
|
|
|
// There should be only one `VariantDef` for each `def_id`, therefore
|
|
|
|
|
// it is fine to implement `PartialEq` only based on `def_id`.
|
|
|
|
|
//
|
|
|
|
|
// Below, we exhaustively destructure `self` and `other` so that if the
|
|
|
|
|
// definition of `VariantDef` changes, a compile-error will be produced,
|
|
|
|
|
// reminding us to revisit this assumption.
|
|
|
|
|
|
2024-07-11 00:07:07 +08:00
|
|
|
let Self {
|
|
|
|
|
def_id: lhs_def_id,
|
|
|
|
|
ctor: _,
|
|
|
|
|
name: _,
|
|
|
|
|
discr: _,
|
|
|
|
|
fields: _,
|
|
|
|
|
flags: _,
|
|
|
|
|
tainted: _,
|
|
|
|
|
} = &self;
|
|
|
|
|
let Self {
|
|
|
|
|
def_id: rhs_def_id,
|
|
|
|
|
ctor: _,
|
|
|
|
|
name: _,
|
|
|
|
|
discr: _,
|
|
|
|
|
fields: _,
|
|
|
|
|
flags: _,
|
|
|
|
|
tainted: _,
|
|
|
|
|
} = other;
|
2023-05-13 00:42:23 +00:00
|
|
|
|
|
|
|
|
let res = lhs_def_id == rhs_def_id;
|
|
|
|
|
|
|
|
|
|
// Double check that implicit assumption detailed above.
|
|
|
|
|
if cfg!(debug_assertions) && res {
|
|
|
|
|
let deep = self.ctor == other.ctor
|
|
|
|
|
&& self.name == other.name
|
|
|
|
|
&& self.discr == other.discr
|
|
|
|
|
&& self.fields == other.fields
|
|
|
|
|
&& self.flags == other.flags;
|
|
|
|
|
assert!(deep, "VariantDef for the same def-id has differing data");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res
|
2021-07-03 12:18:13 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Eq for VariantDef {}
|
|
|
|
|
|
|
|
|
|
impl Hash for VariantDef {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn hash<H: Hasher>(&self, s: &mut H) {
|
2022-07-20 20:21:57 +00:00
|
|
|
// There should be only one `VariantDef` for each `def_id`, therefore
|
|
|
|
|
// it is fine to implement `Hash` only based on `def_id`.
|
|
|
|
|
//
|
|
|
|
|
// Below, we exhaustively destructure `self` so that if the definition
|
|
|
|
|
// of `VariantDef` changes, a compile-error will be produced, reminding
|
|
|
|
|
// us to revisit this assumption.
|
|
|
|
|
|
2024-07-11 00:07:07 +08:00
|
|
|
let Self { def_id, ctor: _, name: _, discr: _, fields: _, flags: _, tainted: _ } = &self;
|
2022-07-20 20:21:57 +00:00
|
|
|
def_id.hash(s)
|
2021-07-03 12:18:13 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-29 21:09:54 +01:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
|
2017-02-05 07:01:48 +02:00
|
|
|
pub enum VariantDiscr {
|
2018-11-27 02:59:49 +00:00
|
|
|
/// Explicit value for this variant, i.e., `X = 123`.
|
2017-02-05 07:01:48 +02:00
|
|
|
/// The `DefId` corresponds to the embedded constant.
|
|
|
|
|
Explicit(DefId),
|
|
|
|
|
|
|
|
|
|
/// The previous variant's discriminant plus one.
|
|
|
|
|
/// For efficiency reasons, the distance from the
|
|
|
|
|
/// last `Explicit` discriminant is being stored,
|
|
|
|
|
/// or `0` for the first variant, if it has none.
|
2018-11-01 16:01:24 +01:00
|
|
|
Relative(u32),
|
2017-02-05 07:01:48 +02:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 12:37:04 -05:00
|
|
|
#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
|
2016-11-25 01:33:29 +02:00
|
|
|
pub struct FieldDef {
|
2015-07-22 20:10:18 +03:00
|
|
|
pub did: DefId,
|
2022-01-02 22:37:05 -05:00
|
|
|
pub name: Symbol,
|
2022-08-28 00:10:06 +03:00
|
|
|
pub vis: Visibility<DefId>,
|
2024-10-27 01:35:33 +02:00
|
|
|
pub safety: hir::Safety,
|
2024-08-24 17:22:48 +00:00
|
|
|
pub value: Option<DefId>,
|
2015-07-22 20:10:18 +03:00
|
|
|
}
|
|
|
|
|
|
2021-07-03 12:18:13 -04:00
|
|
|
impl PartialEq for FieldDef {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
2022-07-20 20:21:57 +00:00
|
|
|
// There should be only one `FieldDef` for each `did`, therefore it is
|
|
|
|
|
// fine to implement `PartialEq` only based on `did`.
|
|
|
|
|
//
|
|
|
|
|
// Below, we exhaustively destructure `self` so that if the definition
|
|
|
|
|
// of `FieldDef` changes, a compile-error will be produced, reminding
|
|
|
|
|
// us to revisit this assumption.
|
|
|
|
|
|
2024-08-24 17:22:48 +00:00
|
|
|
let Self { did: lhs_did, name: _, vis: _, safety: _, value: _ } = &self;
|
2022-07-20 20:21:57 +00:00
|
|
|
|
2024-08-24 17:22:48 +00:00
|
|
|
let Self { did: rhs_did, name: _, vis: _, safety: _, value: _ } = other;
|
2022-07-20 20:21:57 +00:00
|
|
|
|
2023-05-13 00:42:23 +00:00
|
|
|
let res = lhs_did == rhs_did;
|
|
|
|
|
|
|
|
|
|
// Double check that implicit assumption detailed above.
|
|
|
|
|
if cfg!(debug_assertions) && res {
|
2024-10-27 01:35:33 +02:00
|
|
|
let deep =
|
|
|
|
|
self.name == other.name && self.vis == other.vis && self.safety == other.safety;
|
2023-05-13 00:42:23 +00:00
|
|
|
assert!(deep, "FieldDef for the same def-id has differing data");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res
|
2021-07-03 12:18:13 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Eq for FieldDef {}
|
|
|
|
|
|
|
|
|
|
impl Hash for FieldDef {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn hash<H: Hasher>(&self, s: &mut H) {
|
2022-07-20 20:21:57 +00:00
|
|
|
// There should be only one `FieldDef` for each `did`, therefore it is
|
|
|
|
|
// fine to implement `Hash` only based on `did`.
|
|
|
|
|
//
|
|
|
|
|
// Below, we exhaustively destructure `self` so that if the definition
|
|
|
|
|
// of `FieldDef` changes, a compile-error will be produced, reminding
|
|
|
|
|
// us to revisit this assumption.
|
|
|
|
|
|
2024-08-24 17:22:48 +00:00
|
|
|
let Self { did, name: _, vis: _, safety: _, value: _ } = &self;
|
2022-07-20 20:21:57 +00:00
|
|
|
|
|
|
|
|
did.hash(s)
|
2021-07-03 12:18:13 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl<'tcx> FieldDef {
|
2023-07-11 22:35:29 +01:00
|
|
|
/// Returns the type of this field. The resulting type is not normalized. The `arg` is
|
2021-11-03 11:12:39 -07:00
|
|
|
/// typically obtained via the second field of [`TyKind::Adt`].
|
2024-12-29 04:42:21 +00:00
|
|
|
pub fn ty(&self, tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
|
|
|
|
|
tcx.type_of(self.did).instantiate(tcx, args)
|
2015-07-22 21:53:52 +03:00
|
|
|
}
|
2022-01-02 22:37:05 -05:00
|
|
|
|
|
|
|
|
/// Computes the `Ident` of this variant by looking up the `Span`
|
|
|
|
|
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
|
|
|
|
|
Ident::new(self.name, tcx.def_ident_span(self.did).unwrap())
|
|
|
|
|
}
|
2016-09-14 23:58:58 +08:00
|
|
|
}
|
|
|
|
|
|
2019-01-03 23:46:46 +02:00
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
|
|
|
pub enum ImplOverlapKind {
|
|
|
|
|
/// These impls are always allowed to overlap.
|
2020-01-09 10:01:20 -05:00
|
|
|
Permitted {
|
2020-01-25 15:30:19 -05:00
|
|
|
/// Whether or not the impl is permitted due to the trait being a `#[marker]` trait
|
2020-01-09 10:01:20 -05:00
|
|
|
marker: bool,
|
|
|
|
|
},
|
2019-01-03 23:46:46 +02:00
|
|
|
}
|
|
|
|
|
|
2023-03-12 20:32:50 +00:00
|
|
|
/// Useful source information about where a desugared associated type for an
|
|
|
|
|
/// RPITIT originated from.
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable)]
|
2023-02-28 18:27:26 -03:00
|
|
|
pub enum ImplTraitInTraitData {
|
|
|
|
|
Trait { fn_def_id: DefId, opaque_def_id: DefId },
|
|
|
|
|
Impl { fn_def_id: DefId },
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl<'tcx> TyCtxt<'tcx> {
|
2020-07-17 08:47:04 +00:00
|
|
|
pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> {
|
2025-02-17 14:17:57 +11:00
|
|
|
self.typeck(self.hir_body_owner_def_id(body))
|
2017-01-06 21:54:24 +02:00
|
|
|
}
|
|
|
|
|
|
2020-02-17 13:09:01 -08:00
|
|
|
pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'tcx AssocItem> {
|
2016-11-10 02:06:34 +02:00
|
|
|
self.associated_items(id)
|
2020-02-17 13:09:01 -08:00
|
|
|
.in_definition_order()
|
2025-04-11 06:28:59 +10:00
|
|
|
.filter(move |item| item.is_fn() && item.defaultness(self).has_value())
|
2015-06-25 23:42:17 +03:00
|
|
|
}
|
|
|
|
|
|
2024-02-22 10:18:56 +01:00
|
|
|
pub fn repr_options_of_def(self, did: LocalDefId) -> ReprOptions {
|
2022-11-07 00:36:11 +03:30
|
|
|
let mut flags = ReprFlags::empty();
|
|
|
|
|
let mut size = None;
|
|
|
|
|
let mut max_align: Option<Align> = None;
|
|
|
|
|
let mut min_pack: Option<Align> = None;
|
|
|
|
|
|
|
|
|
|
// Generate a deterministically-derived seed from the item's path hash
|
|
|
|
|
// to allow for cross-crate compilation to actually work
|
2025-02-15 13:57:21 -05:00
|
|
|
let mut field_shuffle_seed = self.def_path_hash(did.to_def_id()).0.to_smaller_hash();
|
2022-11-07 00:36:11 +03:30
|
|
|
|
|
|
|
|
// If the user defined a custom seed for layout randomization, xor the item's
|
|
|
|
|
// path hash with the user defined seed, this will allowing determinism while
|
|
|
|
|
// still allowing users to further randomize layout generation for e.g. fuzzing
|
|
|
|
|
if let Some(user_seed) = self.sess.opts.unstable_opts.layout_seed {
|
|
|
|
|
field_shuffle_seed ^= user_seed;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-04 12:42:33 +02:00
|
|
|
if let Some(reprs) =
|
2025-07-31 11:00:40 +02:00
|
|
|
find_attr!(self.get_all_attrs(did), AttributeKind::Repr { reprs, .. } => reprs)
|
2025-02-09 22:49:33 +01:00
|
|
|
{
|
|
|
|
|
for (r, _) in reprs {
|
|
|
|
|
flags.insert(match *r {
|
2023-07-29 06:58:29 +00:00
|
|
|
attr::ReprRust => ReprFlags::empty(),
|
2022-11-07 00:36:11 +03:30
|
|
|
attr::ReprC => ReprFlags::IS_C,
|
|
|
|
|
attr::ReprPacked(pack) => {
|
|
|
|
|
min_pack = Some(if let Some(min_pack) = min_pack {
|
|
|
|
|
min_pack.min(pack)
|
|
|
|
|
} else {
|
|
|
|
|
pack
|
|
|
|
|
});
|
|
|
|
|
ReprFlags::empty()
|
|
|
|
|
}
|
|
|
|
|
attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
|
|
|
|
|
attr::ReprSimd => ReprFlags::IS_SIMD,
|
|
|
|
|
attr::ReprInt(i) => {
|
|
|
|
|
size = Some(match i {
|
|
|
|
|
attr::IntType::SignedInt(x) => match x {
|
|
|
|
|
ast::IntTy::Isize => IntegerType::Pointer(true),
|
|
|
|
|
ast::IntTy::I8 => IntegerType::Fixed(Integer::I8, true),
|
|
|
|
|
ast::IntTy::I16 => IntegerType::Fixed(Integer::I16, true),
|
|
|
|
|
ast::IntTy::I32 => IntegerType::Fixed(Integer::I32, true),
|
|
|
|
|
ast::IntTy::I64 => IntegerType::Fixed(Integer::I64, true),
|
|
|
|
|
ast::IntTy::I128 => IntegerType::Fixed(Integer::I128, true),
|
|
|
|
|
},
|
|
|
|
|
attr::IntType::UnsignedInt(x) => match x {
|
|
|
|
|
ast::UintTy::Usize => IntegerType::Pointer(false),
|
|
|
|
|
ast::UintTy::U8 => IntegerType::Fixed(Integer::I8, false),
|
|
|
|
|
ast::UintTy::U16 => IntegerType::Fixed(Integer::I16, false),
|
|
|
|
|
ast::UintTy::U32 => IntegerType::Fixed(Integer::I32, false),
|
|
|
|
|
ast::UintTy::U64 => IntegerType::Fixed(Integer::I64, false),
|
|
|
|
|
ast::UintTy::U128 => IntegerType::Fixed(Integer::I128, false),
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
ReprFlags::empty()
|
|
|
|
|
}
|
|
|
|
|
attr::ReprAlign(align) => {
|
2024-03-24 01:03:39 +00:00
|
|
|
max_align = max_align.max(Some(align));
|
2022-11-07 00:36:11 +03:30
|
|
|
ReprFlags::empty()
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If `-Z randomize-layout` was enabled for the type definition then we can
|
|
|
|
|
// consider performing layout randomization
|
|
|
|
|
if self.sess.opts.unstable_opts.randomize_layout {
|
|
|
|
|
flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-31 14:43:23 +02:00
|
|
|
// box is special, on the one hand the compiler assumes an ordered layout, with the pointer
|
|
|
|
|
// always at offset zero. On the other hand we want scalar abi optimizations.
|
|
|
|
|
let is_box = self.is_lang_item(did.to_def_id(), LangItem::OwnedBox);
|
|
|
|
|
|
2022-11-07 00:36:11 +03:30
|
|
|
// This is here instead of layout because the choice must make it into metadata.
|
2023-05-01 09:56:39 +00:00
|
|
|
if is_box {
|
2022-11-07 00:36:11 +03:30
|
|
|
flags.insert(ReprFlags::IS_LINEAR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-12 20:13:54 +02:00
|
|
|
/// Look up the name of a definition across crates. This does not look at HIR.
|
2025-07-03 09:09:26 +00:00
|
|
|
pub fn opt_item_name(self, def_id: impl IntoQueryParam<DefId>) -> Option<Symbol> {
|
|
|
|
|
let def_id = def_id.into_query_param();
|
2022-04-15 19:27:53 +02:00
|
|
|
if let Some(cnum) = def_id.as_crate_root() {
|
|
|
|
|
Some(self.crate_name(cnum))
|
2020-10-21 22:00:32 -04:00
|
|
|
} else {
|
|
|
|
|
let def_key = self.def_key(def_id);
|
|
|
|
|
match def_key.disambiguated_data.data {
|
|
|
|
|
// The name of a constructor is that of its parent.
|
2022-04-08 23:06:20 +02:00
|
|
|
rustc_hir::definitions::DefPathData::Ctor => self
|
|
|
|
|
.opt_item_name(DefId { krate: def_id.krate, index: def_key.parent.unwrap() }),
|
|
|
|
|
_ => def_key.get_opt_name(),
|
2020-10-21 22:00:32 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-08 23:06:20 +02:00
|
|
|
/// Look up the name of a definition across crates. This does not look at HIR.
|
2020-10-21 22:00:32 -04:00
|
|
|
///
|
2022-11-16 20:34:16 +00:00
|
|
|
/// This method will ICE if the corresponding item does not have a name. In these cases, use
|
2020-10-21 22:00:32 -04:00
|
|
|
/// [`opt_item_name`] instead.
|
|
|
|
|
///
|
|
|
|
|
/// [`opt_item_name`]: Self::opt_item_name
|
2025-07-03 09:09:26 +00:00
|
|
|
pub fn item_name(self, id: impl IntoQueryParam<DefId>) -> Symbol {
|
|
|
|
|
let id = id.into_query_param();
|
2022-04-08 23:06:20 +02:00
|
|
|
self.opt_item_name(id).unwrap_or_else(|| {
|
2020-11-07 10:34:00 -05:00
|
|
|
bug!("item_name: no name for {:?}", self.def_path(id));
|
|
|
|
|
})
|
2020-10-21 22:00:32 -04:00
|
|
|
}
|
|
|
|
|
|
2022-04-08 23:06:20 +02:00
|
|
|
/// Look up the name and span of a definition.
|
2020-10-21 22:00:32 -04:00
|
|
|
///
|
|
|
|
|
/// See [`item_name`][Self::item_name] for more information.
|
2025-07-03 09:09:26 +00:00
|
|
|
pub fn opt_item_ident(self, def_id: impl IntoQueryParam<DefId>) -> Option<Ident> {
|
|
|
|
|
let def_id = def_id.into_query_param();
|
2022-04-08 23:06:20 +02:00
|
|
|
let def = self.opt_item_name(def_id)?;
|
2023-05-03 19:27:29 +03:00
|
|
|
let span = self
|
|
|
|
|
.def_ident_span(def_id)
|
|
|
|
|
.unwrap_or_else(|| bug!("missing ident span for {def_id:?}"));
|
2022-04-08 23:06:20 +02:00
|
|
|
Some(Ident::new(def, span))
|
2019-09-04 10:17:59 -07:00
|
|
|
}
|
|
|
|
|
|
2025-01-27 01:16:12 +00:00
|
|
|
/// Look up the name and span of a definition.
|
|
|
|
|
///
|
|
|
|
|
/// See [`item_name`][Self::item_name] for more information.
|
2025-07-03 09:09:26 +00:00
|
|
|
pub fn item_ident(self, def_id: impl IntoQueryParam<DefId>) -> Ident {
|
|
|
|
|
let def_id = def_id.into_query_param();
|
2025-01-27 01:16:12 +00:00
|
|
|
self.opt_item_ident(def_id).unwrap_or_else(|| {
|
|
|
|
|
bug!("item_ident: no name for {:?}", self.def_path(def_id));
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-06 08:57:34 +00:00
|
|
|
pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> {
|
2021-01-10 22:41:50 +01:00
|
|
|
if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
|
|
|
|
|
Some(self.associated_item(def_id))
|
2017-04-18 10:54:47 -04:00
|
|
|
} else {
|
2021-01-10 22:41:50 +01:00
|
|
|
None
|
|
|
|
|
}
|
2017-04-18 10:54:47 -04:00
|
|
|
}
|
|
|
|
|
|
2024-06-14 12:16:15 +00:00
|
|
|
/// If the `def_id` is an associated type that was desugared from a
|
2023-03-12 20:32:50 +00:00
|
|
|
/// return-position `impl Trait` from a trait, then provide the source info
|
|
|
|
|
/// about where that RPITIT came from.
|
|
|
|
|
pub fn opt_rpitit_info(self, def_id: DefId) -> Option<ImplTraitInTraitData> {
|
2025-04-11 16:50:20 +10:00
|
|
|
if let DefKind::AssocTy = self.def_kind(def_id)
|
2025-04-14 13:15:01 +10:00
|
|
|
&& let AssocKind::Type { data: AssocTypeData::Rpitit(rpitit_info) } =
|
|
|
|
|
self.associated_item(def_id).kind
|
2025-04-11 16:50:20 +10:00
|
|
|
{
|
2025-04-14 13:15:01 +10:00
|
|
|
Some(rpitit_info)
|
2023-03-12 20:32:50 +00:00
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-28 23:32:25 -07:00
|
|
|
pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<FieldIdx> {
|
|
|
|
|
variant.fields.iter_enumerated().find_map(|(i, field)| {
|
|
|
|
|
self.hygienic_eq(ident, field.ident(self), variant.def_id).then_some(i)
|
|
|
|
|
})
|
2018-04-05 03:20:21 +03:00
|
|
|
}
|
|
|
|
|
|
2025-02-13 09:53:08 +00:00
|
|
|
/// Returns `Some` if the impls are the same polarity and the trait either
|
2020-05-01 22:28:15 +02:00
|
|
|
/// has no items or is annotated `#[marker]` and prevents item overrides.
|
2023-03-07 08:04:34 +00:00
|
|
|
#[instrument(level = "debug", skip(self), ret)]
|
2019-01-03 23:46:46 +02:00
|
|
|
pub fn impls_are_allowed_to_overlap(
|
|
|
|
|
self,
|
|
|
|
|
def_id1: DefId,
|
|
|
|
|
def_id2: DefId,
|
|
|
|
|
) -> Option<ImplOverlapKind> {
|
2025-07-22 17:05:45 -05:00
|
|
|
let impl1 = self.impl_trait_header(def_id1);
|
|
|
|
|
let impl2 = self.impl_trait_header(def_id2);
|
2024-03-05 20:19:05 +01:00
|
|
|
|
|
|
|
|
let trait_ref1 = impl1.trait_ref.skip_binder();
|
|
|
|
|
let trait_ref2 = impl2.trait_ref.skip_binder();
|
2024-02-10 22:27:03 +00:00
|
|
|
|
2019-09-14 19:26:49 -04:00
|
|
|
// If either trait impl references an error, they're allowed to overlap,
|
|
|
|
|
// as one of them essentially doesn't exist.
|
2024-03-05 20:19:05 +01:00
|
|
|
if trait_ref1.references_error() || trait_ref2.references_error() {
|
2020-01-09 10:01:20 -05:00
|
|
|
return Some(ImplOverlapKind::Permitted { marker: false });
|
2019-09-14 19:26:49 -04:00
|
|
|
}
|
|
|
|
|
|
2024-02-10 22:27:03 +00:00
|
|
|
match (impl1.polarity, impl2.polarity) {
|
2019-07-14 00:09:46 +03:00
|
|
|
(ImplPolarity::Reservation, _) | (_, ImplPolarity::Reservation) => {
|
|
|
|
|
// `#[rustc_reservation_impl]` impls don't overlap with anything
|
2020-01-09 10:01:20 -05:00
|
|
|
return Some(ImplOverlapKind::Permitted { marker: false });
|
2019-07-14 00:09:46 +03:00
|
|
|
}
|
|
|
|
|
(ImplPolarity::Positive, ImplPolarity::Negative)
|
|
|
|
|
| (ImplPolarity::Negative, ImplPolarity::Positive) => {
|
2019-07-27 20:44:14 +03:00
|
|
|
// `impl AutoTrait for Type` + `impl !AutoTrait for Type`
|
2019-07-14 00:09:46 +03:00
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
(ImplPolarity::Positive, ImplPolarity::Positive)
|
|
|
|
|
| (ImplPolarity::Negative, ImplPolarity::Negative) => {}
|
|
|
|
|
};
|
2019-07-13 18:02:00 +03:00
|
|
|
|
2024-04-25 01:58:41 +02:00
|
|
|
let is_marker_impl = |trait_ref: TraitRef<'_>| self.trait_def(trait_ref.def_id).is_marker;
|
|
|
|
|
let is_marker_overlap = is_marker_impl(trait_ref1) && is_marker_impl(trait_ref2);
|
2019-01-03 23:46:46 +02:00
|
|
|
|
2019-07-14 00:09:46 +03:00
|
|
|
if is_marker_overlap {
|
2024-04-25 01:58:41 +02:00
|
|
|
return Some(ImplOverlapKind::Permitted { marker: true });
|
|
|
|
|
}
|
2019-01-03 23:46:46 +02:00
|
|
|
|
2024-04-25 01:58:41 +02:00
|
|
|
None
|
2017-02-25 16:16:27 -05:00
|
|
|
}
|
|
|
|
|
|
2019-04-20 19:36:05 +03:00
|
|
|
/// Returns `ty::VariantDef` if `res` refers to a struct,
|
2019-03-22 17:19:12 +01:00
|
|
|
/// or variant or their constructors, panics otherwise.
|
2019-04-20 19:36:05 +03:00
|
|
|
pub fn expect_variant_res(self, res: Res) -> &'tcx VariantDef {
|
|
|
|
|
match res {
|
|
|
|
|
Res::Def(DefKind::Variant, did) => {
|
2022-04-25 22:08:45 +03:00
|
|
|
let enum_did = self.parent(did);
|
2019-03-24 12:09:44 +03:00
|
|
|
self.adt_def(enum_did).variant_with_id(did)
|
2016-06-11 18:47:47 +03:00
|
|
|
}
|
2020-04-16 17:38:52 -07:00
|
|
|
Res::Def(DefKind::Struct | DefKind::Union, did) => self.adt_def(did).non_enum_variant(),
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_did) => {
|
2022-04-25 22:08:45 +03:00
|
|
|
let variant_did = self.parent(variant_ctor_did);
|
|
|
|
|
let enum_did = self.parent(variant_did);
|
2019-03-21 23:38:50 +01:00
|
|
|
self.adt_def(enum_did).variant_with_ctor_id(variant_ctor_did)
|
|
|
|
|
}
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Def(DefKind::Ctor(CtorOf::Struct, ..), ctor_did) => {
|
2022-04-25 22:08:45 +03:00
|
|
|
let struct_did = self.parent(ctor_did);
|
2019-03-21 23:38:50 +01:00
|
|
|
self.adt_def(struct_did).non_enum_variant()
|
2016-06-11 18:47:47 +03:00
|
|
|
}
|
2019-04-20 19:36:05 +03:00
|
|
|
_ => bug!("expect_variant_res used with unexpected res {:?}", res),
|
2016-06-11 18:47:47 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-16 21:35:16 -04:00
|
|
|
/// Returns the possibly-auto-generated MIR of a [`ty::InstanceKind`].
|
2022-02-16 10:56:01 +01:00
|
|
|
#[instrument(skip(self), level = "debug")]
|
2024-06-16 21:35:16 -04:00
|
|
|
pub fn instance_mir(self, instance: ty::InstanceKind<'tcx>) -> &'tcx Body<'tcx> {
|
2017-02-08 18:31:03 +01:00
|
|
|
match instance {
|
2024-06-16 21:35:16 -04:00
|
|
|
ty::InstanceKind::Item(def) => {
|
2022-02-16 10:56:01 +01:00
|
|
|
debug!("calling def_kind on def: {:?}", def);
|
2022-05-08 15:53:19 +02:00
|
|
|
let def_kind = self.def_kind(def);
|
2022-02-16 10:56:01 +01:00
|
|
|
debug!("returned from def_kind: {:?}", def_kind);
|
|
|
|
|
match def_kind {
|
|
|
|
|
DefKind::Const
|
2024-02-23 23:12:20 +00:00
|
|
|
| DefKind::Static { .. }
|
2022-02-16 10:56:01 +01:00
|
|
|
| DefKind::AssocConst
|
|
|
|
|
| DefKind::Ctor(..)
|
|
|
|
|
| DefKind::AnonConst
|
2022-05-08 15:53:19 +02:00
|
|
|
| DefKind::InlineConst => self.mir_for_ctfe(def),
|
2022-02-16 10:56:01 +01:00
|
|
|
// If the caller wants `mir_for_ctfe` of a function they should not be using
|
|
|
|
|
// `instance_mir`, so we'll assume const fn also wants the optimized version.
|
2022-05-08 15:53:19 +02:00
|
|
|
_ => self.optimized_mir(def),
|
2021-03-04 12:21:36 +00:00
|
|
|
}
|
2022-02-16 10:56:01 +01:00
|
|
|
}
|
2024-06-16 21:35:16 -04:00
|
|
|
ty::InstanceKind::VTableShim(..)
|
|
|
|
|
| ty::InstanceKind::ReifyShim(..)
|
|
|
|
|
| ty::InstanceKind::Intrinsic(..)
|
|
|
|
|
| ty::InstanceKind::FnPtrShim(..)
|
|
|
|
|
| ty::InstanceKind::Virtual(..)
|
|
|
|
|
| ty::InstanceKind::ClosureOnceShim { .. }
|
|
|
|
|
| ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
|
2024-08-26 16:45:15 +03:00
|
|
|
| ty::InstanceKind::FutureDropPollShim(..)
|
2024-06-16 21:35:16 -04:00
|
|
|
| ty::InstanceKind::DropGlue(..)
|
|
|
|
|
| ty::InstanceKind::CloneShim(..)
|
|
|
|
|
| ty::InstanceKind::ThreadLocalShim(..)
|
|
|
|
|
| ty::InstanceKind::FnPtrAddrShim(..)
|
2024-08-26 16:45:15 +03:00
|
|
|
| ty::InstanceKind::AsyncDropGlueCtorShim(..)
|
|
|
|
|
| ty::InstanceKind::AsyncDropGlue(..) => self.mir_shims(instance),
|
2017-02-08 18:31:03 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-02 09:31:56 +02:00
|
|
|
/// Gets all attributes with the given name.
|
2023-03-13 18:54:05 +00:00
|
|
|
pub fn get_attrs(
|
|
|
|
|
self,
|
|
|
|
|
did: impl Into<DefId>,
|
|
|
|
|
attr: Symbol,
|
2025-02-09 22:49:33 +01:00
|
|
|
) -> impl Iterator<Item = &'tcx hir::Attribute> {
|
2025-06-23 23:41:33 +03:00
|
|
|
self.get_all_attrs(did).iter().filter(move |a: &&hir::Attribute| a.has_name(attr))
|
2025-02-09 22:49:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Gets all attributes.
|
|
|
|
|
///
|
2025-07-31 09:08:46 +10:00
|
|
|
/// To see if an item has a specific attribute, you should use
|
2025-07-31 11:00:40 +02:00
|
|
|
/// [`rustc_hir::find_attr!`] so you can use matching.
|
2025-06-23 23:41:33 +03:00
|
|
|
pub fn get_all_attrs(self, did: impl Into<DefId>) -> &'tcx [hir::Attribute] {
|
2023-03-13 18:54:05 +00:00
|
|
|
let did: DefId = did.into();
|
2022-05-02 09:31:56 +02:00
|
|
|
if let Some(did) = did.as_local() {
|
2025-06-23 23:41:33 +03:00
|
|
|
self.hir_attrs(self.local_def_id_to_hir_id(did))
|
2022-05-02 09:31:56 +02:00
|
|
|
} else {
|
2025-06-23 23:41:33 +03:00
|
|
|
self.attrs_for_def(did)
|
2022-05-02 09:31:56 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-06 18:47:22 +02:00
|
|
|
/// Get an attribute from the diagnostic attribute namespace
|
|
|
|
|
///
|
|
|
|
|
/// This function requests an attribute with the following structure:
|
|
|
|
|
///
|
|
|
|
|
/// `#[diagnostic::$attr]`
|
|
|
|
|
///
|
|
|
|
|
/// This function performs feature checking, so if an attribute is returned
|
|
|
|
|
/// it can be used by the consumer
|
|
|
|
|
pub fn get_diagnostic_attr(
|
|
|
|
|
self,
|
|
|
|
|
did: impl Into<DefId>,
|
|
|
|
|
attr: Symbol,
|
2024-10-17 01:14:01 +02:00
|
|
|
) -> Option<&'tcx hir::Attribute> {
|
2024-09-06 18:47:22 +02:00
|
|
|
let did: DefId = did.into();
|
|
|
|
|
if did.as_local().is_some() {
|
|
|
|
|
// it's a crate local item, we need to check feature flags
|
|
|
|
|
if rustc_feature::is_stable_diagnostic_attribute(attr, self.features()) {
|
|
|
|
|
self.get_attrs_by_path(did, &[sym::diagnostic, sym::do_not_recommend]).next()
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// we filter out unstable diagnostic attributes before
|
|
|
|
|
// encoding attributes
|
|
|
|
|
debug_assert!(rustc_feature::encode_cross_crate(attr));
|
2024-10-17 01:14:01 +02:00
|
|
|
self.attrs_for_def(did)
|
2024-09-06 18:47:22 +02:00
|
|
|
.iter()
|
|
|
|
|
.find(|a| matches!(a.path().as_ref(), [sym::diagnostic, a] if *a == attr))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-20 18:58:46 +00:00
|
|
|
pub fn get_attrs_by_path(
|
2023-06-02 13:55:46 +02:00
|
|
|
self,
|
|
|
|
|
did: DefId,
|
2025-02-20 18:58:46 +00:00
|
|
|
attr: &[Symbol],
|
|
|
|
|
) -> impl Iterator<Item = &'tcx hir::Attribute> {
|
2024-10-17 01:14:01 +02:00
|
|
|
let filter_fn = move |a: &&hir::Attribute| a.path_matches(attr);
|
2023-06-02 13:55:46 +02:00
|
|
|
if let Some(did) = did.as_local() {
|
2025-02-21 18:33:05 +11:00
|
|
|
self.hir_attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
|
2023-06-02 13:55:46 +02:00
|
|
|
} else {
|
2024-10-17 01:14:01 +02:00
|
|
|
self.attrs_for_def(did).iter().filter(filter_fn)
|
2023-06-02 13:55:46 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-17 01:14:01 +02:00
|
|
|
pub fn get_attr(self, did: impl Into<DefId>, attr: Symbol) -> Option<&'tcx hir::Attribute> {
|
2022-09-06 14:16:54 +08:00
|
|
|
if cfg!(debug_assertions) && !rustc_feature::is_valid_for_get_attr(attr) {
|
2023-03-13 18:54:05 +00:00
|
|
|
let did: DefId = did.into();
|
2022-09-06 14:16:54 +08:00
|
|
|
bug!("get_attr: unexpected called with DefId `{:?}`, attr `{:?}`", did, attr);
|
|
|
|
|
} else {
|
|
|
|
|
self.get_attrs(did, attr).next()
|
|
|
|
|
}
|
2022-05-02 09:31:56 +02:00
|
|
|
}
|
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Determines whether an item is annotated with an attribute.
|
2023-03-13 18:54:05 +00:00
|
|
|
pub fn has_attr(self, did: impl Into<DefId>, attr: Symbol) -> bool {
|
2024-03-19 00:05:18 +08:00
|
|
|
self.get_attrs(did, attr).next().is_some()
|
2015-06-25 23:42:17 +03:00
|
|
|
}
|
2013-05-24 18:08:45 -04:00
|
|
|
|
2024-09-02 07:50:22 +02:00
|
|
|
/// Determines whether an item is annotated with a multi-segment attribute
|
2024-05-10 14:12:30 +02:00
|
|
|
pub fn has_attrs_with_path(self, did: impl Into<DefId>, attrs: &[Symbol]) -> bool {
|
|
|
|
|
self.get_attrs_by_path(did.into(), attrs).next().is_some()
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-01 19:43:38 +00:00
|
|
|
/// Returns `true` if this is an `auto trait`.
|
2017-10-16 17:33:45 -02:00
|
|
|
pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
|
2017-10-09 13:59:20 -03:00
|
|
|
self.trait_def(trait_def_id).has_auto_impl
|
2015-06-25 23:42:17 +03:00
|
|
|
}
|
2014-02-05 17:31:33 +13:00
|
|
|
|
2023-02-14 10:17:19 +01:00
|
|
|
/// Returns `true` if this is coinductive, either because it is
|
|
|
|
|
/// an auto trait or because it has the `#[rustc_coinductive]` attribute.
|
|
|
|
|
pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool {
|
|
|
|
|
self.trait_def(trait_def_id).is_coinductive
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 20:16:30 +00:00
|
|
|
/// Returns `true` if this is a trait alias.
|
|
|
|
|
pub fn trait_is_alias(self, trait_def_id: DefId) -> bool {
|
|
|
|
|
self.def_kind(trait_def_id) == DefKind::TraitAlias
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-11 20:58:52 +07:00
|
|
|
/// Arena-alloc of LayoutError for coroutine layout
|
|
|
|
|
fn layout_error(self, err: LayoutError<'tcx>) -> &'tcx LayoutError<'tcx> {
|
|
|
|
|
self.arena.alloc(err)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-26 16:45:15 +03:00
|
|
|
/// Returns layout of a non-async-drop coroutine. Layout might be unavailable if the
|
2023-10-19 21:46:28 +00:00
|
|
|
/// coroutine is tainted by errors.
|
2024-03-24 21:12:49 -04:00
|
|
|
///
|
|
|
|
|
/// Takes `coroutine_kind` which can be acquired from the `CoroutineArgs::kind_ty`,
|
|
|
|
|
/// e.g. `args.as_coroutine().kind_ty()`.
|
2024-08-26 16:45:15 +03:00
|
|
|
fn ordinary_coroutine_layout(
|
2024-03-24 21:12:49 -04:00
|
|
|
self,
|
|
|
|
|
def_id: DefId,
|
2025-05-11 20:58:52 +07:00
|
|
|
args: GenericArgsRef<'tcx>,
|
|
|
|
|
) -> Result<&'tcx CoroutineLayout<'tcx>, &'tcx LayoutError<'tcx>> {
|
|
|
|
|
let coroutine_kind_ty = args.as_coroutine().kind_ty();
|
2024-03-24 21:12:49 -04:00
|
|
|
let mir = self.optimized_mir(def_id);
|
2025-05-11 20:58:52 +07:00
|
|
|
let ty = || Ty::new_coroutine(self, def_id, args);
|
2024-03-24 21:12:49 -04:00
|
|
|
// Regular coroutine
|
|
|
|
|
if coroutine_kind_ty.is_unit() {
|
2025-05-11 20:58:52 +07:00
|
|
|
mir.coroutine_layout_raw().ok_or_else(|| self.layout_error(LayoutError::Unknown(ty())))
|
2024-03-24 21:12:49 -04:00
|
|
|
} else {
|
|
|
|
|
// If we have a `Coroutine` that comes from an coroutine-closure,
|
|
|
|
|
// then it may be a by-move or by-ref body.
|
|
|
|
|
let ty::Coroutine(_, identity_args) =
|
|
|
|
|
*self.type_of(def_id).instantiate_identity().kind()
|
|
|
|
|
else {
|
|
|
|
|
unreachable!();
|
|
|
|
|
};
|
|
|
|
|
let identity_kind_ty = identity_args.as_coroutine().kind_ty();
|
|
|
|
|
// If the types differ, then we must be getting the by-move body of
|
|
|
|
|
// a by-ref coroutine.
|
|
|
|
|
if identity_kind_ty == coroutine_kind_ty {
|
|
|
|
|
mir.coroutine_layout_raw()
|
2025-05-11 20:58:52 +07:00
|
|
|
.ok_or_else(|| self.layout_error(LayoutError::Unknown(ty())))
|
2024-03-24 21:12:49 -04:00
|
|
|
} else {
|
|
|
|
|
assert_matches!(coroutine_kind_ty.to_opt_closure_kind(), Some(ClosureKind::FnOnce));
|
|
|
|
|
assert_matches!(
|
|
|
|
|
identity_kind_ty.to_opt_closure_kind(),
|
|
|
|
|
Some(ClosureKind::Fn | ClosureKind::FnMut)
|
|
|
|
|
);
|
2024-08-01 13:05:17 -04:00
|
|
|
self.optimized_mir(self.coroutine_by_move_body_def_id(def_id))
|
|
|
|
|
.coroutine_layout_raw()
|
2025-05-11 20:58:52 +07:00
|
|
|
.ok_or_else(|| self.layout_error(LayoutError::Unknown(ty())))
|
2024-03-24 21:12:49 -04:00
|
|
|
}
|
|
|
|
|
}
|
2016-12-26 14:34:03 +01:00
|
|
|
}
|
|
|
|
|
|
2024-08-26 16:45:15 +03:00
|
|
|
/// Returns layout of a `async_drop_in_place::{closure}` coroutine
|
|
|
|
|
/// (returned from `async fn async_drop_in_place<T>(..)`).
|
|
|
|
|
/// Layout might be unavailable if the coroutine is tainted by errors.
|
|
|
|
|
fn async_drop_coroutine_layout(
|
|
|
|
|
self,
|
|
|
|
|
def_id: DefId,
|
|
|
|
|
args: GenericArgsRef<'tcx>,
|
2025-05-11 20:58:52 +07:00
|
|
|
) -> Result<&'tcx CoroutineLayout<'tcx>, &'tcx LayoutError<'tcx>> {
|
|
|
|
|
let ty = || Ty::new_coroutine(self, def_id, args);
|
2025-05-11 02:21:56 +07:00
|
|
|
if args[0].has_placeholders() || args[0].has_non_region_param() {
|
2025-05-11 20:58:52 +07:00
|
|
|
return Err(self.layout_error(LayoutError::TooGeneric(ty())));
|
2025-05-11 02:21:56 +07:00
|
|
|
}
|
2024-08-26 16:45:15 +03:00
|
|
|
let instance = InstanceKind::AsyncDropGlue(def_id, Ty::new_coroutine(self, def_id, args));
|
2025-05-11 20:58:52 +07:00
|
|
|
self.mir_shims(instance)
|
|
|
|
|
.coroutine_layout_raw()
|
|
|
|
|
.ok_or_else(|| self.layout_error(LayoutError::Unknown(ty())))
|
2024-08-26 16:45:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns layout of a coroutine. Layout might be unavailable if the
|
|
|
|
|
/// coroutine is tainted by errors.
|
|
|
|
|
pub fn coroutine_layout(
|
|
|
|
|
self,
|
|
|
|
|
def_id: DefId,
|
|
|
|
|
args: GenericArgsRef<'tcx>,
|
2025-05-11 20:58:52 +07:00
|
|
|
) -> Result<&'tcx CoroutineLayout<'tcx>, &'tcx LayoutError<'tcx>> {
|
2024-08-26 16:45:15 +03:00
|
|
|
if self.is_async_drop_in_place_coroutine(def_id) {
|
|
|
|
|
// layout of `async_drop_in_place<T>::{closure}` in case,
|
|
|
|
|
// when T is a coroutine, contains this internal coroutine's ptr in upvars
|
|
|
|
|
// and doesn't require any locals. Here is an `empty coroutine's layout`
|
|
|
|
|
let arg_cor_ty = args.first().unwrap().expect_ty();
|
|
|
|
|
if arg_cor_ty.is_coroutine() {
|
|
|
|
|
let span = self.def_span(def_id);
|
|
|
|
|
let source_info = SourceInfo::outermost(span);
|
2025-05-04 01:24:39 +07:00
|
|
|
// Even minimal, empty coroutine has 3 states (RESERVED_VARIANTS),
|
|
|
|
|
// so variant_fields and variant_source_info should have 3 elements.
|
2024-08-26 16:45:15 +03:00
|
|
|
let variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, CoroutineSavedLocal>> =
|
|
|
|
|
iter::repeat(IndexVec::new()).take(CoroutineArgs::RESERVED_VARIANTS).collect();
|
2025-05-04 01:24:39 +07:00
|
|
|
let variant_source_info: IndexVec<VariantIdx, SourceInfo> =
|
|
|
|
|
iter::repeat(source_info).take(CoroutineArgs::RESERVED_VARIANTS).collect();
|
2024-08-26 16:45:15 +03:00
|
|
|
let proxy_layout = CoroutineLayout {
|
|
|
|
|
field_tys: [].into(),
|
|
|
|
|
field_names: [].into(),
|
|
|
|
|
variant_fields,
|
2025-05-04 01:24:39 +07:00
|
|
|
variant_source_info,
|
2024-08-26 16:45:15 +03:00
|
|
|
storage_conflicts: BitMatrix::new(0, 0),
|
|
|
|
|
};
|
2025-05-11 20:58:52 +07:00
|
|
|
return Ok(self.arena.alloc(proxy_layout));
|
2024-08-26 16:45:15 +03:00
|
|
|
} else {
|
|
|
|
|
self.async_drop_coroutine_layout(def_id, args)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2025-05-11 20:58:52 +07:00
|
|
|
self.ordinary_coroutine_layout(def_id, args)
|
2024-08-26 16:45:15 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-12 17:57:02 -05:00
|
|
|
/// If the given `DefId` is an associated item, returns the `DefId` and `DefKind` of the parent trait or impl.
|
|
|
|
|
pub fn assoc_parent(self, def_id: DefId) -> Option<(DefId, DefKind)> {
|
|
|
|
|
if !self.def_kind(def_id).is_assoc() {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
let parent = self.parent(def_id);
|
|
|
|
|
let def_kind = self.def_kind(parent);
|
|
|
|
|
Some((parent, def_kind))
|
2025-07-24 18:34:17 -05:00
|
|
|
}
|
|
|
|
|
|
2025-08-15 16:12:35 -05:00
|
|
|
/// Returns the trait item that is implemented by the given item `DefId`.
|
|
|
|
|
pub fn trait_item_of(self, def_id: impl IntoQueryParam<DefId>) -> Option<DefId> {
|
2025-08-13 15:24:19 -05:00
|
|
|
self.opt_associated_item(def_id.into_query_param())?.trait_item_def_id()
|
2025-08-15 16:12:35 -05:00
|
|
|
}
|
|
|
|
|
|
2025-07-24 19:01:22 -05:00
|
|
|
/// If the given `DefId` is an associated item of a trait,
|
|
|
|
|
/// returns the `DefId` of the trait; otherwise, returns `None`.
|
2025-07-24 19:05:31 -05:00
|
|
|
pub fn trait_of_assoc(self, def_id: DefId) -> Option<DefId> {
|
2025-08-12 17:57:02 -05:00
|
|
|
match self.assoc_parent(def_id) {
|
|
|
|
|
Some((id, DefKind::Trait)) => Some(id),
|
|
|
|
|
_ => None,
|
|
|
|
|
}
|
2022-03-13 00:58:21 +01:00
|
|
|
}
|
|
|
|
|
|
2025-10-13 12:56:21 -05:00
|
|
|
pub fn impl_is_of_trait(self, def_id: impl IntoQueryParam<DefId>) -> bool {
|
|
|
|
|
let def_id = def_id.into_query_param();
|
|
|
|
|
let DefKind::Impl { of_trait } = self.def_kind(def_id) else {
|
|
|
|
|
panic!("expected Impl for {def_id:?}");
|
|
|
|
|
};
|
|
|
|
|
of_trait
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-24 19:01:22 -05:00
|
|
|
/// If the given `DefId` is an associated item of an impl,
|
|
|
|
|
/// returns the `DefId` of the impl; otherwise returns `None`.
|
2025-07-24 19:09:05 -05:00
|
|
|
pub fn impl_of_assoc(self, def_id: DefId) -> Option<DefId> {
|
2025-08-12 17:57:02 -05:00
|
|
|
match self.assoc_parent(def_id) {
|
|
|
|
|
Some((id, DefKind::Impl { .. })) => Some(id),
|
|
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// If the given `DefId` is an associated item of an inherent impl,
|
|
|
|
|
/// returns the `DefId` of the impl; otherwise, returns `None`.
|
|
|
|
|
pub fn inherent_impl_of_assoc(self, def_id: DefId) -> Option<DefId> {
|
|
|
|
|
match self.assoc_parent(def_id) {
|
|
|
|
|
Some((id, DefKind::Impl { of_trait: false })) => Some(id),
|
|
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// If the given `DefId` is an associated item of a trait impl,
|
|
|
|
|
/// returns the `DefId` of the impl; otherwise, returns `None`.
|
|
|
|
|
pub fn trait_impl_of_assoc(self, def_id: DefId) -> Option<DefId> {
|
|
|
|
|
match self.assoc_parent(def_id) {
|
|
|
|
|
Some((id, DefKind::Impl { of_trait: true })) => Some(id),
|
|
|
|
|
_ => None,
|
|
|
|
|
}
|
2013-08-23 14:34:00 -07:00
|
|
|
}
|
|
|
|
|
|
2025-07-24 16:08:35 -05:00
|
|
|
pub fn impl_polarity(self, def_id: impl IntoQueryParam<DefId>) -> ty::ImplPolarity {
|
2025-07-22 17:05:45 -05:00
|
|
|
self.impl_trait_header(def_id).polarity
|
2025-07-24 16:08:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Given an `impl_id`, return the trait it implements.
|
|
|
|
|
pub fn impl_trait_ref(
|
|
|
|
|
self,
|
|
|
|
|
def_id: impl IntoQueryParam<DefId>,
|
2025-10-13 12:56:21 -05:00
|
|
|
) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> {
|
2025-07-22 17:05:45 -05:00
|
|
|
self.impl_trait_header(def_id).trait_ref
|
2025-10-13 12:56:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Given an `impl_id`, return the trait it implements.
|
|
|
|
|
/// Returns `None` if it is an inherent impl.
|
|
|
|
|
pub fn impl_opt_trait_ref(
|
|
|
|
|
self,
|
|
|
|
|
def_id: impl IntoQueryParam<DefId>,
|
2025-07-24 16:08:35 -05:00
|
|
|
) -> Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>> {
|
2025-07-22 17:05:45 -05:00
|
|
|
let def_id = def_id.into_query_param();
|
|
|
|
|
self.impl_is_of_trait(def_id).then(|| self.impl_trait_ref(def_id))
|
2025-07-24 16:08:35 -05:00
|
|
|
}
|
|
|
|
|
|
2025-08-09 16:39:04 -05:00
|
|
|
/// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
|
2025-10-13 12:56:21 -05:00
|
|
|
pub fn impl_trait_id(self, def_id: impl IntoQueryParam<DefId>) -> DefId {
|
|
|
|
|
self.impl_trait_ref(def_id).skip_binder().def_id
|
2025-08-09 16:39:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
|
2025-10-13 12:56:21 -05:00
|
|
|
/// Returns `None` if it is an inherent impl.
|
|
|
|
|
pub fn impl_opt_trait_id(self, def_id: impl IntoQueryParam<DefId>) -> Option<DefId> {
|
|
|
|
|
let def_id = def_id.into_query_param();
|
|
|
|
|
self.impl_is_of_trait(def_id).then(|| self.impl_trait_id(def_id))
|
2025-08-09 16:39:04 -05:00
|
|
|
}
|
|
|
|
|
|
2024-09-30 21:07:36 +03:00
|
|
|
pub fn is_exportable(self, def_id: DefId) -> bool {
|
|
|
|
|
self.exportable_items(def_id.krate).contains(&def_id)
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-03 04:10:46 +01:00
|
|
|
/// Check if the given `DefId` is `#\[automatically_derived\]`, *and*
|
2023-02-16 17:17:55 +00:00
|
|
|
/// whether it was produced by expanding a builtin derive macro.
|
|
|
|
|
pub fn is_builtin_derived(self, def_id: DefId) -> bool {
|
|
|
|
|
if self.is_automatically_derived(def_id)
|
|
|
|
|
&& let Some(def_id) = def_id.as_local()
|
|
|
|
|
&& let outer = self.def_span(def_id).ctxt().outer_expn_data()
|
|
|
|
|
&& matches!(outer.kind, ExpnKind::Macro(MacroKind::Derive, _))
|
2025-07-07 20:48:42 +02:00
|
|
|
&& find_attr!(
|
|
|
|
|
self.get_all_attrs(outer.macro_def_id.unwrap()),
|
|
|
|
|
AttributeKind::RustcBuiltinMacro { .. }
|
|
|
|
|
)
|
2023-02-16 17:17:55 +00:00
|
|
|
{
|
|
|
|
|
true
|
|
|
|
|
} else {
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Check if the given `DefId` is `#\[automatically_derived\]`.
|
|
|
|
|
pub fn is_automatically_derived(self, def_id: DefId) -> bool {
|
2025-07-11 12:01:11 +02:00
|
|
|
find_attr!(self.get_all_attrs(def_id), AttributeKind::AutomaticallyDerived(..))
|
2021-12-13 20:56:40 +00:00
|
|
|
}
|
|
|
|
|
|
2015-12-29 10:55:34 -08:00
|
|
|
/// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err`
|
|
|
|
|
/// with the name of the crate containing the impl.
|
2022-10-19 17:17:19 +02:00
|
|
|
pub fn span_of_impl(self, impl_def_id: DefId) -> Result<Span, Symbol> {
|
|
|
|
|
if let Some(impl_def_id) = impl_def_id.as_local() {
|
|
|
|
|
Ok(self.def_span(impl_def_id))
|
2015-12-29 10:55:34 -08:00
|
|
|
} else {
|
2022-10-19 17:17:19 +02:00
|
|
|
Err(self.crate_name(impl_def_id.krate))
|
2015-12-29 10:55:34 -08:00
|
|
|
}
|
|
|
|
|
}
|
2017-03-24 23:03:15 +00:00
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Hygienically compares a use-site name (`use_name`) for a field or an associated item with
|
|
|
|
|
/// its supposed definition name (`def_name`). The method also needs `DefId` of the supposed
|
|
|
|
|
/// definition's parent/scope to perform comparison.
|
2025-04-08 12:23:07 +10:00
|
|
|
pub fn hygienic_eq(self, use_ident: Ident, def_ident: Ident, def_parent_def_id: DefId) -> bool {
|
2025-04-10 09:39:21 +10:00
|
|
|
// We could use `Ident::eq` here, but we deliberately don't. The identifier
|
2019-05-28 06:19:23 +10:00
|
|
|
// comparison fails frequently, and we want to avoid the expensive
|
2020-03-14 01:36:46 +03:00
|
|
|
// `normalize_to_macros_2_0()` calls required for the span comparison whenever possible.
|
2025-04-08 12:23:07 +10:00
|
|
|
use_ident.name == def_ident.name
|
|
|
|
|
&& use_ident
|
2019-06-03 09:43:20 +10:00
|
|
|
.span
|
|
|
|
|
.ctxt()
|
2025-04-08 12:23:07 +10:00
|
|
|
.hygienic_eq(def_ident.span.ctxt(), self.expn_that_defined(def_parent_def_id))
|
2019-05-28 07:43:05 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident {
|
2021-06-04 21:37:05 +02:00
|
|
|
ident.span.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope));
|
2019-05-28 07:43:05 +10:00
|
|
|
ident
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-22 10:36:30 +01:00
|
|
|
// FIXME(vincenzopalazzo): move the HirId to a LocalDefId
|
2019-05-28 07:43:05 +10:00
|
|
|
pub fn adjust_ident_and_get_scope(
|
|
|
|
|
self,
|
|
|
|
|
mut ident: Ident,
|
|
|
|
|
scope: DefId,
|
|
|
|
|
block: hir::HirId,
|
|
|
|
|
) -> (Ident, DefId) {
|
2021-06-28 19:29:55 +02:00
|
|
|
let scope = ident
|
|
|
|
|
.span
|
|
|
|
|
.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope))
|
|
|
|
|
.and_then(|actual_expansion| actual_expansion.expn_data().parent_module)
|
|
|
|
|
.unwrap_or_else(|| self.parent_module(block).to_def_id());
|
2017-03-24 23:03:15 +00:00
|
|
|
(ident, scope)
|
|
|
|
|
}
|
2020-02-19 17:59:24 +01:00
|
|
|
|
2024-10-12 20:37:35 +02:00
|
|
|
/// Checks whether this is a `const fn`. Returns `false` for non-functions.
|
|
|
|
|
///
|
|
|
|
|
/// Even if this returns `true`, constness may still be unstable!
|
2022-03-13 11:12:50 +01:00
|
|
|
#[inline]
|
2024-10-12 20:37:35 +02:00
|
|
|
pub fn is_const_fn(self, def_id: DefId) -> bool {
|
2022-12-21 16:32:16 +00:00
|
|
|
matches!(
|
|
|
|
|
self.def_kind(def_id),
|
2024-10-23 16:53:59 +00:00
|
|
|
DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Closure
|
2022-12-21 16:32:16 +00:00
|
|
|
) && self.constness(def_id) == hir::Constness::Const
|
2022-03-13 11:12:50 +01:00
|
|
|
}
|
2022-05-11 16:02:20 +00:00
|
|
|
|
2024-10-23 16:53:59 +00:00
|
|
|
/// Whether this item is conditionally constant for the purposes of the
|
|
|
|
|
/// effects implementation.
|
|
|
|
|
///
|
|
|
|
|
/// This roughly corresponds to all const functions and other callable
|
|
|
|
|
/// items, along with const impls and traits, and associated types within
|
|
|
|
|
/// those impls and traits.
|
|
|
|
|
pub fn is_conditionally_const(self, def_id: impl Into<DefId>) -> bool {
|
|
|
|
|
let def_id: DefId = def_id.into();
|
|
|
|
|
match self.def_kind(def_id) {
|
|
|
|
|
DefKind::Impl { of_trait: true } => {
|
2025-07-22 17:05:45 -05:00
|
|
|
let header = self.impl_trait_header(def_id);
|
2024-12-10 10:12:36 +00:00
|
|
|
header.constness == hir::Constness::Const
|
|
|
|
|
&& self.is_const_trait(header.trait_ref.skip_binder().def_id)
|
2024-10-23 16:53:59 +00:00
|
|
|
}
|
|
|
|
|
DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => {
|
|
|
|
|
self.constness(def_id) == hir::Constness::Const
|
|
|
|
|
}
|
2025-07-21 11:35:45 +00:00
|
|
|
DefKind::TraitAlias | DefKind::Trait => self.is_const_trait(def_id),
|
2024-12-10 10:12:36 +00:00
|
|
|
DefKind::AssocTy => {
|
|
|
|
|
let parent_def_id = self.parent(def_id);
|
|
|
|
|
match self.def_kind(parent_def_id) {
|
|
|
|
|
DefKind::Impl { of_trait: false } => false,
|
|
|
|
|
DefKind::Impl { of_trait: true } | DefKind::Trait => {
|
|
|
|
|
self.is_conditionally_const(parent_def_id)
|
|
|
|
|
}
|
|
|
|
|
_ => bug!("unexpected parent item of associated type: {parent_def_id:?}"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
DefKind::AssocFn => {
|
2024-10-23 16:53:59 +00:00
|
|
|
let parent_def_id = self.parent(def_id);
|
|
|
|
|
match self.def_kind(parent_def_id) {
|
|
|
|
|
DefKind::Impl { of_trait: false } => {
|
|
|
|
|
self.constness(def_id) == hir::Constness::Const
|
|
|
|
|
}
|
|
|
|
|
DefKind::Impl { of_trait: true } | DefKind::Trait => {
|
|
|
|
|
self.is_conditionally_const(parent_def_id)
|
|
|
|
|
}
|
2024-12-10 10:12:36 +00:00
|
|
|
_ => bug!("unexpected parent item of associated fn: {parent_def_id:?}"),
|
2024-10-23 16:53:59 +00:00
|
|
|
}
|
|
|
|
|
}
|
2024-11-19 20:29:01 +00:00
|
|
|
DefKind::OpaqueTy => match self.opaque_ty_origin(def_id) {
|
|
|
|
|
hir::OpaqueTyOrigin::FnReturn { parent, .. } => self.is_conditionally_const(parent),
|
|
|
|
|
hir::OpaqueTyOrigin::AsyncFn { .. } => false,
|
|
|
|
|
// FIXME(const_trait_impl): ATPITs could be conditionally const?
|
|
|
|
|
hir::OpaqueTyOrigin::TyAlias { .. } => false,
|
|
|
|
|
},
|
|
|
|
|
DefKind::Closure => {
|
2024-10-23 16:53:59 +00:00
|
|
|
// Closures and RPITs will eventually have const conditions
|
2025-03-11 12:08:45 +00:00
|
|
|
// for `[const]` bounds.
|
2024-10-23 16:53:59 +00:00
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
DefKind::Ctor(_, CtorKind::Const)
|
|
|
|
|
| DefKind::Impl { of_trait: false }
|
|
|
|
|
| DefKind::Mod
|
|
|
|
|
| DefKind::Struct
|
|
|
|
|
| DefKind::Union
|
|
|
|
|
| DefKind::Enum
|
|
|
|
|
| DefKind::Variant
|
|
|
|
|
| DefKind::TyAlias
|
|
|
|
|
| DefKind::ForeignTy
|
|
|
|
|
| DefKind::TyParam
|
|
|
|
|
| DefKind::Const
|
|
|
|
|
| DefKind::ConstParam
|
|
|
|
|
| DefKind::Static { .. }
|
|
|
|
|
| DefKind::AssocConst
|
|
|
|
|
| DefKind::Macro(_)
|
|
|
|
|
| DefKind::ExternCrate
|
|
|
|
|
| DefKind::Use
|
|
|
|
|
| DefKind::ForeignMod
|
|
|
|
|
| DefKind::AnonConst
|
|
|
|
|
| DefKind::InlineConst
|
|
|
|
|
| DefKind::Field
|
|
|
|
|
| DefKind::LifetimeParam
|
|
|
|
|
| DefKind::GlobalAsm
|
|
|
|
|
| DefKind::SyntheticCoroutineBody => false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-01 08:36:28 +00:00
|
|
|
#[inline]
|
|
|
|
|
pub fn is_const_trait(self, def_id: DefId) -> bool {
|
|
|
|
|
self.trait_def(def_id).constness == hir::Constness::Const
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-11 16:02:20 +00:00
|
|
|
#[inline]
|
|
|
|
|
pub fn is_const_default_method(self, def_id: DefId) -> bool {
|
2025-07-24 19:05:31 -05:00
|
|
|
matches!(self.trait_of_assoc(def_id), Some(trait_id) if self.is_const_trait(trait_id))
|
2022-05-11 16:02:20 +00:00
|
|
|
}
|
2022-09-02 21:02:59 +00:00
|
|
|
|
2023-02-28 02:03:26 +00:00
|
|
|
pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
|
|
|
|
|
if self.def_kind(def_id) != DefKind::AssocFn {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let Some(item) = self.opt_associated_item(def_id) else {
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-13 15:24:19 -05:00
|
|
|
let AssocContainer::TraitImpl(Ok(trait_item_def_id)) = item.container else {
|
2023-02-28 02:03:26 +00:00
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-13 15:24:19 -05:00
|
|
|
!self.associated_types_for_impl_traits_in_associated_fn(trait_item_def_id).is_empty()
|
2023-02-28 02:03:26 +00:00
|
|
|
}
|
2015-01-02 04:09:35 -05:00
|
|
|
}
|
2014-04-21 19:21:53 -04:00
|
|
|
|
2023-05-15 06:24:45 +02:00
|
|
|
pub fn provide(providers: &mut Providers) {
|
2021-07-09 22:40:51 +08:00
|
|
|
closure::provide(providers);
|
2017-08-29 11:10:22 -07:00
|
|
|
context::provide(providers);
|
2017-10-17 11:24:46 -04:00
|
|
|
erase_regions::provide(providers);
|
2022-10-04 09:22:39 -05:00
|
|
|
inhabitedness::provide(providers);
|
2020-04-11 00:50:02 -04:00
|
|
|
util::provide(providers);
|
2020-09-02 10:40:56 +03:00
|
|
|
print::provide(providers);
|
2020-03-12 18:07:58 -05:00
|
|
|
super::util::bug::provide(providers);
|
2023-05-15 06:24:45 +02:00
|
|
|
*providers = Providers {
|
2020-02-08 04:14:29 +01:00
|
|
|
trait_impls_of: trait_def::trait_impls_of_provider,
|
2022-03-15 16:30:30 +01:00
|
|
|
incoherent_impls: trait_def::incoherent_impls_provider,
|
2024-02-08 21:21:30 +00:00
|
|
|
trait_impls_in_crate: trait_def::trait_impls_in_crate_provider,
|
|
|
|
|
traits: trait_def::traits_provider,
|
2021-10-07 11:29:01 +02:00
|
|
|
vtable_allocation: vtable::vtable_allocation_provider,
|
2020-02-08 04:14:29 +01:00
|
|
|
..*providers
|
|
|
|
|
};
|
2017-04-15 15:40:38 +03:00
|
|
|
}
|
|
|
|
|
|
2017-03-20 18:35:16 -04:00
|
|
|
/// A map for the local crate mapping each type to a vector of its
|
|
|
|
|
/// inherent impls. This is not meant to be used outside of coherence;
|
|
|
|
|
/// rather, you should request the vector for a specific type via
|
2017-04-24 18:06:39 +03:00
|
|
|
/// `tcx.inherent_impls(def_id)` so as to minimize your dependencies
|
|
|
|
|
/// (constructing this map requires touching the entire crate).
|
2018-12-03 01:14:35 +01:00
|
|
|
#[derive(Clone, Debug, Default, HashStable)]
|
2017-03-20 18:35:16 -04:00
|
|
|
pub struct CrateInherentImpls {
|
2024-02-08 21:10:16 +00:00
|
|
|
pub inherent_impls: FxIndexMap<LocalDefId, Vec<DefId>>,
|
|
|
|
|
pub incoherent_impls: FxIndexMap<SimplifiedType, Vec<LocalDefId>>,
|
2017-03-20 18:35:16 -04:00
|
|
|
}
|
2017-04-23 17:43:23 +03:00
|
|
|
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]
|
2020-07-10 15:45:05 +10:00
|
|
|
pub struct SymbolName<'tcx> {
|
|
|
|
|
/// `&str` gives a consistent ordering, which ensures reproducible builds.
|
|
|
|
|
pub name: &'tcx str,
|
2017-04-24 19:35:47 +03:00
|
|
|
}
|
|
|
|
|
|
2020-07-10 15:45:05 +10:00
|
|
|
impl<'tcx> SymbolName<'tcx> {
|
|
|
|
|
pub fn new(tcx: TyCtxt<'tcx>, name: &str) -> SymbolName<'tcx> {
|
2023-12-05 17:33:16 -08:00
|
|
|
SymbolName { name: tcx.arena.alloc_str(name) }
|
2019-10-21 15:53:37 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-10 15:45:05 +10:00
|
|
|
impl<'tcx> fmt::Display for SymbolName<'tcx> {
|
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
|
fmt::Display::fmt(&self.name, fmt)
|
2019-10-21 15:53:37 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-10 15:45:05 +10:00
|
|
|
impl<'tcx> fmt::Debug for SymbolName<'tcx> {
|
2018-08-29 22:02:42 -07:00
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2017-04-24 19:35:47 +03:00
|
|
|
fmt::Display::fmt(&self.name, fmt)
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-04-26 19:00:55 -04:00
|
|
|
|
2022-06-02 19:42:29 +02:00
|
|
|
/// The constituent parts of a type level constant of kind ADT or array.
|
|
|
|
|
#[derive(Copy, Clone, Debug, HashStable)]
|
|
|
|
|
pub struct DestructuredConst<'tcx> {
|
|
|
|
|
pub variant: Option<VariantIdx>,
|
|
|
|
|
pub fields: &'tcx [ty::Const<'tcx>],
|
|
|
|
|
}
|
2025-08-23 20:17:32 +00:00
|
|
|
|
|
|
|
|
/// Generate TypeTree information for autodiff.
|
|
|
|
|
/// This function creates TypeTree metadata that describes the memory layout
|
|
|
|
|
/// of function parameters and return types for Enzyme autodiff.
|
|
|
|
|
pub fn fnc_typetrees<'tcx>(tcx: TyCtxt<'tcx>, fn_ty: Ty<'tcx>) -> FncTree {
|
|
|
|
|
// Check if TypeTrees are disabled via NoTT flag
|
|
|
|
|
if tcx.sess.opts.unstable_opts.autodiff.contains(&rustc_session::config::AutoDiff::NoTT) {
|
|
|
|
|
return FncTree { args: vec![], ret: TypeTree::new() };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if this is actually a function type
|
|
|
|
|
if !fn_ty.is_fn() {
|
|
|
|
|
return FncTree { args: vec![], ret: TypeTree::new() };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the function signature
|
|
|
|
|
let fn_sig = fn_ty.fn_sig(tcx);
|
|
|
|
|
let sig = tcx.instantiate_bound_regions_with_erased(fn_sig);
|
|
|
|
|
|
|
|
|
|
// Create TypeTrees for each input parameter
|
|
|
|
|
let mut args = vec![];
|
|
|
|
|
for ty in sig.inputs().iter() {
|
|
|
|
|
let type_tree = typetree_from_ty(tcx, *ty);
|
|
|
|
|
args.push(type_tree);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create TypeTree for return type
|
|
|
|
|
let ret = typetree_from_ty(tcx, sig.output());
|
|
|
|
|
|
|
|
|
|
FncTree { args, ret }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Generate TypeTree for a specific type.
|
|
|
|
|
/// This function analyzes a Rust type and creates appropriate TypeTree metadata.
|
2025-08-23 21:56:56 +00:00
|
|
|
pub fn typetree_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> TypeTree {
|
2025-09-11 07:30:35 +00:00
|
|
|
let mut visited = Vec::new();
|
|
|
|
|
typetree_from_ty_inner(tcx, ty, 0, &mut visited)
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-12 06:11:18 +00:00
|
|
|
/// Maximum recursion depth for TypeTree generation to prevent stack overflow
|
|
|
|
|
/// from pathological deeply nested types. Combined with cycle detection.
|
|
|
|
|
const MAX_TYPETREE_DEPTH: usize = 6;
|
|
|
|
|
|
2025-09-11 07:30:35 +00:00
|
|
|
/// Internal recursive function for TypeTree generation with cycle detection and depth limiting.
|
|
|
|
|
fn typetree_from_ty_inner<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
|
depth: usize,
|
|
|
|
|
visited: &mut Vec<Ty<'tcx>>,
|
|
|
|
|
) -> TypeTree {
|
2025-09-12 06:11:18 +00:00
|
|
|
if depth >= MAX_TYPETREE_DEPTH {
|
|
|
|
|
trace!("typetree depth limit {} reached for type: {}", MAX_TYPETREE_DEPTH, ty);
|
2025-09-11 07:30:35 +00:00
|
|
|
return TypeTree::new();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if visited.contains(&ty) {
|
|
|
|
|
return TypeTree::new();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
visited.push(ty);
|
|
|
|
|
let result = typetree_from_ty_impl(tcx, ty, depth, visited);
|
|
|
|
|
visited.pop();
|
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Implementation of TypeTree generation logic.
|
|
|
|
|
fn typetree_from_ty_impl<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
|
depth: usize,
|
|
|
|
|
visited: &mut Vec<Ty<'tcx>>,
|
|
|
|
|
) -> TypeTree {
|
|
|
|
|
typetree_from_ty_impl_inner(tcx, ty, depth, visited, false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Internal implementation with context about whether this is for a reference target.
|
|
|
|
|
fn typetree_from_ty_impl_inner<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
|
depth: usize,
|
|
|
|
|
visited: &mut Vec<Ty<'tcx>>,
|
|
|
|
|
is_reference_target: bool,
|
|
|
|
|
) -> TypeTree {
|
2025-08-23 20:17:32 +00:00
|
|
|
if ty.is_scalar() {
|
|
|
|
|
let (kind, size) = if ty.is_integral() || ty.is_char() || ty.is_bool() {
|
|
|
|
|
(Kind::Integer, ty.primitive_size(tcx).bytes_usize())
|
|
|
|
|
} else if ty.is_floating_point() {
|
|
|
|
|
match ty {
|
2025-08-23 21:56:56 +00:00
|
|
|
x if x == tcx.types.f16 => (Kind::Half, 2),
|
2025-08-23 20:17:32 +00:00
|
|
|
x if x == tcx.types.f32 => (Kind::Float, 4),
|
|
|
|
|
x if x == tcx.types.f64 => (Kind::Double, 8),
|
2025-08-23 21:56:56 +00:00
|
|
|
x if x == tcx.types.f128 => (Kind::F128, 16),
|
2025-09-04 11:17:34 +00:00
|
|
|
_ => (Kind::Integer, 0),
|
2025-08-23 20:17:32 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
2025-09-04 11:17:34 +00:00
|
|
|
(Kind::Integer, 0)
|
2025-08-23 20:17:32 +00:00
|
|
|
};
|
2025-08-23 21:56:56 +00:00
|
|
|
|
2025-09-11 07:30:35 +00:00
|
|
|
// Use offset 0 for scalars that are direct targets of references (like &f64)
|
|
|
|
|
// Use offset -1 for scalars used directly (like function return types)
|
|
|
|
|
let offset = if is_reference_target && !ty.is_array() { 0 } else { -1 };
|
|
|
|
|
return TypeTree(vec![Type { offset, size, kind, child: TypeTree::new() }]);
|
2025-08-23 20:17:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ty.is_ref() || ty.is_raw_ptr() || ty.is_box() {
|
|
|
|
|
let inner_ty = if let Some(inner) = ty.builtin_deref(true) {
|
|
|
|
|
inner
|
|
|
|
|
} else {
|
|
|
|
|
return TypeTree::new();
|
|
|
|
|
};
|
|
|
|
|
|
2025-09-11 07:30:35 +00:00
|
|
|
let child = typetree_from_ty_impl_inner(tcx, inner_ty, depth + 1, visited, true);
|
2025-08-23 20:17:32 +00:00
|
|
|
return TypeTree(vec![Type {
|
|
|
|
|
offset: -1,
|
2025-08-23 23:10:48 +00:00
|
|
|
size: tcx.data_layout.pointer_size().bytes_usize(),
|
2025-08-23 20:17:32 +00:00
|
|
|
kind: Kind::Pointer,
|
|
|
|
|
child,
|
|
|
|
|
}]);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-01 05:05:49 +00:00
|
|
|
if ty.is_array() {
|
|
|
|
|
if let ty::Array(element_ty, len_const) = ty.kind() {
|
|
|
|
|
let len = len_const.try_to_target_usize(tcx).unwrap_or(0);
|
|
|
|
|
if len == 0 {
|
|
|
|
|
return TypeTree::new();
|
|
|
|
|
}
|
2025-09-11 07:30:35 +00:00
|
|
|
let element_tree =
|
|
|
|
|
typetree_from_ty_impl_inner(tcx, *element_ty, depth + 1, visited, false);
|
2025-09-01 05:05:49 +00:00
|
|
|
let mut types = Vec::new();
|
2025-09-04 11:17:34 +00:00
|
|
|
for elem_type in &element_tree.0 {
|
|
|
|
|
types.push(Type {
|
|
|
|
|
offset: -1,
|
|
|
|
|
size: elem_type.size,
|
|
|
|
|
kind: elem_type.kind,
|
|
|
|
|
child: elem_type.child.clone(),
|
|
|
|
|
});
|
2025-09-01 05:05:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TypeTree(types);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-01 06:17:34 +00:00
|
|
|
if ty.is_slice() {
|
|
|
|
|
if let ty::Slice(element_ty) = ty.kind() {
|
2025-09-11 07:30:35 +00:00
|
|
|
let element_tree =
|
|
|
|
|
typetree_from_ty_impl_inner(tcx, *element_ty, depth + 1, visited, false);
|
2025-09-01 06:17:34 +00:00
|
|
|
return element_tree;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-01 16:14:31 +00:00
|
|
|
if let ty::Tuple(tuple_types) = ty.kind() {
|
|
|
|
|
if tuple_types.is_empty() {
|
|
|
|
|
return TypeTree::new();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut types = Vec::new();
|
|
|
|
|
let mut current_offset = 0;
|
|
|
|
|
|
|
|
|
|
for tuple_ty in tuple_types.iter() {
|
2025-09-11 07:30:35 +00:00
|
|
|
let element_tree =
|
|
|
|
|
typetree_from_ty_impl_inner(tcx, tuple_ty, depth + 1, visited, false);
|
2025-09-01 16:14:31 +00:00
|
|
|
|
|
|
|
|
let element_layout = tcx
|
|
|
|
|
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(tuple_ty))
|
|
|
|
|
.ok()
|
|
|
|
|
.map(|layout| layout.size.bytes_usize())
|
|
|
|
|
.unwrap_or(0);
|
|
|
|
|
|
|
|
|
|
for elem_type in &element_tree.0 {
|
|
|
|
|
types.push(Type {
|
|
|
|
|
offset: if elem_type.offset == -1 {
|
|
|
|
|
current_offset as isize
|
|
|
|
|
} else {
|
|
|
|
|
current_offset as isize + elem_type.offset
|
|
|
|
|
},
|
|
|
|
|
size: elem_type.size,
|
|
|
|
|
kind: elem_type.kind,
|
|
|
|
|
child: elem_type.child.clone(),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current_offset += element_layout;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TypeTree(types);
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-01 16:28:14 +00:00
|
|
|
if let ty::Adt(adt_def, args) = ty.kind() {
|
|
|
|
|
if adt_def.is_struct() {
|
|
|
|
|
let struct_layout =
|
|
|
|
|
tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty));
|
|
|
|
|
if let Ok(layout) = struct_layout {
|
|
|
|
|
let mut types = Vec::new();
|
|
|
|
|
|
|
|
|
|
for (field_idx, field_def) in adt_def.all_fields().enumerate() {
|
|
|
|
|
let field_ty = field_def.ty(tcx, args);
|
2025-09-11 07:30:35 +00:00
|
|
|
let field_tree =
|
|
|
|
|
typetree_from_ty_impl_inner(tcx, field_ty, depth + 1, visited, false);
|
2025-09-01 16:28:14 +00:00
|
|
|
|
|
|
|
|
let field_offset = layout.fields.offset(field_idx).bytes_usize();
|
|
|
|
|
|
|
|
|
|
for elem_type in &field_tree.0 {
|
|
|
|
|
types.push(Type {
|
|
|
|
|
offset: if elem_type.offset == -1 {
|
|
|
|
|
field_offset as isize
|
|
|
|
|
} else {
|
|
|
|
|
field_offset as isize + elem_type.offset
|
|
|
|
|
},
|
|
|
|
|
size: elem_type.size,
|
|
|
|
|
kind: elem_type.kind,
|
|
|
|
|
child: elem_type.child.clone(),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TypeTree(types);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-23 20:17:32 +00:00
|
|
|
TypeTree::new()
|
|
|
|
|
}
|