#![allow(rustc::usage_of_ty_tykind)]
pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
pub use self::AssocItemContainer::*;
pub use self::BorrowKind::*;
pub use self::IntVarValue::*;
pub use self::Variance::*;
use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
use crate::metadata::ModChild;
use crate::middle::privacy::EffectiveVisibilities;
use crate::mir::{Body, GeneratorLayout};
use crate::query::Providers;
use crate::traits::{self, Reveal};
use crate::ty;
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::util::Discr;
pub use adt::*;
pub use assoc::*;
pub use generic_args::*;
pub use generics::*;
use rustc_ast as ast;
use rustc_ast::node_id::NodeMap;
use rustc_attr as attr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
use rustc_hir::Node;
use rustc_index::IndexVec;
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
use rustc_serialize::{Decodable, Encodable};
use rustc_session::lint::LintBuffer;
pub use rustc_session::lint::RegisteredTools;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ExpnId, ExpnKind, Span};
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
pub use rustc_target::abi::{ReprFlags, ReprOptions};
pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, OptWithInfcx};
pub use vtable::*;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::mem;
use std::num::NonZeroUsize;
use std::ops::ControlFlow;
use std::{fmt, str};
pub use crate::ty::diagnostics::*;
pub use rustc_type_ir::AliasKind::*;
pub use rustc_type_ir::ConstKind::{
Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt,
Placeholder as PlaceholderCt, Unevaluated, Value,
};
pub use rustc_type_ir::DynKind::*;
pub use rustc_type_ir::InferTy::*;
pub use rustc_type_ir::RegionKind::*;
pub use rustc_type_ir::TyKind::*;
pub use rustc_type_ir::*;
pub use self::binding::BindingMode;
pub use self::binding::BindingMode::*;
pub use self::closure::{
is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, CAPTURE_STRUCT_LOCAL,
};
pub use self::consts::{
Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
};
pub use self::context::{
tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
};
pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
pub use self::list::List;
pub use self::parameterized::ParameterizedOverTcx;
pub use self::rvalue_scopes::RvalueScopes;
pub use self::sty::BoundRegionKind::*;
pub use self::sty::{
AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
BoundVariableKind, CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, ConstKind, ConstVid,
EarlyBoundRegion, EffectVid, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef,
FnSig, FreeRegion, GenSig, GeneratorArgs, GeneratorArgsParts, InlineConstArgs,
InlineConstArgsParts, ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection,
PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, Region, RegionKind, RegionVid,
TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo,
};
pub use self::trait_def::TraitDef;
pub use self::typeck_results::{
CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, TypeckResults,
UserType, UserTypeAnnotationIndex,
};
pub mod _match;
pub mod abstract_const;
pub mod adjustment;
pub mod binding;
pub mod cast;
pub mod codec;
pub mod error;
pub mod fast_reject;
pub mod flags;
pub mod fold;
pub mod inhabitedness;
pub mod layout;
pub mod normalize_erasing_regions;
pub mod print;
pub mod relate;
pub mod trait_def;
pub mod util;
pub mod visit;
pub mod vtable;
pub mod walk;
mod adt;
mod assoc;
mod closure;
mod consts;
mod context;
mod diagnostics;
mod erase_regions;
mod generic_args;
mod generics;
mod impls_ty;
mod instance;
mod list;
mod opaque_types;
mod parameterized;
mod rvalue_scopes;
mod structural_impls;
#[allow(hidden_glob_reexports)]
mod sty;
mod typeck_results;
pub struct ResolverOutputs {
pub global_ctxt: ResolverGlobalCtxt,
pub ast_lowering: ResolverAstLowering,
}
#[derive(Debug)]
pub struct ResolverGlobalCtxt {
pub visibilities: FxHashMap<LocalDefId, Visibility>,
pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
pub effective_visibilities: EffectiveVisibilities,
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
pub module_children: LocalDefIdMap<Vec<ModChild>>,
pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
pub main_def: Option<MainDefinition>,
pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
pub proc_macros: Vec<LocalDefId>,
pub confused_type_with_std_module: FxHashMap<Span, Span>,
pub doc_link_resolutions: FxHashMap<LocalDefId, DocLinkResMap>,
pub doc_link_traits_in_scope: FxHashMap<LocalDefId, Vec<DefId>>,
pub all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>,
}
#[derive(Debug)]
pub struct ResolverAstLowering {
pub legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,
pub partial_res_map: NodeMap<hir::def::PartialRes>,
pub import_res_map: NodeMap<hir::def::PerNS<Option<Res<ast::NodeId>>>>,
pub label_res_map: NodeMap<ast::NodeId>,
pub lifetimes_res_map: NodeMap<LifetimeRes>,
pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, LifetimeRes)>>,
pub next_node_id: ast::NodeId,
pub node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>,
pub def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
pub trait_map: NodeMap<Vec<hir::TraitCandidate>>,
pub builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>,
pub lifetime_elision_allowed: FxHashSet<ast::NodeId>,
pub lint_buffer: Steal<LintBuffer>,
}
#[derive(Clone, Copy, Debug)]
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(Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct ImplHeader<'tcx> {
pub impl_def_id: DefId,
pub self_ty: Ty<'tcx>,
pub trait_ref: Option<TraitRef<'tcx>>,
pub predicates: Vec<Predicate<'tcx>>,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
pub enum ImplSubject<'tcx> {
Trait(TraitRef<'tcx>),
Inherent(Ty<'tcx>),
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum ImplPolarity {
Positive,
Negative,
Reservation,
}
impl ImplPolarity {
pub fn flip(&self) -> Option<ImplPolarity> {
match self {
ImplPolarity::Positive => Some(ImplPolarity::Negative),
ImplPolarity::Negative => Some(ImplPolarity::Positive),
ImplPolarity::Reservation => None,
}
}
}
impl fmt::Display for ImplPolarity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Positive => f.write_str("positive"),
Self::Negative => f.write_str("negative"),
Self::Reservation => f.write_str("reservation"),
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum Asyncness {
Yes,
No,
}
impl Asyncness {
pub fn is_async(self) -> bool {
matches!(self, Asyncness::Yes)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Encodable, Decodable, HashStable)]
pub enum Visibility<Id = LocalDefId> {
Public,
Restricted(Id),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
pub enum BoundConstness {
NotConst,
ConstIfConst,
}
impl BoundConstness {
pub fn and(&mut self, constness: hir::Constness) -> hir::Constness {
match (constness, self) {
(hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const,
(_, this) => {
*this = BoundConstness::NotConst;
hir::Constness::NotConst
}
}
}
}
impl fmt::Display for BoundConstness {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotConst => f.write_str("normal"),
Self::ConstIfConst => f.write_str("`~const`"),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
#[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()
}
pub fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool {
if descendant.krate != ancestor.krate {
return false;
}
while descendant != ancestor {
match self.opt_parent(descendant) {
Some(parent) => descendant = parent,
None => return false,
}
}
true
}
}
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)
}
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.into(), id.into()),
}
}
pub fn is_at_least(self, vis: Visibility<impl Into<DefId>>, tcx: TyCtxt<'_>) -> bool {
match vis {
Visibility::Public => self.is_public(),
Visibility::Restricted(id) => self.is_accessible_from(id, tcx),
}
}
}
impl Visibility<DefId> {
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(def_id) => def_id.is_local(),
}
}
}
#[derive(HashStable, 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, PartialOrd, Ord, Hash, HashStable)]
#[rustc_diagnostic_item = "Ty"]
#[rustc_pass_by_value]
pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
impl ty::EarlyBoundRegion {
pub fn has_name(&self) -> bool {
self.name != kw::UnderscoreLifetime && self.name != kw::Empty
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value]
pub struct Predicate<'tcx>(
Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
);
impl<'tcx> Predicate<'tcx> {
#[inline]
pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> {
self.0.internee
}
#[inline(always)]
pub fn flags(self) -> TypeFlags {
self.0.flags
}
#[inline(always)]
pub fn outer_exclusive_binder(self) -> DebruijnIndex {
self.0.outer_exclusive_binder
}
pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option<Predicate<'tcx>> {
let kind = self
.kind()
.map_bound(|kind| match kind {
PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
trait_ref,
polarity,
})) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
trait_ref,
polarity: polarity.flip()?,
}))),
_ => None,
})
.transpose()?;
Some(tcx.mk_predicate(kind))
}
#[instrument(level = "debug", skip(tcx), ret)]
pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool {
match self.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
tcx.trait_is_coinductive(data.def_id())
}
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => true,
_ => false,
}
}
#[inline]
pub fn allow_normalization(self) -> bool {
match self.kind().skip_binder() {
PredicateKind::Clause(ClauseKind::WellFormed(_)) => false,
PredicateKind::Clause(ClauseKind::Trait(_))
| PredicateKind::Clause(ClauseKind::RegionOutlives(_))
| PredicateKind::Clause(ClauseKind::TypeOutlives(_))
| PredicateKind::Clause(ClauseKind::Projection(_))
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::ObjectSafe(_)
| PredicateKind::ClosureKind(_, _, _)
| PredicateKind::Subtype(_)
| PredicateKind::Coerce(_)
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(_))
| PredicateKind::ConstEquate(_, _)
| PredicateKind::Ambiguous => true,
}
}
}
impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
}
}
impl rustc_errors::IntoDiagnosticArg for Clause<'_> {
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value]
pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>);
impl<'tcx> Clause<'tcx> {
pub fn as_predicate(self) -> Predicate<'tcx> {
Predicate(self.0)
}
pub fn kind(self) -> Binder<'tcx, ClauseKind<'tcx>> {
self.0.internee.map_bound(|kind| match kind {
PredicateKind::Clause(clause) => clause,
_ => unreachable!(),
})
}
pub fn as_trait_clause(self) -> Option<Binder<'tcx, TraitPredicate<'tcx>>> {
let clause = self.kind();
if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() {
Some(clause.rebind(trait_clause))
} else {
None
}
}
pub fn as_projection_clause(self) -> Option<Binder<'tcx, ProjectionPredicate<'tcx>>> {
let clause = self.kind();
if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() {
Some(clause.rebind(projection_clause))
} else {
None
}
}
pub fn as_type_outlives_clause(self) -> Option<Binder<'tcx, TypeOutlivesPredicate<'tcx>>> {
let clause = self.kind();
if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() {
Some(clause.rebind(o))
} else {
None
}
}
pub fn as_region_outlives_clause(self) -> Option<Binder<'tcx, RegionOutlivesPredicate<'tcx>>> {
let clause = self.kind();
if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() {
Some(clause.rebind(o))
} else {
None
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub enum ClauseKind<'tcx> {
Trait(TraitPredicate<'tcx>),
RegionOutlives(RegionOutlivesPredicate<'tcx>),
TypeOutlives(TypeOutlivesPredicate<'tcx>),
Projection(ProjectionPredicate<'tcx>),
ConstArgHasType(Const<'tcx>, Ty<'tcx>),
WellFormed(GenericArg<'tcx>),
ConstEvaluatable(ty::Const<'tcx>),
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub enum PredicateKind<'tcx> {
Clause(ClauseKind<'tcx>),
ObjectSafe(DefId),
ClosureKind(DefId, GenericArgsRef<'tcx>, ClosureKind),
Subtype(SubtypePredicate<'tcx>),
Coerce(CoercePredicate<'tcx>),
ConstEquate(Const<'tcx>, Const<'tcx>),
Ambiguous,
AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection),
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, Debug)]
pub enum AliasRelationDirection {
Equate,
Subtype,
}
impl std::fmt::Display for AliasRelationDirection {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AliasRelationDirection::Equate => write!(f, "=="),
AliasRelationDirection::Subtype => write!(f, "<:"),
}
}
}
#[derive(HashStable, Debug)]
pub struct CratePredicatesMap<'tcx> {
pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
}
impl<'tcx> Clause<'tcx> {
pub fn subst_supertrait(
self,
tcx: TyCtxt<'tcx>,
trait_ref: &ty::PolyTraitRef<'tcx>,
) -> Clause<'tcx> {
let bound_pred = self.kind();
let pred_bound_vars = bound_pred.bound_vars();
let trait_bound_vars = trait_ref.bound_vars();
let shifted_pred =
tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args);
let bound_vars =
tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
tcx.reuse_or_mk_predicate(
self.as_predicate(),
ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars),
)
.expect_clause()
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct TraitPredicate<'tcx> {
pub trait_ref: TraitRef<'tcx>,
pub polarity: ImplPolarity,
}
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
impl<'tcx> TraitPredicate<'tcx> {
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
}
pub fn def_id(self) -> DefId {
self.trait_ref.def_id
}
pub fn self_ty(self) -> Ty<'tcx> {
self.trait_ref.self_ty()
}
}
impl<'tcx> PolyTraitPredicate<'tcx> {
pub fn def_id(self) -> DefId {
self.skip_binder().def_id()
}
pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> {
self.map_bound(|trait_ref| trait_ref.self_ty())
}
#[inline]
pub fn polarity(self) -> ImplPolarity {
self.skip_binder().polarity
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct OutlivesPredicate<A, B>(pub A, pub B);
pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>;
pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct SubtypePredicate<'tcx> {
pub a_is_expected: bool,
pub a: Ty<'tcx>,
pub b: Ty<'tcx>,
}
pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct CoercePredicate<'tcx> {
pub a: Ty<'tcx>,
pub b: Ty<'tcx>,
}
pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Term<'tcx> {
ptr: NonZeroUsize,
marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>,
}
impl Debug for Term<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let data = if let Some(ty) = self.ty() {
format!("Term::Ty({ty:?})")
} else if let Some(ct) = self.ct() {
format!("Term::Ct({ct:?})")
} else {
unreachable!()
};
f.write_str(&data)
}
}
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<'a, 'tcx> HashStable<StableHashingContext<'a>> for Term<'tcx> {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
self.unpack().hash_stable(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> {
Ok(self.unpack().try_fold_with(folder)?.pack())
}
}
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.unpack().visit_with(visitor)
}
}
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for Term<'tcx> {
fn encode(&self, e: &mut E) {
self.unpack().encode(e)
}
}
impl<'tcx, D: TyDecoder<I = TyCtxt<'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 unpack(self) -> TermKind<'tcx> {
let ptr = self.ptr.get();
unsafe {
match ptr & TAG_MASK {
TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
))),
CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
))),
_ => core::intrinsics::unreachable(),
}
}
}
pub fn ty(&self) -> Option<Ty<'tcx>> {
if let TermKind::Ty(ty) = self.unpack() { Some(ty) } else { None }
}
pub fn ct(&self) -> Option<Const<'tcx>> {
if let TermKind::Const(c) = self.unpack() { Some(c) } else { None }
}
pub fn into_arg(self) -> GenericArg<'tcx> {
match self.unpack() {
TermKind::Ty(ty) => ty.into(),
TermKind::Const(c) => c.into(),
}
}
pub fn to_alias_ty(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
match self.unpack() {
TermKind::Ty(ty) => match *ty.kind() {
ty::Alias(_kind, alias_ty) => Some(alias_ty),
_ => None,
},
TermKind::Const(ct) => match ct.kind() {
ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.args)),
_ => None,
},
}
}
pub fn is_infer(&self) -> bool {
match self.unpack() {
TermKind::Ty(ty) => ty.is_ty_var(),
TermKind::Const(ct) => ct.is_ct_infer(),
}
}
}
const TAG_MASK: usize = 0b11;
const TYPE_TAG: usize = 0b00;
const CONST_TAG: usize = 0b01;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub enum TermKind<'tcx> {
Ty(Ty<'tcx>),
Const(Const<'tcx>),
}
impl<'tcx> TermKind<'tcx> {
#[inline]
fn pack(self) -> Term<'tcx> {
let (tag, ptr) = match self {
TermKind::Ty(ty) => {
assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0);
(TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize)
}
TermKind::Const(ct) => {
assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
(CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
}
};
Term { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData }
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum ParamTerm {
Ty(ParamTy),
Const(ParamConst),
}
impl ParamTerm {
pub fn index(self) -> usize {
match self {
ParamTerm::Ty(ty) => ty.index as usize,
ParamTerm::Const(ct) => ct.index as usize,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum TermVid<'tcx> {
Ty(ty::TyVid),
Const(ty::ConstVid<'tcx>),
}
impl From<ty::TyVid> for TermVid<'_> {
fn from(value: ty::TyVid) -> Self {
TermVid::Ty(value)
}
}
impl<'tcx> From<ty::ConstVid<'tcx>> for TermVid<'tcx> {
fn from(value: ty::ConstVid<'tcx>) -> Self {
TermVid::Const(value)
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct ProjectionPredicate<'tcx> {
pub projection_ty: AliasTy<'tcx>,
pub term: Term<'tcx>,
}
impl<'tcx> ProjectionPredicate<'tcx> {
pub fn self_ty(self) -> Ty<'tcx> {
self.projection_ty.self_ty()
}
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> {
Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self }
}
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
self.projection_ty.trait_def_id(tcx)
}
pub fn def_id(self) -> DefId {
self.projection_ty.def_id
}
}
pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>;
impl<'tcx> PolyProjectionPredicate<'tcx> {
#[inline]
pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
self.skip_binder().projection_ty.trait_def_id(tcx)
}
#[inline]
pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> {
self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx))
}
pub fn term(&self) -> Binder<'tcx, Term<'tcx>> {
self.map_bound(|predicate| predicate.term)
}
pub fn projection_def_id(&self) -> DefId {
self.skip_binder().projection_ty.def_id
}
}
pub trait ToPolyTraitRef<'tcx> {
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
}
impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> {
self.map_bound_ref(|trait_pred| trait_pred.trait_ref)
}
}
pub trait ToPredicate<'tcx, P = Predicate<'tcx>> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P;
}
impl<'tcx, T> ToPredicate<'tcx, T> for T {
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T {
self
}
}
impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
ty::Binder::dummy(self).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
tcx.mk_predicate(self)
}
}
impl<'tcx> ToPredicate<'tcx> for ClauseKind<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self)))
}
}
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
tcx.mk_predicate(self.map_bound(ty::PredicateKind::Clause))
}
}
impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
#[inline(always)]
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.as_predicate()
}
}
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ClauseKind<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(self))).expect_clause()
}
}
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, ClauseKind<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))).expect_clause()
}
}
impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
ty::Binder::dummy(self).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> {
#[inline(always)]
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> {
TraitPredicate { trait_ref: self, polarity: ImplPolarity::Positive }
}
}
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let p: Predicate<'tcx> = self.to_predicate(tcx);
p.expect_clause()
}
}
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
pred.to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
pred.to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
#[inline(always)]
fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
self.map_bound(|trait_ref| TraitPredicate {
trait_ref,
polarity: ty::ImplPolarity::Positive,
})
}
}
impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let p: Predicate<'tcx> = self.to_predicate(tcx);
p.expect_clause()
}
}
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let p: Predicate<'tcx> = self.to_predicate(tcx);
p.expect_clause()
}
}
impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(self))).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for ProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(self))).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let p: Predicate<'tcx> = self.to_predicate(tcx);
p.expect_clause()
}
}
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let p: Predicate<'tcx> = self.to_predicate(tcx);
p.expect_clause()
}
}
impl<'tcx> Predicate<'tcx> {
pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
let predicate = self.kind();
match predicate.skip_binder() {
PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(ClauseKind::Projection(..))
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(ClauseKind::RegionOutlives(..))
| PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
| PredicateKind::Clause(ClauseKind::TypeOutlives(..))
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
| PredicateKind::Ambiguous => None,
}
}
pub fn to_opt_poly_projection_pred(self) -> Option<PolyProjectionPredicate<'tcx>> {
let predicate = self.kind();
match predicate.skip_binder() {
PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(ClauseKind::Trait(..))
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(ClauseKind::RegionOutlives(..))
| PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
| PredicateKind::Clause(ClauseKind::TypeOutlives(..))
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
| PredicateKind::Ambiguous => None,
}
}
pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
let predicate = self.kind();
match predicate.skip_binder() {
PredicateKind::Clause(ClauseKind::TypeOutlives(data)) => Some(predicate.rebind(data)),
PredicateKind::Clause(ClauseKind::Trait(..))
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::Clause(ClauseKind::Projection(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(ClauseKind::RegionOutlives(..))
| PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
| PredicateKind::Ambiguous => None,
}
}
pub fn as_clause(self) -> Option<Clause<'tcx>> {
match self.kind().skip_binder() {
PredicateKind::Clause(..) => Some(self.expect_clause()),
_ => None,
}
}
pub fn expect_clause(self) -> Clause<'tcx> {
match self.kind().skip_binder() {
PredicateKind::Clause(..) => Clause(self.0),
_ => bug!("{self} is not a clause"),
}
}
}
#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct InstantiatedPredicates<'tcx> {
pub predicates: Vec<Clause<'tcx>>,
pub spans: Vec<Span>,
}
impl<'tcx> InstantiatedPredicates<'tcx> {
pub fn empty() -> InstantiatedPredicates<'tcx> {
InstantiatedPredicates { predicates: vec![], spans: vec![] }
}
pub fn is_empty(&self) -> bool {
self.predicates.is_empty()
}
pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter {
(&self).into_iter()
}
}
impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> {
type Item = (Clause<'tcx>, Span);
type IntoIter = std::iter::Zip<std::vec::IntoIter<Clause<'tcx>>, std::vec::IntoIter<Span>>;
fn into_iter(self) -> Self::IntoIter {
debug_assert_eq!(self.predicates.len(), self.spans.len());
std::iter::zip(self.predicates, self.spans)
}
}
impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> {
type Item = (Clause<'tcx>, Span);
type IntoIter = std::iter::Zip<
std::iter::Copied<std::slice::Iter<'a, Clause<'tcx>>>,
std::iter::Copied<std::slice::Iter<'a, Span>>,
>;
fn into_iter(self) -> Self::IntoIter {
debug_assert_eq!(self.predicates.len(), self.spans.len());
std::iter::zip(self.predicates.iter().copied(), self.spans.iter().copied())
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct OpaqueTypeKey<'tcx> {
pub def_id: LocalDefId,
pub args: GenericArgsRef<'tcx>,
}
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
pub struct OpaqueHiddenType<'tcx> {
pub span: Span,
pub ty: Ty<'tcx>,
}
impl<'tcx> OpaqueHiddenType<'tcx> {
pub fn report_mismatch(
&self,
other: &Self,
opaque_def_id: LocalDefId,
tcx: TyCtxt<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
if let Some(diag) = tcx
.sess
.diagnostic()
.steal_diagnostic(tcx.def_span(opaque_def_id), StashKey::OpaqueHiddenTypeMismatch)
{
diag.cancel();
}
let sub_diag = if self.span == other.span {
TypeMismatchReason::ConflictType { span: self.span }
} else {
TypeMismatchReason::PreviousUse { span: self.span }
};
tcx.sess.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>,
ignore_errors: bool,
) -> Self {
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);
self.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span, ignore_errors))
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[derive(HashStable, TyEncodable, TyDecodable)]
pub struct Placeholder<T> {
pub universe: UniverseIndex,
pub bound: T,
}
pub type PlaceholderRegion = Placeholder<BoundRegion>;
pub type PlaceholderType = Placeholder<BoundTy>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
pub struct BoundConst<'tcx> {
pub var: BoundVar,
pub ty: Ty<'tcx>,
}
pub type PlaceholderConst<'tcx> = Placeholder<BoundVar>;
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct ParamEnv<'tcx> {
packed: CopyTaggedPtr<&'tcx List<Clause<'tcx>>, ParamTag, true>,
}
#[derive(Copy, Clone)]
struct ParamTag {
reveal: traits::Reveal,
}
impl_tag! {
impl Tag for ParamTag;
ParamTag { reveal: traits::Reveal::UserFacing },
ParamTag { reveal: traits::Reveal::All },
}
impl<'tcx> fmt::Debug for ParamEnv<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ParamEnv")
.field("caller_bounds", &self.caller_bounds())
.field("reveal", &self.reveal())
.finish()
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
self.caller_bounds().hash_stable(hcx, hasher);
self.reveal().hash_stable(hcx, hasher);
}
}
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
fn try_fold_with<F: ty::fold::FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
Ok(ParamEnv::new(
self.caller_bounds().try_fold_with(folder)?,
self.reveal().try_fold_with(folder)?,
))
}
}
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.caller_bounds().visit_with(visitor)?;
self.reveal().visit_with(visitor)
}
}
impl<'tcx> ParamEnv<'tcx> {
#[inline]
pub fn empty() -> Self {
Self::new(List::empty(), Reveal::UserFacing)
}
#[inline]
pub fn caller_bounds(self) -> &'tcx List<Clause<'tcx>> {
self.packed.pointer()
}
#[inline]
pub fn reveal(self) -> traits::Reveal {
self.packed.tag().reveal
}
#[inline]
pub fn reveal_all() -> Self {
Self::new(List::empty(), Reveal::All)
}
#[inline]
pub fn new(caller_bounds: &'tcx List<Clause<'tcx>>, reveal: Reveal) -> Self {
ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal }) }
}
pub fn with_user_facing(mut self) -> Self {
self.packed.set_tag(ParamTag { reveal: Reveal::UserFacing, ..self.packed.tag() });
self
}
pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self {
if self.packed.tag().reveal == traits::Reveal::All {
return self;
}
ParamEnv::new(tcx.reveal_opaque_types_in_bounds(self.caller_bounds()), Reveal::All)
}
#[inline]
pub fn without_caller_bounds(self) -> Self {
Self::new(List::empty(), self.reveal())
}
pub fn and<T: TypeVisitable<TyCtxt<'tcx>>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
ParamEnvAnd { param_env: self, value }
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
#[derive(HashStable)]
pub struct ParamEnvAnd<'tcx, T> {
pub param_env: ParamEnv<'tcx>,
pub value: T,
}
impl<'tcx, T> ParamEnvAnd<'tcx, T> {
pub fn into_parts(self) -> (ParamEnv<'tcx>, T) {
(self.param_env, self.value)
}
}
#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)]
pub struct Destructor {
pub did: DefId,
pub constness: hir::Constness,
}
bitflags! {
#[derive(HashStable, TyEncodable, TyDecodable)]
pub struct VariantFlags: u8 {
const NO_VARIANT_FLAGS = 0;
const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0;
const IS_RECOVERED = 1 << 1;
}
}
#[derive(Debug, HashStable, 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>,
flags: VariantFlags,
}
impl VariantDef {
pub fn new(
name: Symbol,
variant_did: Option<DefId>,
ctor: Option<(CtorKind, DefId)>,
discr: VariantDiscr,
fields: IndexVec<FieldIdx, FieldDef>,
adt_kind: AdtKind,
parent_did: DefId,
recovered: bool,
is_field_list_non_exhaustive: bool,
) -> Self {
debug!(
"VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?},
fields = {:?}, adt_kind = {:?}, parent_did = {:?})",
name, variant_did, ctor, discr, fields, adt_kind, parent_did,
);
let mut flags = VariantFlags::NO_VARIANT_FLAGS;
if is_field_list_non_exhaustive {
flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
}
if recovered {
flags |= VariantFlags::IS_RECOVERED;
}
VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags }
}
#[inline]
pub fn is_field_list_non_exhaustive(&self) -> bool {
self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
}
#[inline]
pub fn is_recovered(&self) -> bool {
self.flags.intersects(VariantFlags::IS_RECOVERED)
}
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
}
#[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::from_u32(0)]
}
#[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")
}
}
impl PartialEq for VariantDef {
#[inline]
fn eq(&self, other: &Self) -> bool {
let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = 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: _ } = &self;
def_id.hash(s)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
pub enum VariantDiscr {
Explicit(DefId),
Relative(u32),
}
#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
pub struct FieldDef {
pub did: DefId,
pub name: Symbol,
pub vis: Visibility<DefId>,
}
impl PartialEq for FieldDef {
#[inline]
fn eq(&self, other: &Self) -> bool {
let Self { did: lhs_did, name: _, vis: _ } = &self;
let Self { did: rhs_did, name: _, vis: _ } = other;
let res = lhs_did == rhs_did;
if cfg!(debug_assertions) && res {
let deep = self.name == other.name && self.vis == other.vis;
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: _ } = &self;
did.hash(s)
}
}
impl<'tcx> FieldDef {
pub fn ty(&self, tcx: TyCtxt<'tcx>, arg: GenericArgsRef<'tcx>) -> Ty<'tcx> {
tcx.type_of(self.did).instantiate(tcx, arg)
}
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,
},
Issue33140,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable)]
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.kind == AssocKind::Fn && item.defaultness(self).has_value())
}
pub fn repr_options_of_def(self, did: DefId) -> 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).0.to_smaller_hash();
if let Some(user_seed) = self.sess.opts.unstable_opts.layout_seed {
field_shuffle_seed ^= user_seed;
}
for attr in self.get_attrs(did, sym::repr) {
for r in attr::parse_repr_attr(&self.sess, attr) {
flags.insert(match r {
attr::ReprRust => ReprFlags::empty(),
attr::ReprC => ReprFlags::IS_C,
attr::ReprPacked(pack) => {
let pack = Align::from_bytes(pack as u64).unwrap();
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::from_bytes(align as u64).unwrap()));
ReprFlags::empty()
}
});
}
}
if self.sess.opts.unstable_opts.randomize_layout {
flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
}
if !self.consider_optimizing(|| format!("Reorder fields of {:?}", self.def_path_str(did))) {
flags.insert(ReprFlags::IS_LINEAR);
}
ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
}
pub fn opt_item_name(self, def_id: DefId) -> Option<Symbol> {
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 {
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: DefId) -> Symbol {
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: DefId) -> Option<Ident> {
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 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) {
self.associated_item(def_id).opt_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 impl_trait_ref1 = self.impl_trait_ref(def_id1);
let impl_trait_ref2 = self.impl_trait_ref(def_id2);
if impl_trait_ref1.is_some_and(|tr| tr.instantiate_identity().references_error())
|| impl_trait_ref2.is_some_and(|tr| tr.instantiate_identity().references_error())
{
return Some(ImplOverlapKind::Permitted { marker: false });
}
match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) {
(ImplPolarity::Reservation, _) | (_, ImplPolarity::Reservation) => {
return Some(ImplOverlapKind::Permitted { marker: false });
}
(ImplPolarity::Positive, ImplPolarity::Negative)
| (ImplPolarity::Negative, ImplPolarity::Positive) => {
return None;
}
(ImplPolarity::Positive, ImplPolarity::Positive)
| (ImplPolarity::Negative, ImplPolarity::Negative) => {}
};
let is_marker_overlap = {
let is_marker_impl = |trait_ref: Option<EarlyBinder<TraitRef<'_>>>| -> bool {
trait_ref.is_some_and(|tr| self.trait_def(tr.skip_binder().def_id).is_marker)
};
is_marker_impl(impl_trait_ref1) && is_marker_impl(impl_trait_ref2)
};
if is_marker_overlap {
Some(ImplOverlapKind::Permitted { marker: true })
} else {
if let Some(self_ty1) = self.issue33140_self_ty(def_id1) {
if let Some(self_ty2) = self.issue33140_self_ty(def_id2) {
if self_ty1 == self_ty2 {
return Some(ImplOverlapKind::Issue33140);
} else {
debug!("found {self_ty1:?} != {self_ty2:?}");
}
}
}
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::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
match instance {
ty::InstanceDef::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
| DefKind::InlineConst => self.mir_for_ctfe(def),
_ => self.optimized_mir(def),
}
}
ty::InstanceDef::VTableShim(..)
| ty::InstanceDef::ReifyShim(..)
| ty::InstanceDef::Intrinsic(..)
| ty::InstanceDef::FnPtrShim(..)
| ty::InstanceDef::Virtual(..)
| ty::InstanceDef::ClosureOnceShim { .. }
| ty::InstanceDef::DropGlue(..)
| ty::InstanceDef::CloneShim(..)
| ty::InstanceDef::ThreadLocalShim(..)
| ty::InstanceDef::FnPtrAddrShim(..) => self.mir_shims(instance),
}
}
pub fn get_attrs_unchecked(self, did: DefId) -> &'tcx [ast::Attribute] {
if let Some(did) = did.as_local() {
self.hir().attrs(self.hir().local_def_id_to_hir_id(did))
} else {
self.item_attrs(did)
}
}
pub fn get_attrs(
self,
did: impl Into<DefId>,
attr: Symbol,
) -> impl Iterator<Item = &'tcx ast::Attribute> {
let did: DefId = did.into();
let filter_fn = move |a: &&ast::Attribute| a.has_name(attr);
if let Some(did) = did.as_local() {
self.hir().attrs(self.hir().local_def_id_to_hir_id(did)).iter().filter(filter_fn)
} else if cfg!(debug_assertions) && rustc_feature::is_builtin_only_local(attr) {
bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr);
} else {
self.item_attrs(did).iter().filter(filter_fn)
}
}
pub fn get_attrs_by_path<'attr>(
self,
did: DefId,
attr: &'attr [Symbol],
) -> impl Iterator<Item = &'tcx ast::Attribute> + 'attr
where
'tcx: 'attr,
{
let filter_fn = move |a: &&ast::Attribute| a.path_matches(&attr);
if let Some(did) = did.as_local() {
self.hir().attrs(self.hir().local_def_id_to_hir_id(did)).iter().filter(filter_fn)
} else {
self.item_attrs(did).iter().filter(filter_fn)
}
}
pub fn get_attr(self, did: impl Into<DefId>, attr: Symbol) -> Option<&'tcx ast::Attribute> {
if cfg!(debug_assertions) && !rustc_feature::is_valid_for_get_attr(attr) {
let did: DefId = did.into();
bug!("get_attr: unexpected called with DefId `{:?}`, attr `{:?}`", did, attr);
} else {
self.get_attrs(did, attr).next()
}
}
pub fn has_attr(self, did: impl Into<DefId>, attr: Symbol) -> bool {
let did: DefId = did.into();
if cfg!(debug_assertions) && !did.is_local() && rustc_feature::is_builtin_only_local(attr) {
bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr);
} else {
self.get_attrs(did, attr).next().is_some()
}
}
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
}
pub fn generator_layout(self, def_id: DefId) -> Option<&'tcx GeneratorLayout<'tcx>> {
self.optimized_mir(def_id).generator_layout()
}
pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> {
self.impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id)
}
pub fn trait_of_item(self, def_id: DefId) -> Option<DefId> {
if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
let parent = self.parent(def_id);
if let DefKind::Trait | DefKind::TraitAlias = self.def_kind(parent) {
return Some(parent);
}
}
None
}
pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
let parent = self.parent(def_id);
if let DefKind::Impl { .. } = self.def_kind(parent) {
return Some(parent);
}
}
None
}
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, _))
&& self.has_attr(outer.macro_def_id.unwrap(), sym::rustc_builtin_macro)
{
true
} else {
false
}
}
pub fn is_automatically_derived(self, def_id: DefId) -> bool {
self.has_attr(def_id, sym::automatically_derived)
}
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_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool {
use_name.name == def_name.name
&& use_name
.span
.ctxt()
.hygienic_eq(def_name.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,
block: hir::HirId,
) -> (Ident, DefId) {
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());
(ident, scope)
}
pub fn should_collapse_debuginfo(self, span: Span) -> bool {
!self.sess.opts.unstable_opts.debug_macros
&& if self.features().collapse_debuginfo {
span.in_macro_expansion_with_collapse_debuginfo()
} else {
span.from_expansion()
}
}
#[inline]
pub fn is_const_fn_raw(self, def_id: DefId) -> bool {
matches!(
self.def_kind(def_id),
DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure
) && self.constness(def_id) == hir::Constness::Const
}
#[inline]
pub fn is_const_default_method(self, def_id: DefId) -> bool {
matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait))
}
pub fn impl_trait_parent(self, mut def_id: LocalDefId) -> LocalDefId {
while let DefKind::OpaqueTy = self.def_kind(def_id) {
def_id = self.local_parent(def_id);
}
def_id
}
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;
};
if item.container != ty::AssocItemContainer::ImplContainer {
return false;
}
let Some(trait_item_def_id) = item.trait_item_def_id else {
return false;
};
return !self
.associated_types_for_impl_traits_in_associated_fn(trait_item_def_id)
.is_empty();
}
}
pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<LocalDefId> {
let def_id = def_id.as_local()?;
if let Node::Item(item) = tcx.hir().get_by_def_id(def_id) {
if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind {
return match opaque_ty.origin {
hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => {
Some(parent)
}
hir::OpaqueTyOrigin::TyAlias { .. } => None,
};
}
}
None
}
pub fn int_ty(ity: ast::IntTy) -> IntTy {
match ity {
ast::IntTy::Isize => IntTy::Isize,
ast::IntTy::I8 => IntTy::I8,
ast::IntTy::I16 => IntTy::I16,
ast::IntTy::I32 => IntTy::I32,
ast::IntTy::I64 => IntTy::I64,
ast::IntTy::I128 => IntTy::I128,
}
}
pub fn uint_ty(uty: ast::UintTy) -> UintTy {
match uty {
ast::UintTy::Usize => UintTy::Usize,
ast::UintTy::U8 => UintTy::U8,
ast::UintTy::U16 => UintTy::U16,
ast::UintTy::U32 => UintTy::U32,
ast::UintTy::U64 => UintTy::U64,
ast::UintTy::U128 => UintTy::U128,
}
}
pub fn float_ty(fty: ast::FloatTy) -> FloatTy {
match fty {
ast::FloatTy::F32 => FloatTy::F32,
ast::FloatTy::F64 => FloatTy::F64,
}
}
pub fn ast_int_ty(ity: IntTy) -> ast::IntTy {
match ity {
IntTy::Isize => ast::IntTy::Isize,
IntTy::I8 => ast::IntTy::I8,
IntTy::I16 => ast::IntTy::I16,
IntTy::I32 => ast::IntTy::I32,
IntTy::I64 => ast::IntTy::I64,
IntTy::I128 => ast::IntTy::I128,
}
}
pub fn ast_uint_ty(uty: UintTy) -> ast::UintTy {
match uty {
UintTy::Usize => ast::UintTy::Usize,
UintTy::U8 => ast::UintTy::U8,
UintTy::U16 => ast::UintTy::U16,
UintTy::U32 => ast::UintTy::U32,
UintTy::U64 => ast::UintTy::U64,
UintTy::U128 => ast::UintTy::U128,
}
}
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);
super::middle::provide(providers);
*providers = Providers {
trait_impls_of: trait_def::trait_impls_of_provider,
incoherent_impls: trait_def::incoherent_impls_provider,
const_param_default: consts::const_param_default,
vtable_allocation: vtable::vtable_allocation_provider,
..*providers
};
}
#[derive(Clone, Debug, Default, HashStable)]
pub struct CrateInherentImpls {
pub inherent_impls: LocalDefIdMap<Vec<DefId>>,
pub incoherent_impls: FxHashMap<SimplifiedType, Vec<LocalDefId>>,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]
pub struct SymbolName<'tcx> {
pub name: &'tcx str,
}
impl<'tcx> SymbolName<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, name: &str) -> SymbolName<'tcx> {
SymbolName {
name: unsafe { str::from_utf8_unchecked(tcx.arena.alloc_slice(name.as_bytes())) },
}
}
}
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(Debug, Default, Copy, Clone)]
pub struct InferVarInfo {
pub self_in_trait: bool,
pub output: bool,
}
#[derive(Copy, Clone, Debug, HashStable)]
pub struct DestructuredConst<'tcx> {
pub variant: Option<VariantIdx>,
pub fields: &'tcx [ty::Const<'tcx>],
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
static_assert_size!(PredicateKind<'_>, 32);
static_assert_size!(WithCachedTypeInfo<TyKind<'_>>, 56);
}