use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec;
use alloc::vec::Vec;
use core::cmp::Ordering;
use core::fmt::Debug;
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use core::num::NonZero;
use core::ops::ControlFlow;
use core::ptr::NonNull;
use core::{fmt, iter, str};
use crate::assert_matches;
pub use adt::*;
pub use assoc::*;
pub use generic_args::{GenericArgKind, TermKind, *};
pub use generics::*;
pub use intrinsic::IntrinsicDef;
use crate::rustc_abi::{
Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, ScalableElt, VariantIdx,
};
use crate::rustc_ast::node_id::NodeMap;
use crate::rustc_ast::{self as ast, NodeId};
pub use crate::rustc_ast_ir::{Movability, Mutability, try_visit};
use crate::rustc_attr_ir::lang_items::LangItem;
use crate::rustc_attr_ir::{self as attr, StrippedCfgItem, find_attr};
use crate::rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use crate::rustc_data_structures::intern::Interned;
use crate::rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHasher};
use crate::rustc_data_structures::steal::Steal;
use crate::rustc_data_structures::unord::{UnordMap, UnordSet};
use crate::rustc_errors::{Diag, ErrorGuaranteed, LintBuffer};
use crate::rustc_hir as hir;
use crate::rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
use crate::rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
use crate::rustc_hir::definitions::PerParentDisambiguatorState;
use crate::rustc_index::bit_set::BitMatrix;
use crate::rustc_index::{IndexVec, static_assert_size};
pub use crate::rustc_lint_defs::RegisteredTools;
use rustc_macros::{
BlobDecodable, Decodable, Encodable, StableHash, TyDecodable, TyEncodable, TypeFoldable,
TypeVisitable, extension,
};
use crate::rustc_serialize::{Decodable, Encodable};
use crate::rustc_session::config::OptLevel;
use crate::rustc_span::def_id::{LocalModId, ModId};
use crate::rustc_span::hygiene::MacroKind;
use crate::rustc_span::{DUMMY_SP, ExpnId, ExpnKind, Ident, Span, Symbol};
use crate::rustc_target::callconv::FnAbi;
pub use crate::rustc_type_ir::data_structures::{DelayedMap, DelayedSet};
pub use crate::rustc_type_ir::fast_reject::DeepRejectCtxt;
pub use crate::rustc_type_ir::relate::VarianceDiagInfo;
pub use crate::rustc_type_ir::search_graph::RequiredDepth;
pub use crate::rustc_type_ir::solve::{CandidatePreferenceMode, SizedTraitKind, VisibleForLeakCheck};
pub use crate::rustc_type_ir::*;
use tracing::{debug, instrument};
pub use vtable::*;
pub use self::closure::{
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,
};
pub use self::consts::{
AliasConst, AliasConstKind, AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult,
Expr, ExprKind, LitToConstInput, ScalarInt, SimdAlign, ValTree, ValTreeKindExt, Value,
const_lit_matches_ty,
};
pub use self::context::{
CtxtInterners, CurrentGcx, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls,
};
pub use self::fold::*;
pub use self::instance::{Instance, InstanceKind, ReifyReason, ShimKind};
pub(crate) use self::list::RawList;
pub use self::list::{List, ListWithCachedTypeInfo};
pub use self::opaque_types::OpaqueTypeKey;
pub use self::pattern::{Pattern, PatternKind};
pub use self::predicate::{
AliasTerm, AliasTermKind, ArgOutlivesClause, Clause, ClauseKind, CoercePredicate,
ExistentialPredicate, ExistentialPredicateStableCmpExt, ExistentialProjection,
ExistentialTraitRef, HostEffectClause, NormalizesTo, OutlivesClause, PolyCoercePredicate,
PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef,
PolyProjectionClause, PolyRegionOutlivesClause, PolySubtypePredicate, PolyTraitClause,
PolyTraitRef, PolyTypeOutlivesClause, Predicate, PredicateKind, ProjectionClause,
RegionConstraint, RegionEqPredicate, RegionOutlivesClause, SubtypePredicate, TraitClause,
TraitRef, TypeOutlivesClause,
};
pub use self::region::{
EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, RegionExt, RegionKind,
RegionVid,
};
pub use self::sty::{
Alias, AliasTy, AliasTyKind, Article, Binder, BoundConst, BoundRegion, BoundRegionKind,
BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, CoroutineArgsExt, EarlyBinder,
FnSig, FnSigKind, FreeAliasTy, InherentAliasTy, InlineConstArgs, InlineConstArgsParts,
OpaqueAliasTy, ParamConst, ParamTy, PlaceholderConst, PlaceholderRegion, PlaceholderType,
PolyFnSig, ProjectionAliasTy, TyKind, TypeAndMut, TypingMode, TypingModeEqWrapper,
Unnormalized, UpvarArgs,
};
pub use self::trait_def::TraitDef;
pub use self::typeck_results::{
CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, IsIdentity,
Rust2024IncompatiblePatInfo, SplattedDef, TypeckResults, UserType, UserTypeAnnotationIndex,
UserTypeKind,
};
use crate::rustc_middle::diagnostics::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
use crate::rustc_middle::metadata::{AmbigModChild, ModChild};
use crate::rustc_middle::middle::privacy::EffectiveVisibilities;
use crate::rustc_middle::mir::{Body, CoroutineLayout, CoroutineSavedLocal, MirPhase, SourceInfo};
use crate::rustc_middle::query::{IntoQueryKey, Providers};
use crate::rustc_middle::ty;
use crate::rustc_middle::ty::codec::{TyDecoder, TyEncoder};
pub use crate::rustc_middle::ty::diagnostics::*;
use crate::rustc_middle::ty::fast_reject::SimplifiedType;
use crate::rustc_middle::ty::layout::{FnAbiError, LayoutError};
use crate::rustc_middle::ty::print::{with_crate_prefix, with_no_trimmed_paths};
use crate::rustc_middle::ty::util::Discr;
use crate::rustc_middle::ty::walk::TypeWalker;
pub mod abstract_const;
pub mod adjustment;
pub mod cast;
pub mod codec;
pub mod error;
pub mod fast_reject;
pub mod inhabitedness;
pub mod layout;
pub mod normalize_erasing_regions;
pub mod offload_meta;
pub mod pattern;
pub mod print;
pub mod relate;
pub mod significant_drop_order;
pub mod sty;
pub mod trait_def;
pub mod typetree;
pub mod util;
pub mod vtable;
mod adt;
mod assoc;
mod closure;
mod consts;
mod context;
mod diagnostics;
mod elaborate_impl;
mod erase_regions;
mod fold;
mod generic_args;
mod generics;
mod impls_ty;
mod instance;
mod intrinsic;
mod list;
mod opaque_types;
mod predicate;
mod region;
mod structural_impls;
mod typeck_results;
mod visit;
#[derive(Debug, StableHash)]
pub struct ResolverGlobalCtxt {
pub visibilities_for_hashing: Vec<(LocalDefId, Visibility)>,
pub expn_that_defined: UnordMap<LocalDefId, ExpnId>,
pub effective_visibilities: EffectiveVisibilities,
pub macro_reachable_adts: FxIndexMap<LocalDefId, FxIndexSet<LocalDefId>>,
pub extern_crate_map: UnordMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
pub module_children: LocalDefIdMap<Vec<ModChild>>,
pub ambig_module_children: LocalDefIdMap<Vec<AmbigModChild>>,
pub glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
pub main_def: Option<MainDefinition>,
pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
pub proc_macros: Vec<LocalDefId>,
pub confused_type_with_std_module: FxIndexMap<Span, Span>,
pub doc_link_resolutions: FxIndexMap<LocalModId, DocLinkResMap>,
pub doc_link_traits_in_scope: FxIndexMap<LocalModId, Vec<DefId>>,
pub all_macro_rules: UnordSet<Symbol>,
pub stripped_cfg_items: Vec<StrippedCfgItem>,
pub delegation_infos: FxIndexMap<LocalDefId, DelegationInfo>,
}
#[derive(Debug)]
pub struct PerOwnerResolverData<'tcx> {
pub node_id_to_def_id: NodeMap<LocalDefId>,
pub lifetime_elision_allowed: bool,
pub label_res_map: NodeMap<ast::NodeId>,
pub lifetimes_res_map: NodeMap<LifetimeRes>,
pub trait_map: NodeMap<&'tcx [hir::TraitCandidate<'tcx>]>,
pub import_res: hir::def::PerNS<Option<Res<ast::NodeId>>>,
pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, hir::MissingLifetimeKind)>>,
pub id: ast::NodeId,
pub def_id: LocalDefId,
}
impl<'tcx> PerOwnerResolverData<'tcx> {
pub fn new(id: ast::NodeId, def_id: LocalDefId) -> PerOwnerResolverData<'tcx> {
PerOwnerResolverData {
node_id_to_def_id: Default::default(),
lifetime_elision_allowed: false,
label_res_map: Default::default(),
lifetimes_res_map: Default::default(),
trait_map: Default::default(),
import_res: Default::default(),
extra_lifetime_params_map: Default::default(),
id,
def_id,
}
}
pub fn get_label_res(&self, id: ast::NodeId) -> Option<ast::NodeId> {
self.label_res_map.get(&id).copied()
}
pub fn get_lifetime_res(&self, id: ast::NodeId) -> Option<LifetimeRes> {
self.lifetimes_res_map.get(&id).copied()
}
pub fn extra_lifetime_params(
&self,
id: NodeId,
) -> &[(Ident, NodeId, hir::MissingLifetimeKind)] {
self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..])
}
}
#[derive(Debug)]
pub struct ResolverAstLowering<'tcx> {
pub partial_res_map: NodeMap<hir::def::PartialRes>,
pub next_node_id: ast::NodeId,
pub owners: NodeMap<PerOwnerResolverData<'tcx>>,
pub lint_buffer: Steal<LintBuffer>,
pub disambiguators: LocalDefIdMap<Steal<PerParentDisambiguatorState>>,
}
#[derive(Debug, StableHash)]
pub struct DelegationInfo {
pub resolution_id: Result<DefId, ErrorGuaranteed>,
}
#[derive(Clone, Copy, Debug, StableHash)]
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 }
}
}
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, StableHash)]
pub struct ImplTraitHeader<'tcx> {
pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
pub polarity: ImplPolarity,
pub safety: hir::Safety,
pub constness: hir::Constness,
}
impl<'tcx> ImplTraitHeader<'tcx> {
pub fn is_fully_generic_for_reflection(self) -> bool {
#[derive(Default)]
struct ParamFinder {
seen: FxHashSet<u32>,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParamFinder {
type Result = ControlFlow<()>;
fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result {
match r.kind() {
RegionKind::ReEarlyParam(param) => {
if self.seen.insert(param.index) {
ControlFlow::Continue(())
} else {
ControlFlow::Break(())
}
}
RegionKind::ReBound(..) => ControlFlow::Continue(()),
RegionKind::ReStatic | RegionKind::ReError(_) => ControlFlow::Break(()),
RegionKind::ReVar(_)
| RegionKind::RePlaceholder(_)
| RegionKind::ReErased
| RegionKind::ReLateParam(_) => bug!("unexpected lifetime in impl: {r:?}"),
}
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
match t.kind() {
TyKind::Param(p) => {
if !self.seen.insert(p.index) {
return ControlFlow::Break(());
}
}
TyKind::Alias(..) => return ControlFlow::Break(()),
_ => (),
}
t.super_visit_with(self)
}
}
self.trait_ref
.instantiate_identity()
.skip_norm_wip()
.visit_with(&mut ParamFinder::default())
.is_continue()
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, StableHash, Debug)]
#[derive(TypeFoldable, TypeVisitable, Default)]
pub enum Asyncness {
Yes,
#[default]
No,
}
impl Asyncness {
pub fn is_async(self) -> bool {
matches!(self, Asyncness::Yes)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Encodable, BlobDecodable, StableHash)]
pub enum Visibility<Id = LocalModId> {
Public,
Restricted(Id),
}
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) {
"pub(self)".to_string()
} else {
format!(
"pub(in crate{})",
tcx.def_path(restricted_id.to_def_id()).to_string_no_crate_verbose()
)
}
}
ty::Visibility::Public => "pub".to_string(),
}
}
}
#[derive(Debug, StableHash, PartialEq, Clone, Copy, Encodable, Decodable)]
pub enum RestrictionKind {
Unrestricted,
Restricted(DefId, Span),
}
impl RestrictionKind {
pub fn is_allowed_in(self, module: DefId, tcx: TyCtxt<'_>) -> bool {
match self {
RestrictionKind::Unrestricted => true,
RestrictionKind::Restricted(restricted_to, _) => {
tcx.is_descendant_of(module, restricted_to)
}
}
}
pub fn expect_span(self) -> Span {
match self {
RestrictionKind::Unrestricted => {
bug!("called `expect_span` on an unrestricted item")
}
RestrictionKind::Restricted(_, span) => span,
}
}
pub fn restriction_path(self, tcx: TyCtxt<'_>) -> String {
match self {
RestrictionKind::Unrestricted => String::new(),
RestrictionKind::Restricted(restricted_to, _) => {
if restricted_to.krate == crate::rustc_hir::def_id::LOCAL_CRATE {
with_crate_prefix!(with_no_trimmed_paths!(tcx.def_path_str(restricted_to)))
} else {
tcx.def_path_str(restricted_to.krate.as_mod_id())
}
}
}
}
pub fn stricter_of(self, rhs: Self, tcx: TyCtxt<'_>) -> Self {
match (self, rhs) {
(RestrictionKind::Unrestricted, r) | (r, RestrictionKind::Unrestricted) => r,
(
RestrictionKind::Restricted(left_did, _),
RestrictionKind::Restricted(right_did, _),
) => {
if left_did.krate != right_did.krate {
bug!("stricter_of: left and right restriction do not reference the same crate");
}
if tcx.is_descendant_of(left_did, right_did) { self } else { rhs }
}
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, StableHash)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ClosureSizeProfileData<'tcx> {
pub before_feature_tys: Ty<'tcx>,
pub after_feature_tys: Ty<'tcx>,
}
impl TyCtxt<'_> {
#[inline]
pub fn opt_parent(self, id: DefId) -> Option<DefId> {
self.def_key(id).parent.map(|index| DefId { index, ..id })
}
#[inline]
#[track_caller]
pub fn parent(self, id: DefId) -> DefId {
match self.opt_parent(id) {
Some(id) => id,
None => bug!("{id:?} doesn't have a parent"),
}
}
#[inline]
#[track_caller]
pub fn opt_local_parent(self, id: LocalDefId) -> Option<LocalDefId> {
self.opt_parent(id.to_def_id()).map(DefId::expect_local)
}
#[inline]
#[track_caller]
pub fn local_parent(self, id: impl Into<LocalDefId>) -> LocalDefId {
self.parent(id.into().to_def_id()).expect_local()
}
fn def_id_partial_cmp(self, lhs: DefId, rhs: DefId) -> Option<Ordering> {
if lhs.krate != rhs.krate {
return None;
}
let search = |mut start: DefId, finish: DefId, ord| {
while start.index != finish.index {
match self.opt_parent(start) {
Some(parent) => start.index = parent.index,
None => return None,
}
}
Some(ord)
};
match lhs.index.cmp(&rhs.index) {
Ordering::Equal => Some(Ordering::Equal),
Ordering::Less => search(rhs, lhs, Ordering::Greater),
Ordering::Greater => search(lhs, rhs, Ordering::Less),
}
}
pub fn is_descendant_of(
self,
descendant: impl Into<DefId>,
ancestor: impl Into<DefId>,
) -> bool {
matches!(
self.def_id_partial_cmp(descendant.into(), ancestor.into()),
Some(Ordering::Less | Ordering::Equal)
)
}
}
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 Visibility<LocalModId> {
pub fn to_mod_id(self) -> Visibility<ModId> {
self.map_id(LocalModId::to_mod_id)
}
}
impl<Id: Into<DefId>> Visibility<Id> {
pub fn is_accessible_from(self, module: impl Into<DefId>, tcx: TyCtxt<'_>) -> bool {
match self {
Visibility::Public => true,
Visibility::Restricted(id) => tcx.is_descendant_of(module, id),
}
}
pub fn partial_cmp(
self,
vis: Visibility<impl Into<DefId>>,
tcx: TyCtxt<'_>,
) -> Option<Ordering> {
match (self, vis) {
(Visibility::Public, Visibility::Public) => Some(Ordering::Equal),
(Visibility::Public, Visibility::Restricted(_)) => Some(Ordering::Greater),
(Visibility::Restricted(_), Visibility::Public) => Some(Ordering::Less),
(Visibility::Restricted(lhs_id), Visibility::Restricted(rhs_id)) => {
let (lhs_id, rhs_id) = (lhs_id.into(), rhs_id.into());
tcx.def_id_partial_cmp(lhs_id, rhs_id)
}
}
}
}
impl<Id: Into<DefId> + Debug + Copy> Visibility<Id> {
#[track_caller]
pub fn greater_than(
self,
vis: Visibility<impl Into<DefId> + Debug + Copy>,
tcx: TyCtxt<'_>,
) -> bool {
match self.partial_cmp(vis, tcx) {
Some(ord) => ord.is_gt(),
None => {
tcx.dcx().delayed_bug(format!("unordered visibilities: {self:?} and {vis:?}"));
false
}
}
}
}
impl Visibility<ModId> {
pub fn expect_local(self) -> Visibility {
self.map_id(|id| id.expect_local())
}
pub fn is_visible_locally(self) -> bool {
match self {
Visibility::Public => true,
Visibility::Restricted(mod_id) => mod_id.is_local(),
}
}
}
#[derive(StableHash, Debug)]
pub struct CrateVariancesMap<'tcx> {
pub variances: DefIdMap<&'tcx [ty::Variance]>,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct CReaderCacheKey {
pub cnum: Option<CrateNum>,
pub pos: usize,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, StableHash)]
pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
impl<'tcx> crate::rustc_type_ir::inherent::IntoKind for Ty<'tcx> {
type Kind = TyKind<'tcx>;
fn kind(self) -> TyKind<'tcx> {
*self.kind()
}
}
impl<'tcx> crate::rustc_type_ir::Flags for Ty<'tcx> {
fn flags(&self) -> TypeFlags {
self.0.flags
}
fn outer_exclusive_binder(&self) -> DebruijnIndex {
self.0.outer_exclusive_binder
}
}
#[derive(StableHash, Debug)]
pub struct CrateClausesMap<'tcx> {
pub clauses: DefIdMap<&'tcx [(Clause<'tcx>, Span)]>,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Term<'tcx> {
ptr: NonNull<()>,
marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>,
}
impl<'tcx> crate::rustc_type_ir::inherent::Term<TyCtxt<'tcx>> for Term<'tcx> {}
impl<'tcx> crate::rustc_type_ir::inherent::IntoKind for Term<'tcx> {
type Kind = TermKind<'tcx>;
fn kind(self) -> Self::Kind {
self.kind()
}
}
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 {}
impl Debug for Term<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.kind() {
TermKind::Ty(ty) => write!(f, "Term::Ty({ty:?})"),
TermKind::Const(ct) => write!(f, "Term::Const({ct:?})"),
}
}
}
impl<'tcx> From<Ty<'tcx>> for Term<'tcx> {
fn from(ty: Ty<'tcx>) -> Self {
TermKind::Ty(ty).pack()
}
}
impl<'tcx> From<Const<'tcx>> for Term<'tcx> {
fn from(c: Const<'tcx>) -> Self {
TermKind::Const(c).pack()
}
}
impl<'tcx> StableHash for Term<'tcx> {
fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
self.kind().stable_hash(hcx, hasher);
}
}
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
match self.kind() {
ty::TermKind::Ty(ty) => ty.try_fold_with(folder).map(Into::into),
ty::TermKind::Const(ct) => ct.try_fold_with(folder).map(Into::into),
}
}
fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
match self.kind() {
ty::TermKind::Ty(ty) => ty.fold_with(folder).into(),
ty::TermKind::Const(ct) => ct.fold_with(folder).into(),
}
}
}
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
match self.kind() {
ty::TermKind::Ty(ty) => ty.visit_with(visitor),
ty::TermKind::Const(ct) => ct.visit_with(visitor),
}
}
}
impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Term<'tcx> {
fn encode(&self, e: &mut E) {
self.kind().encode(e)
}
}
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Term<'tcx> {
fn decode(d: &mut D) -> Self {
let res: TermKind<'tcx> = Decodable::decode(d);
res.pack()
}
}
impl<'tcx> Term<'tcx> {
#[inline]
pub fn kind(self) -> TermKind<'tcx> {
let ptr =
unsafe { self.ptr.map_addr(|addr| NonZero::new_unchecked(addr.get() & !TAG_MASK)) };
unsafe {
match self.ptr.addr().get() & TAG_MASK {
TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked(
ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(),
))),
CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
ptr.cast::<WithCachedTypeInfo<ty::ConstKind<'tcx>>>().as_ref(),
))),
_ => core::hint::unreachable_unchecked(),
}
}
}
pub fn as_type(&self) -> Option<Ty<'tcx>> {
if let TermKind::Ty(ty) = self.kind() { Some(ty) } else { None }
}
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>> {
if let TermKind::Const(c) = self.kind() { Some(c) } else { None }
}
pub fn expect_const(&self) -> Const<'tcx> {
self.as_const().expect("expected a const, but found a type")
}
pub fn into_arg(self) -> GenericArg<'tcx> {
match self.kind() {
TermKind::Ty(ty) => ty.into(),
TermKind::Const(c) => c.into(),
}
}
pub fn to_alias_term(self) -> Option<AliasTerm<'tcx>> {
match self.kind() {
TermKind::Ty(ty) => match *ty.kind() {
ty::Alias(_, alias_ty) => Some(alias_ty.into()),
_ => None,
},
TermKind::Const(ct) => match ct.kind() {
ConstKind::Alias(_, alias_const) => Some(alias_const.into()),
_ => None,
},
}
}
pub fn is_non_rigid_alias(self) -> bool {
match self.kind() {
ty::TermKind::Ty(ty) => match ty.kind() {
ty::Alias(ty::IsRigid::No, _) => true,
_ => false,
},
ty::TermKind::Const(ct) => match ct.kind() {
ty::ConstKind::Alias(ty::IsRigid::No, _) => true,
_ => false,
},
}
}
pub fn is_infer(&self) -> bool {
match self.kind() {
TermKind::Ty(ty) => ty.is_ty_var(),
TermKind::Const(ct) => ct.is_ct_infer(),
}
}
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(),
}
}
pub fn walk(self) -> TypeWalker<TyCtxt<'tcx>> {
TypeWalker::new(self.into())
}
}
const TAG_MASK: usize = 0b11;
const TYPE_TAG: usize = 0b00;
const CONST_TAG: usize = 0b01;
#[extension(pub trait TermKindPackExt<'tcx>)]
impl<'tcx> TermKind<'tcx> {
#[inline]
fn pack(self) -> Term<'tcx> {
let (tag, ptr) = match self {
TermKind::Ty(ty) => {
assert_eq!(align_of_val(&*ty.0.0) & TAG_MASK, 0);
(TYPE_TAG, NonNull::from(ty.0.0).cast())
}
TermKind::Const(ct) => {
assert_eq!(align_of_val(&*ct.0.0) & TAG_MASK, 0);
(CONST_TAG, NonNull::from(ct.0.0).cast())
}
};
Term { ptr: ptr.map_addr(|addr| addr | tag), marker: PhantomData }
}
}
#[derive(Clone, Debug)]
pub struct InstantiatedClauses<'tcx> {
pub clauses: Vec<Unnormalized<'tcx, Clause<'tcx>>>,
pub spans: Vec<Span>,
}
impl<'tcx> InstantiatedClauses<'tcx> {
pub fn empty() -> InstantiatedClauses<'tcx> {
InstantiatedClauses { clauses: vec![], spans: vec![] }
}
pub fn is_empty(&self) -> bool {
self.clauses.is_empty()
}
pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter {
self.into_iter()
}
}
impl<'tcx> IntoIterator for InstantiatedClauses<'tcx> {
type Item = (Unnormalized<'tcx, Clause<'tcx>>, Span);
type IntoIter = core::iter::Zip<
alloc::vec::IntoIter<Unnormalized<'tcx, Clause<'tcx>>>,
alloc::vec::IntoIter<Span>,
>;
fn into_iter(self) -> Self::IntoIter {
debug_assert_eq!(self.clauses.len(), self.spans.len());
core::iter::zip(self.clauses, self.spans)
}
}
impl<'a, 'tcx> IntoIterator for &'a InstantiatedClauses<'tcx> {
type Item = (Unnormalized<'tcx, Clause<'tcx>>, Span);
type IntoIter = core::iter::Zip<
core::iter::Copied<core::slice::Iter<'a, Unnormalized<'tcx, Clause<'tcx>>>>,
core::iter::Copied<core::slice::Iter<'a, Span>>,
>;
fn into_iter(self) -> Self::IntoIter {
debug_assert_eq!(self.clauses.len(), self.spans.len());
core::iter::zip(self.clauses.iter().copied(), self.spans.iter().copied())
}
}
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, StableHash, TyEncodable, TyDecodable)]
pub struct ProvisionalHiddenType<'tcx> {
pub span: Span,
pub ty: Ty<'tcx>,
}
#[derive(Debug, Clone, Copy)]
pub enum DefiningScopeKind {
HirTypeck,
MirBorrowck,
}
impl<'tcx> ProvisionalHiddenType<'tcx> {
pub fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> ProvisionalHiddenType<'tcx> {
ProvisionalHiddenType { span: DUMMY_SP, ty: Ty::new_error(tcx, guar) }
}
pub fn build_mismatch_error(
&self,
other: &Self,
tcx: TyCtxt<'tcx>,
) -> Result<Diag<'tcx>, ErrorGuaranteed> {
(self.ty, other.ty).error_reported()?;
let sub_diag = if self.span == other.span {
TypeMismatchReason::ConflictType { span: self.span }
} else {
TypeMismatchReason::PreviousUse { span: self.span }
};
Ok(tcx.dcx().create_err(OpaqueHiddenTypeMismatch {
self_ty: self.ty,
other_ty: other.ty,
other_span: other.span,
sub: sub_diag,
}))
}
#[instrument(level = "debug", skip(tcx), ret)]
pub fn remap_generic_params_to_declaration_params(
self,
opaque_type_key: OpaqueTypeKey<'tcx>,
tcx: TyCtxt<'tcx>,
defining_scope_kind: DefiningScopeKind,
) -> DefinitionSiteHiddenType<'tcx> {
let OpaqueTypeKey { def_id, args } = opaque_type_key;
let id_args = GenericArgs::identity_for_item(tcx, def_id);
debug!(?id_args);
let map = args.iter().zip(id_args).collect();
debug!("map = {:#?}", map);
let ty = match defining_scope_kind {
DefiningScopeKind::HirTypeck => {
fold_regions(tcx, self.ty, |_, _| tcx.lifetimes.re_erased)
}
DefiningScopeKind::MirBorrowck => self.ty,
};
let result_ty = ty.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span));
if cfg!(debug_assertions) && matches!(defining_scope_kind, DefiningScopeKind::HirTypeck) {
assert_eq!(result_ty, fold_regions(tcx, result_ty, |_, _| tcx.lifetimes.re_erased));
}
DefinitionSiteHiddenType { span: self.span, ty: ty::EarlyBinder::bind(tcx, result_ty) }
}
}
#[derive(Copy, Clone, Debug, StableHash, TyEncodable, TyDecodable)]
pub struct DefinitionSiteHiddenType<'tcx> {
pub span: Span,
pub ty: ty::EarlyBinder<'tcx, Ty<'tcx>>,
}
impl<'tcx> DefinitionSiteHiddenType<'tcx> {
pub fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> DefinitionSiteHiddenType<'tcx> {
DefinitionSiteHiddenType {
span: DUMMY_SP,
ty: ty::EarlyBinder::bind(tcx, Ty::new_error(tcx, guar)),
}
}
pub fn build_mismatch_error(
&self,
other: &Self,
tcx: TyCtxt<'tcx>,
) -> Result<Diag<'tcx>, ErrorGuaranteed> {
let self_ty = self.ty.instantiate_identity().skip_norm_wip();
let other_ty = other.ty.instantiate_identity().skip_norm_wip();
(self_ty, other_ty).error_reported()?;
let sub_diag = if self.span == other.span {
TypeMismatchReason::ConflictType { span: self.span }
} else {
TypeMismatchReason::PreviousUse { span: self.span }
};
Ok(tcx.dcx().create_err(OpaqueHiddenTypeMismatch {
self_ty,
other_ty,
other_span: other.span,
sub: sub_diag,
}))
}
}
pub type Clauses<'tcx> = &'tcx ListWithCachedTypeInfo<Clause<'tcx>>;
impl<'tcx> crate::rustc_type_ir::Flags for Clauses<'tcx> {
fn flags(&self) -> TypeFlags {
(**self).flags()
}
fn outer_exclusive_binder(&self) -> DebruijnIndex {
(**self).outer_exclusive_binder()
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(StableHash, TypeVisitable, TypeFoldable)]
pub struct ParamEnv<'tcx> {
caller_bounds: Clauses<'tcx>,
}
static_assert_size!(ParamEnv<'_>, core::mem::size_of::<usize>());
impl<'tcx> crate::rustc_type_ir::inherent::ParamEnv<TyCtxt<'tcx>> for ParamEnv<'tcx> {
fn caller_bounds(self) -> impl Iterator<Item = ty::Clause<'tcx>> {
self.caller_bounds()
}
}
impl<'tcx> ParamEnv<'tcx> {
#[inline]
pub fn empty() -> Self {
Self { caller_bounds: ListWithCachedTypeInfo::empty() }
}
#[inline]
pub fn caller_bounds(self) -> impl Iterator<Item = ty::Clause<'tcx>> + Clone {
self.caller_bounds.iter()
}
#[inline]
pub fn is_empty(self) -> bool {
self.caller_bounds.as_slice().is_empty()
}
#[inline]
pub fn new(
tcx: TyCtxt<'tcx>,
caller_bounds: impl IntoIterator<Item = ty::Clause<'tcx>>,
) -> Self {
ParamEnv { caller_bounds: tcx.mk_clauses_from_iter(caller_bounds.into_iter()) }
}
pub fn and<T: TypeVisitable<TyCtxt<'tcx>>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
ParamEnvAnd { param_env: self, value }
}
pub fn with_normalized(self, tcx: TyCtxt<'tcx>) -> ParamEnv<'tcx> {
if tcx.next_trait_solver_globally() {
self
} else {
ParamEnv::new(tcx, tcx.reveal_opaque_types_in_bounds(self.caller_bounds).iter())
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
#[derive(StableHash)]
pub struct ParamEnvAnd<'tcx, T> {
pub param_env: ParamEnv<'tcx>,
pub value: T,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, StableHash)]
#[derive(TypeVisitable, TypeFoldable)]
pub struct TypingEnv<'tcx> {
#[type_foldable(identity)]
#[type_visitable(ignore)]
typing_mode: TypingModeEqWrapper<'tcx>,
pub param_env: ParamEnv<'tcx>,
}
impl<'tcx> TypingEnv<'tcx> {
pub fn new(param_env: ParamEnv<'tcx>, typing_mode: TypingMode<'tcx>) -> Self {
Self { typing_mode: TypingModeEqWrapper(typing_mode), param_env }
}
pub fn typing_mode(&self) -> TypingMode<'tcx> {
self.typing_mode.0
}
pub fn fully_monomorphized() -> TypingEnv<'tcx> {
Self::new(ParamEnv::empty(), TypingMode::Codegen)
}
pub fn non_body_analysis(
tcx: TyCtxt<'tcx>,
def_id: impl IntoQueryKey<DefId>,
) -> TypingEnv<'tcx> {
let def_id = def_id.into_query_key();
Self::new(tcx.param_env(def_id), TypingMode::non_body_analysis())
}
pub fn post_typeck_until_borrowck(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> TypingEnv<'tcx> {
let param_env = tcx.param_env(def_id.to_def_id());
TypingEnv::new(param_env, ty::TypingMode::borrowck(tcx, def_id))
}
pub fn post_typeck_until_borrowck_for_mir_build(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
) -> TypingEnv<'tcx> {
if tcx.use_typing_mode_post_typeck_until_borrowck() {
TypingEnv::new(tcx.param_env(def_id.to_def_id()), ty::TypingMode::borrowck(tcx, def_id))
} else {
TypingEnv::non_body_analysis(tcx, def_id)
}
}
pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryKey<DefId>) -> TypingEnv<'tcx> {
TypingEnv::new(tcx.param_env_normalized_for_post_analysis(def_id), TypingMode::PostAnalysis)
}
pub fn codegen(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryKey<DefId>) -> TypingEnv<'tcx> {
TypingEnv::new(tcx.param_env_normalized_for_post_analysis(def_id), TypingMode::Codegen)
}
pub fn with_post_analysis_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> {
let TypingEnv { typing_mode, param_env } = self;
match typing_mode.0.assert_not_erased() {
TypingMode::Coherence
| TypingMode::Reflection
| TypingMode::Typeck { .. }
| TypingMode::PostTypeckUntilBorrowck { .. }
| TypingMode::PostBorrowck { .. } => {}
TypingMode::PostAnalysis | TypingMode::Codegen => return self,
}
let param_env = param_env.with_normalized(tcx);
TypingEnv::new(param_env, TypingMode::PostAnalysis)
}
pub fn with_codegen_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> {
let TypingEnv { typing_mode, param_env } = self;
match typing_mode.0.assert_not_erased() {
TypingMode::Coherence
| TypingMode::Reflection
| TypingMode::Typeck { .. }
| TypingMode::PostTypeckUntilBorrowck { .. }
| TypingMode::PostBorrowck { .. }
| TypingMode::PostAnalysis => {}
TypingMode::Codegen => return self,
}
let param_env = param_env.with_normalized(tcx);
TypingEnv::new(param_env, TypingMode::Codegen)
}
pub fn as_query_input<T>(self, value: T) -> PseudoCanonicalInput<'tcx, T>
where
T: TypeVisitable<TyCtxt<'tcx>>,
{
PseudoCanonicalInput { typing_env: self, value }
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(StableHash, TypeVisitable, TypeFoldable)]
pub struct PseudoCanonicalInput<'tcx, T> {
pub typing_env: TypingEnv<'tcx>,
pub value: T,
}
#[derive(Copy, Clone, Debug, StableHash, Encodable, Decodable)]
pub struct Destructor {
pub did: DefId,
}
#[derive(Copy, Clone, Debug, StableHash, Encodable, Decodable)]
pub struct AsyncDestructor {
pub impl_did: DefId,
}
#[derive(Clone, Copy, PartialEq, Eq, StableHash, TyEncodable, TyDecodable)]
pub struct VariantFlags(u8);
bitflags::bitflags! {
impl VariantFlags: u8 {
const NO_VARIANT_FLAGS = 0;
const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0;
}
}
crate::external_bitflags_debug! { VariantFlags }
#[derive(Debug, StableHash, TyEncodable, TyDecodable)]
pub struct VariantDef {
pub def_id: DefId,
pub ctor: Option<(CtorKind, DefId)>,
pub name: Symbol,
pub discr: VariantDiscr,
pub fields: IndexVec<FieldIdx, FieldDef>,
tainted: Option<ErrorGuaranteed>,
flags: VariantFlags,
}
impl VariantDef {
#[instrument(level = "debug")]
pub fn new(
name: Symbol,
variant_did: Option<DefId>,
ctor: Option<(CtorKind, DefId)>,
discr: VariantDiscr,
fields: IndexVec<FieldIdx, FieldDef>,
parent_did: DefId,
recover_tainted: Option<ErrorGuaranteed>,
is_field_list_non_exhaustive: bool,
) -> Self {
let mut flags = VariantFlags::NO_VARIANT_FLAGS;
if is_field_list_non_exhaustive {
flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
}
VariantDef {
def_id: variant_did.unwrap_or(parent_did),
ctor,
name,
discr,
fields,
flags,
tainted: recover_tainted,
}
}
#[inline]
pub fn is_field_list_non_exhaustive(&self) -> bool {
self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
}
#[inline]
pub fn field_list_has_applicable_non_exhaustive(&self) -> bool {
self.is_field_list_non_exhaustive() && !self.def_id.is_local()
}
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
}
#[inline]
pub fn has_errors(&self) -> Result<(), ErrorGuaranteed> {
self.tainted.map_or(Ok(()), Err)
}
#[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)
}
#[inline]
pub fn single_field(&self) -> &FieldDef {
assert!(self.fields.len() == 1);
&self.fields[FieldIdx::ZERO]
}
#[inline]
pub fn tail_opt(&self) -> Option<&FieldDef> {
self.fields.raw.last()
}
#[inline]
pub fn tail(&self) -> &FieldDef {
self.tail_opt().expect("expected unsized ADT to have a tail field")
}
pub fn has_unsafe_fields(&self) -> bool {
self.fields.iter().any(|x| x.safety.is_unsafe())
}
}
impl PartialEq for VariantDef {
#[inline]
fn eq(&self, other: &Self) -> bool {
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;
let res = lhs_def_id == rhs_def_id;
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
}
}
impl Eq for VariantDef {}
impl Hash for VariantDef {
#[inline]
fn hash<H: Hasher>(&self, s: &mut H) {
let Self { def_id, ctor: _, name: _, discr: _, fields: _, flags: _, tainted: _ } = &self;
def_id.hash(s)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, StableHash)]
pub enum VariantDiscr {
Explicit(DefId),
Relative(u32),
}
#[derive(Debug, StableHash, TyEncodable, TyDecodable)]
pub struct FieldDef {
pub did: DefId,
pub name: Symbol,
pub vis: Visibility<ModId>,
pub mut_restriction: RestrictionKind,
pub safety: hir::Safety,
pub value: Option<DefId>,
}
impl PartialEq for FieldDef {
#[inline]
fn eq(&self, other: &Self) -> bool {
let Self { did: lhs_did, name: _, vis: _, mut_restriction: _, safety: _, value: _ } = &self;
let Self { did: rhs_did, name: _, vis: _, mut_restriction: _, safety: _, value: _ } = other;
let res = lhs_did == rhs_did;
if cfg!(debug_assertions) && res {
let deep = self.name == other.name
&& self.vis == other.vis
&& self.mut_restriction == other.mut_restriction
&& self.safety == other.safety;
assert!(deep, "FieldDef for the same def-id has differing data");
}
res
}
}
impl Eq for FieldDef {}
impl Hash for FieldDef {
#[inline]
fn hash<H: Hasher>(&self, s: &mut H) {
let Self { did, name: _, vis: _, mut_restriction: _, safety: _, value: _ } = &self;
did.hash(s)
}
}
impl<'tcx> FieldDef {
pub fn ty(
&self,
tcx: TyCtxt<'tcx>,
args: GenericArgsRef<'tcx>,
) -> Unnormalized<'tcx, Ty<'tcx>> {
tcx.type_of(self.did).instantiate(tcx, args)
}
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
Ident::new(self.name, tcx.def_ident_span(self.did).unwrap())
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum ImplOverlapKind {
Permitted {
marker: bool,
},
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable, StableHash)]
pub enum ImplTraitInTraitData {
Trait { fn_def_id: DefId, opaque_def_id: DefId },
Impl { fn_def_id: DefId },
}
impl<'tcx> TyCtxt<'tcx> {
pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> {
self.typeck(self.hir_body_owner_def_id(body))
}
pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'tcx AssocItem> {
self.associated_items(id)
.in_definition_order()
.filter(move |item| item.is_fn() && item.defaultness(self).has_value())
}
pub fn repr_options_of_def(self, did: LocalDefId) -> ReprOptions {
let mut flags = ReprFlags::empty();
let mut size = None;
let mut max_align: Option<Align> = None;
let mut min_pack: Option<Align> = None;
let mut field_shuffle_seed = self.def_path_hash(did.to_def_id()).0.to_smaller_hash();
if let Some(user_seed) = self.sess.opts.unstable_opts.layout_seed {
field_shuffle_seed ^= user_seed;
}
let elt = find_attr!(self, did, RustcScalableVector { element_count } => element_count
)
.map(|elt| match elt {
Some(n) => ScalableElt::ElementCount(*n),
None => ScalableElt::Container,
});
if elt.is_some() {
flags.insert(ReprFlags::IS_SCALABLE);
}
if let Some(reprs) = find_attr!(self, did, Repr { reprs, .. } => reprs) {
for (r, _) in reprs {
flags.insert(match *r {
attr::ReprRust => ReprFlags::empty(),
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) => {
max_align = max_align.max(Some(align));
ReprFlags::empty()
}
});
}
}
if self.sess.opts.unstable_opts.randomize_layout {
flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
}
let is_box = self.is_lang_item(did.to_def_id(), LangItem::OwnedBox);
if is_box {
flags.insert(ReprFlags::IS_LINEAR);
}
if find_attr!(self, did, RustcPassIndirectlyInNonRusticAbis(..)) {
flags.insert(ReprFlags::PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS);
}
ReprOptions {
int: size,
align: max_align,
pack: min_pack,
flags,
field_shuffle_seed,
scalable: elt,
}
}
pub fn opt_item_name(self, def_id: impl IntoQueryKey<DefId>) -> Option<Symbol> {
let def_id = def_id.into_query_key();
if let Some(cnum) = def_id.as_crate_root() {
Some(self.crate_name(cnum))
} else {
let def_key = self.def_key(def_id);
match def_key.disambiguated_data.data {
crate::rustc_hir::definitions::DefPathData::Ctor => self
.opt_item_name(DefId { krate: def_id.krate, index: def_key.parent.unwrap() }),
_ => def_key.get_opt_name(),
}
}
}
pub fn item_name(self, id: impl IntoQueryKey<DefId>) -> Symbol {
let id = id.into_query_key();
self.opt_item_name(id).unwrap_or_else(|| {
bug!("item_name: no name for {:?}", self.def_path(id));
})
}
pub fn opt_item_ident(self, def_id: impl IntoQueryKey<DefId>) -> Option<Ident> {
let def_id = def_id.into_query_key();
let def = self.opt_item_name(def_id)?;
let span = self
.def_ident_span(def_id)
.unwrap_or_else(|| bug!("missing ident span for {def_id:?}"));
Some(Ident::new(def, span))
}
pub fn item_ident(self, def_id: impl IntoQueryKey<DefId>) -> Ident {
let def_id = def_id.into_query_key();
self.opt_item_ident(def_id).unwrap_or_else(|| {
bug!("item_ident: no name for {:?}", self.def_path(def_id));
})
}
pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> {
if let DefKind::AssocConst { .. } | DefKind::AssocFn | DefKind::AssocTy =
self.def_kind(def_id)
{
Some(self.associated_item(def_id))
} else {
None
}
}
pub fn opt_rpitit_info(self, def_id: DefId) -> Option<ImplTraitInTraitData> {
if let DefKind::AssocTy = self.def_kind(def_id)
&& let AssocKind::Type { data: AssocTypeData::Rpitit(rpitit_info) } =
self.associated_item(def_id).kind
{
Some(rpitit_info)
} else {
None
}
}
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)
})
}
#[instrument(level = "debug", skip(self), ret)]
pub fn impls_are_allowed_to_overlap(
self,
def_id1: DefId,
def_id2: DefId,
) -> Option<ImplOverlapKind> {
let impl1 = self.impl_trait_header(def_id1);
let impl2 = self.impl_trait_header(def_id2);
let trait_ref1 = impl1.trait_ref.skip_binder();
let trait_ref2 = impl2.trait_ref.skip_binder();
if trait_ref1.references_error() || trait_ref2.references_error() {
return Some(ImplOverlapKind::Permitted { marker: false });
}
match (impl1.polarity, impl2.polarity) {
(ImplPolarity::Positive, ImplPolarity::Negative)
| (ImplPolarity::Negative, ImplPolarity::Positive) => {
return None;
}
(ImplPolarity::Positive, ImplPolarity::Positive)
| (ImplPolarity::Negative, ImplPolarity::Negative) => {}
};
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);
if is_marker_overlap {
return Some(ImplOverlapKind::Permitted { marker: true });
}
None
}
pub fn expect_variant_res(self, res: Res) -> &'tcx VariantDef {
match res {
Res::Def(DefKind::Variant, did) => {
let enum_did = self.parent(did);
self.adt_def(enum_did).variant_with_id(did)
}
Res::Def(DefKind::Struct | DefKind::Union, did) => self.adt_def(did).non_enum_variant(),
Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_did) => {
let variant_did = self.parent(variant_ctor_did);
let enum_did = self.parent(variant_did);
self.adt_def(enum_did).variant_with_ctor_id(variant_ctor_did)
}
Res::Def(DefKind::Ctor(CtorOf::Struct, ..), ctor_did) => {
let struct_did = self.parent(ctor_did);
self.adt_def(struct_did).non_enum_variant()
}
_ => bug!("expect_variant_res used with unexpected res {:?}", res),
}
}
#[instrument(skip(self), level = "debug")]
pub fn instance_mir(self, instance: ty::InstanceKind<'tcx>) -> &'tcx Body<'tcx> {
let body = match instance {
ty::InstanceKind::Item(def) => {
debug!("calling def_kind on def: {:?}", def);
let def_kind = self.def_kind(def);
debug!("returned from def_kind: {:?}", def_kind);
match def_kind {
DefKind::Const { .. }
| DefKind::Static { .. }
| DefKind::AssocConst { .. }
| DefKind::Ctor(..)
| DefKind::AnonConst => self.mir_for_ctfe(def),
DefKind::Fn | DefKind::AssocFn
if matches!(
self.constness(def),
hir::Constness::Const { always: true }
) =>
{
self.mir_for_ctfe(def)
}
_ => self.optimized_mir(def),
}
}
ty::InstanceKind::Intrinsic(..) | ty::InstanceKind::LlvmIntrinsic(..) => {
bug!("intrinsics have no instance MIR")
}
ty::InstanceKind::Virtual(..) => bug!("virtual dispatches have no instance MIR"),
ty::InstanceKind::Shim(shim) => self.mir_shims(shim),
};
assert!(
matches!(body.phase, MirPhase::Runtime(_)),
"body: {body:?} instance: {instance:?} {:?}",
if let ty::InstanceKind::Item(d) = instance { Some(self.def_kind(d)) } else { None },
);
body
}
#[deprecated = "Though there are valid usecases for this method, especially when your attribute is not a parsed attribute, usually you want to call crate::find_attr! instead."]
pub fn get_attrs(
self,
did: impl Into<DefId>,
attr: Symbol,
) -> impl Iterator<Item = &'tcx crate::rustc_attr_ir::Attribute> {
#[expect(deprecated)]
self.get_all_attrs(did).iter().filter(move |a: &&crate::rustc_attr_ir::Attribute| a.has_name(attr))
}
#[deprecated = "Though there are valid usecases for this method, especially when your attribute is not a parsed attribute, usually you want to call crate::find_attr! instead."]
pub fn get_all_attrs(self, did: impl Into<DefId>) -> &'tcx [crate::rustc_attr_ir::Attribute] {
let did: DefId = did.into();
if let Some(did) = did.as_local() {
self.hir_attrs(self.local_def_id_to_hir_id(did))
} else {
self.attrs_for_def(did)
}
}
pub fn get_attrs_by_path(
self,
did: DefId,
attr: &[Symbol],
) -> impl Iterator<Item = &'tcx crate::rustc_attr_ir::Attribute> {
let filter_fn = move |a: &&crate::rustc_attr_ir::Attribute| a.path_matches(attr);
if let Some(did) = did.as_local() {
self.hir_attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
} else {
self.attrs_for_def(did).iter().filter(filter_fn)
}
}
pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
self.trait_def(trait_def_id).has_auto_impl
}
pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool {
self.trait_def(trait_def_id).is_coinductive
}
pub fn trait_is_alias(self, trait_def_id: DefId) -> bool {
self.def_kind(trait_def_id) == DefKind::TraitAlias
}
fn layout_error(self, err: LayoutError<'tcx>) -> &'tcx LayoutError<'tcx> {
self.arena.alloc(err)
}
fn ordinary_coroutine_layout(
self,
def_id: DefId,
args: GenericArgsRef<'tcx>,
) -> Result<&'tcx CoroutineLayout<'tcx>, &'tcx LayoutError<'tcx>> {
let coroutine_kind_ty = args.as_coroutine().kind_ty();
let mir = self.optimized_mir(def_id);
let ty = || Ty::new_coroutine(self, def_id, args);
if coroutine_kind_ty.is_unit() {
mir.coroutine_layout_raw().ok_or_else(|| self.layout_error(LayoutError::Unknown(ty())))
} else {
let ty::Coroutine(_, identity_args) =
*self.type_of(def_id).instantiate_identity().skip_norm_wip().kind()
else {
unreachable!();
};
let identity_kind_ty = identity_args.as_coroutine().kind_ty();
if identity_kind_ty == coroutine_kind_ty {
mir.coroutine_layout_raw()
.ok_or_else(|| self.layout_error(LayoutError::Unknown(ty())))
} 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)
);
self.optimized_mir(self.coroutine_by_move_body_def_id(def_id))
.coroutine_layout_raw()
.ok_or_else(|| self.layout_error(LayoutError::Unknown(ty())))
}
}
}
fn async_drop_coroutine_layout(
self,
def_id: DefId,
args: GenericArgsRef<'tcx>,
) -> Result<&'tcx CoroutineLayout<'tcx>, &'tcx LayoutError<'tcx>> {
let ty = || Ty::new_coroutine(self, def_id, args);
if args[0].has_placeholders() || args[0].has_non_region_param() {
return Err(self.layout_error(LayoutError::TooGeneric(ty())));
}
let instance = ShimKind::AsyncDropGlue(def_id, Ty::new_coroutine(self, def_id, args));
self.mir_shims(instance)
.coroutine_layout_raw()
.ok_or_else(|| self.layout_error(LayoutError::Unknown(ty())))
}
pub fn coroutine_layout(
self,
def_id: DefId,
args: GenericArgsRef<'tcx>,
) -> Result<&'tcx CoroutineLayout<'tcx>, &'tcx LayoutError<'tcx>> {
if self.is_async_drop_in_place_coroutine(def_id) {
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);
let variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, CoroutineSavedLocal>> =
iter::repeat(IndexVec::new()).take(CoroutineArgs::RESERVED_VARIANTS).collect();
let variant_source_info: IndexVec<VariantIdx, SourceInfo> =
iter::repeat(source_info).take(CoroutineArgs::RESERVED_VARIANTS).collect();
let proxy_layout = CoroutineLayout {
field_tys: [].into(),
variant_fields,
variant_source_info,
storage_conflicts: BitMatrix::new(0, 0),
};
return Ok(self.arena.alloc(proxy_layout));
} else {
self.async_drop_coroutine_layout(def_id, args)
}
} else {
self.ordinary_coroutine_layout(def_id, args)
}
}
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))
}
pub fn trait_item_of(self, def_id: impl IntoQueryKey<DefId>) -> Option<DefId> {
let def_id = def_id.into_query_key();
self.opt_associated_item(def_id)?.trait_item_def_id()
}
pub fn trait_of_assoc(self, def_id: DefId) -> Option<DefId> {
match self.assoc_parent(def_id) {
Some((id, DefKind::Trait)) => Some(id),
_ => None,
}
}
pub fn impl_is_of_trait(self, def_id: impl IntoQueryKey<DefId>) -> bool {
let def_id = def_id.into_query_key();
let DefKind::Impl { of_trait } = self.def_kind(def_id) else {
panic!("expected Impl for {def_id:?}");
};
of_trait
}
pub fn impl_of_assoc(self, def_id: DefId) -> Option<DefId> {
match self.assoc_parent(def_id) {
Some((id, DefKind::Impl { .. })) => Some(id),
_ => 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,
}
}
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,
}
}
pub fn impl_polarity(self, def_id: impl IntoQueryKey<DefId>) -> ty::ImplPolarity {
let def_id = def_id.into_query_key();
self.impl_trait_header(def_id).polarity
}
pub fn impl_trait_ref(
self,
def_id: impl IntoQueryKey<DefId>,
) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> {
let def_id = def_id.into_query_key();
self.impl_trait_header(def_id).trait_ref
}
pub fn impl_opt_trait_ref(
self,
def_id: impl IntoQueryKey<DefId>,
) -> Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>> {
let def_id = def_id.into_query_key();
self.impl_is_of_trait(def_id).then(|| self.impl_trait_ref(def_id))
}
pub fn impl_trait_id(self, def_id: impl IntoQueryKey<DefId>) -> DefId {
let def_id = def_id.into_query_key();
self.impl_trait_ref(def_id).skip_binder().def_id
}
pub fn impl_opt_trait_id(self, def_id: impl IntoQueryKey<DefId>) -> Option<DefId> {
let def_id = def_id.into_query_key();
self.impl_is_of_trait(def_id).then(|| self.impl_trait_id(def_id))
}
pub fn is_exportable(self, def_id: DefId) -> bool {
self.exportable_items(def_id.krate).contains(&def_id)
}
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, _))
&& find_attr!(self, outer.macro_def_id.unwrap(), RustcBuiltinMacro { .. })
{
true
} else {
false
}
}
pub fn is_automatically_derived(self, def_id: DefId) -> bool {
find_attr!(self, def_id, AutomaticallyDerived)
}
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))
} else {
Err(self.crate_name(impl_def_id.krate))
}
}
pub fn hygienic_eq(self, use_ident: Ident, def_ident: Ident, def_parent_def_id: DefId) -> bool {
use_ident.name == def_ident.name
&& use_ident
.span
.ctxt()
.hygienic_eq(def_ident.span.ctxt(), self.expn_that_defined(def_parent_def_id))
}
pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident {
ident.span.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope));
ident
}
pub fn adjust_ident_and_get_scope(
self,
mut ident: Ident,
scope: DefId,
item_id: LocalDefId,
) -> (Ident, ModId) {
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_from_def_id(item_id).to_mod_id());
(ident, scope)
}
#[inline]
pub fn is_const_fn(self, def_id: impl IntoQueryKey<DefId>) -> bool {
let def_id = def_id.into_query_key();
matches!(
self.def_kind(def_id),
DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Closure
) && matches!(self.constness(def_id), hir::Constness::Const { .. })
}
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 } => {
let header = self.impl_trait_header(def_id);
matches!(header.constness, hir::Constness::Const { always: false })
&& self.is_const_trait(header.trait_ref.skip_binder().def_id)
}
DefKind::Impl { of_trait: false } => {
matches!(self.constness(def_id), hir::Constness::Const { always: false })
}
DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => {
matches!(self.constness(def_id), hir::Constness::Const { always: false })
}
DefKind::TraitAlias | DefKind::Trait => self.is_const_trait(def_id),
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 => {
let parent_def_id = self.parent(def_id);
match self.def_kind(parent_def_id) {
DefKind::Impl { of_trait: false } => {
matches!(self.constness(def_id), hir::Constness::Const { always: false })
}
DefKind::Impl { of_trait: true } => {
let Some(trait_method_did) = self.trait_item_of(def_id) else {
return false;
};
matches!(
self.constness(trait_method_did),
hir::Constness::Const { always: false }
) && self.is_conditionally_const(parent_def_id)
}
DefKind::Trait => {
matches!(self.constness(def_id), hir::Constness::Const { always: false })
&& self.is_conditionally_const(parent_def_id)
}
_ => bug!("unexpected parent item of associated fn: {parent_def_id:?}"),
}
}
DefKind::OpaqueTy => match self.opaque_ty_origin(def_id) {
hir::OpaqueTyOrigin::FnReturn { parent, .. } => self.is_conditionally_const(parent),
hir::OpaqueTyOrigin::AsyncFn { .. } => false,
hir::OpaqueTyOrigin::TyAlias { .. } => false,
},
DefKind::Closure => {
matches!(self.constness(def_id), hir::Constness::Const { always: false })
}
DefKind::Ctor(_, CtorKind::Const)
| 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::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm
| DefKind::SyntheticCoroutineBody
| DefKind::TestBinderConstraints => false,
}
}
#[inline]
pub fn is_const_trait(self, def_id: DefId) -> bool {
matches!(self.trait_def(def_id).constness, hir::Constness::Const { .. })
}
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;
};
let AssocContainer::TraitImpl(Ok(trait_item_def_id)) = item.container else {
return false;
};
!self.associated_types_for_impl_traits_in_associated_fn(trait_item_def_id).is_empty()
}
#[inline]
pub fn fn_abi_of_instance(
self,
query: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
if self.sess.opts.optimize != OptLevel::No && self.sess.opts.incremental.is_none() {
self.fn_abi_of_instance_raw(query)
} else {
self.fn_abi_of_instance_no_deduced_attrs(query)
}
}
}
impl<'tcx> crate::rustc_attr_ir::HasAttrs<'tcx, TyCtxt<'tcx>> for DefId {
fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [crate::rustc_attr_ir::Attribute] {
if let Some(did) = self.as_local() {
tcx.hir_attrs(tcx.local_def_id_to_hir_id(did))
} else {
tcx.attrs_for_def(self)
}
}
}
impl<'tcx> crate::rustc_attr_ir::HasAttrs<'tcx, TyCtxt<'tcx>> for LocalDefId {
fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [crate::rustc_attr_ir::Attribute] {
tcx.hir_attrs(tcx.local_def_id_to_hir_id(self))
}
}
impl<'tcx> crate::rustc_attr_ir::HasAttrs<'tcx, TyCtxt<'tcx>> for hir::OwnerId {
fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [crate::rustc_attr_ir::Attribute] {
crate::rustc_attr_ir::HasAttrs::get_attrs(self.def_id, tcx)
}
}
impl<'tcx> crate::rustc_attr_ir::HasAttrs<'tcx, TyCtxt<'tcx>> for hir::HirId {
fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [crate::rustc_attr_ir::Attribute] {
tcx.hir_attrs(self)
}
}
pub fn provide(providers: &mut Providers) {
closure::provide(providers);
context::provide(providers);
erase_regions::provide(providers);
inhabitedness::provide(providers);
util::provide(providers);
print::provide(providers);
super::util::bug::provide(providers);
*providers = Providers {
trait_impls_of: trait_def::trait_impls_of_provider,
incoherent_impls: trait_def::incoherent_impls_provider,
trait_impls_in_crate: trait_def::trait_impls_in_crate_provider,
traits: trait_def::traits_provider,
vtable_allocation: vtable::vtable_allocation_provider,
..*providers
};
}
#[derive(Clone, Debug, Default, StableHash)]
pub struct CrateInherentImpls {
pub inherent_impls: FxIndexMap<LocalDefId, Vec<DefId>>,
pub incoherent_impls: FxIndexMap<SimplifiedType, Vec<LocalDefId>>,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, StableHash)]
pub struct SymbolName<'tcx> {
pub name: &'tcx str,
}
impl<'tcx> SymbolName<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, name: &str) -> SymbolName<'tcx> {
SymbolName { name: tcx.arena.alloc_str(name) }
}
}
impl<'tcx> fmt::Display for SymbolName<'tcx> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.name, fmt)
}
}
impl<'tcx> fmt::Debug for SymbolName<'tcx> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.name, fmt)
}
}
#[derive(Copy, Clone, Debug, StableHash)]
pub struct DestructuredAdtConst<'tcx> {
pub variant: VariantIdx,
pub fields: &'tcx [ty::Const<'tcx>],
}