1
Fork 0
rust/compiler/rustc_middle/src/ty/structural_impls.rs

1133 lines
41 KiB
Rust
Raw Normal View History

//! This module contains implements of the `Lift` and `TypeFoldable`
//! traits for various types in the Rust compiler. Most are written by
2019-11-15 18:19:52 +01:00
//! hand, though we've recently added some macros and proc-macros to help with the tedium.
use crate::mir::interpret;
2019-12-22 17:42:04 -05:00
use crate::mir::ProjectionKind;
2019-02-05 11:20:45 -06:00
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
2019-12-22 17:42:04 -05:00
use crate::ty::{self, InferConst, Lift, Ty, TyCtxt};
2020-10-24 02:21:18 +02:00
use rustc_data_structures::functor::IdFunctor;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::CRATE_DEF_INDEX;
2019-12-22 17:42:04 -05:00
use rustc_index::vec::{Idx, IndexVec};
2015-09-06 21:51:58 +03:00
use std::fmt;
use std::ops::ControlFlow;
2015-09-06 21:51:58 +03:00
use std::rc::Rc;
2019-06-18 08:15:27 -04:00
use std::sync::Arc;
2015-09-06 21:51:58 +03:00
impl fmt::Debug for ty::TraitDef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ty::tls::with(|tcx| {
with_no_trimmed_paths(|| {
FmtPrinter::new(tcx, f, Namespace::TypeNS).print_def_path(self.def_id, &[])
})?;
Ok(())
})
}
}
impl fmt::Debug for ty::AdtDef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ty::tls::with(|tcx| {
with_no_trimmed_paths(|| {
FmtPrinter::new(tcx, f, Namespace::TypeNS).print_def_path(self.did, &[])
})?;
Ok(())
})
}
}
impl fmt::Debug for ty::UpvarId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2019-12-22 17:42:04 -05:00
let name = ty::tls::with(|tcx| tcx.hir().name(self.var_path.hir_id));
write!(f, "UpvarId({:?};`{}`;{:?})", self.var_path.hir_id, name, self.closure_expr_id)
}
}
impl fmt::Debug for ty::UpvarBorrow<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2019-12-22 17:42:04 -05:00
write!(f, "UpvarBorrow({:?}, {:?})", self.kind, self.region)
}
}
impl fmt::Debug for ty::ExistentialTraitRef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
with_no_trimmed_paths(|| fmt::Display::fmt(self, f))
}
}
impl fmt::Debug for ty::adjustment::Adjustment<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?} -> {}", self.kind, self.target)
}
}
impl fmt::Debug for ty::BoundRegionKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
ty::BrNamed(did, name) => {
if did.index == CRATE_DEF_INDEX {
write!(f, "BrNamed({})", name)
} else {
write!(f, "BrNamed({:?}, {})", did, name)
}
}
ty::BrEnv => write!(f, "BrEnv"),
}
}
}
impl fmt::Debug for ty::RegionKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
2019-12-22 17:42:04 -05:00
ty::ReEarlyBound(ref data) => write!(f, "ReEarlyBound({}, {})", data.index, data.name),
ty::ReLateBound(binder_id, ref bound_region) => {
write!(f, "ReLateBound({:?}, {:?})", binder_id, bound_region)
}
ty::ReFree(ref fr) => fr.fmt(f),
ty::ReStatic => write!(f, "ReStatic"),
ty::ReVar(ref vid) => vid.fmt(f),
2019-12-22 17:42:04 -05:00
ty::RePlaceholder(placeholder) => write!(f, "RePlaceholder({:?})", placeholder),
ty::ReEmpty(ui) => write!(f, "ReEmpty({:?})", ui),
ty::ReErased => write!(f, "ReErased"),
}
}
}
impl fmt::Debug for ty::FreeRegion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region)
}
}
impl fmt::Debug for ty::FnSig<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2019-12-22 17:42:04 -05:00
write!(f, "({:?}; c_variadic: {})->{:?}", self.inputs(), self.c_variadic, self.output())
}
}
impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "_#{}c", self.index)
}
}
impl fmt::Debug for ty::RegionVid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "'_#{}r", self.index())
}
}
impl fmt::Debug for ty::TraitRef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
with_no_trimmed_paths(|| fmt::Display::fmt(self, f))
}
}
impl fmt::Debug for Ty<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
with_no_trimmed_paths(|| fmt::Display::fmt(self, f))
}
}
impl fmt::Debug for ty::ParamTy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}/#{}", self.name, self.index)
}
}
impl fmt::Debug for ty::ParamConst {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}/#{}", self.name, self.index)
}
}
impl fmt::Debug for ty::TraitPredicate<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2021-08-27 05:02:23 +00:00
if let ty::BoundConstness::ConstIfConst = self.constness {
write!(f, "~const ")?;
2021-07-22 21:56:07 +08:00
}
write!(f, "TraitPredicate({:?})", self.trait_ref)
}
}
impl fmt::Debug for ty::ProjectionPredicate<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.ty)
}
}
2020-05-11 22:06:41 +02:00
impl fmt::Debug for ty::Predicate<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2021-01-07 11:20:28 -05:00
write!(f, "{:?}", self.kind())
2020-05-11 22:06:41 +02:00
}
}
2021-01-07 11:20:28 -05:00
impl fmt::Debug for ty::PredicateKind<'tcx> {
2020-07-09 00:35:55 +02:00
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
2021-07-22 21:56:07 +08:00
ty::PredicateKind::Trait(ref a) => a.fmt(f),
2021-01-07 11:20:28 -05:00
ty::PredicateKind::Subtype(ref pair) => pair.fmt(f),
2020-11-21 07:06:16 -05:00
ty::PredicateKind::Coerce(ref pair) => pair.fmt(f),
2021-01-07 11:20:28 -05:00
ty::PredicateKind::RegionOutlives(ref pair) => pair.fmt(f),
ty::PredicateKind::TypeOutlives(ref pair) => pair.fmt(f),
ty::PredicateKind::Projection(ref pair) => pair.fmt(f),
ty::PredicateKind::WellFormed(data) => write!(f, "WellFormed({:?})", data),
ty::PredicateKind::ObjectSafe(trait_def_id) => {
write!(f, "ObjectSafe({:?})", trait_def_id)
}
2021-01-07 11:20:28 -05:00
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
2019-12-22 17:42:04 -05:00
write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
}
ty::PredicateKind::ConstEvaluatable(uv) => {
write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs_)
}
2021-01-07 11:20:28 -05:00
ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
2020-09-01 17:58:34 +02:00
write!(f, "TypeWellFormedFromEnv({:?})", ty)
}
}
}
}
///////////////////////////////////////////////////////////////////////////
// Atomic structs
//
// For things that don't carry any arena-allocated data (and are
// copy...), just add them to this list.
2020-10-24 09:27:15 +02:00
TrivialTypeFoldableAndLiftImpls! {
(),
bool,
usize,
::rustc_target::abi::VariantIdx,
u32,
u64,
2018-11-26 17:30:19 +01:00
String,
2019-02-05 11:20:45 -06:00
crate::middle::region::Scope,
crate::ty::FloatTy,
2020-04-27 23:26:11 +05:30
::rustc_ast::InlineAsmOptions,
::rustc_ast::InlineAsmTemplatePiece,
::rustc_ast::NodeId,
::rustc_span::symbol::Symbol,
::rustc_hir::def::Res,
::rustc_hir::def_id::DefId,
2020-07-08 01:03:19 +02:00
::rustc_hir::def_id::LocalDefId,
::rustc_hir::HirId,
::rustc_hir::LlvmInlineAsmInner,
::rustc_hir::MatchSource,
::rustc_hir::Mutability,
::rustc_hir::Unsafety,
2020-02-14 18:17:50 +00:00
::rustc_target::asm::InlineAsmRegOrRegClass,
::rustc_target::spec::abi::Abi,
crate::mir::coverage::ExpressionOperandId,
crate::mir::coverage::CounterValueReference,
crate::mir::coverage::InjectedExpressionId,
crate::mir::coverage::InjectedExpressionIndex,
crate::mir::coverage::MappedExpressionIndex,
2019-02-05 11:20:45 -06:00
crate::mir::Local,
crate::mir::Promoted,
crate::traits::Reveal,
crate::ty::adjustment::AutoBorrowMutability,
crate::ty::AdtKind,
2021-08-27 05:02:23 +00:00
crate::ty::BoundConstness,
// Including `BoundRegionKind` is a *bit* dubious, but direct
// references to bound region appear in `ty::Error`, and aren't
// really meant to be folded. In general, we can only fold a fully
// general `Region`.
crate::ty::BoundRegionKind,
crate::ty::AssocItem,
crate::ty::Placeholder<crate::ty::BoundRegionKind>,
2019-02-05 11:20:45 -06:00
crate::ty::ClosureKind,
crate::ty::FreeRegion,
crate::ty::InferTy,
2019-02-05 11:20:45 -06:00
crate::ty::IntVarValue,
crate::ty::ParamConst,
2019-02-05 11:20:45 -06:00
crate::ty::ParamTy,
crate::ty::adjustment::PointerCast,
crate::ty::RegionVid,
2019-02-05 11:20:45 -06:00
crate::ty::UniverseIndex,
crate::ty::Variance,
::rustc_span::Span,
}
2015-09-06 21:51:58 +03:00
///////////////////////////////////////////////////////////////////////////
// Lift implementations
// FIXME(eddyb) replace all the uses of `Option::map` with `?`.
2015-09-06 21:51:58 +03:00
impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>> Lift<'tcx> for (A, B) {
type Lifted = (A::Lifted, B::Lifted);
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
2020-10-21 23:52:41 +02:00
Some((tcx.lift(self.0)?, tcx.lift(self.1)?))
2015-09-06 21:51:58 +03:00
}
}
2016-12-26 14:34:03 +01:00
impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>, C: Lift<'tcx>> Lift<'tcx> for (A, B, C) {
type Lifted = (A::Lifted, B::Lifted, C::Lifted);
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
2020-10-21 23:52:41 +02:00
Some((tcx.lift(self.0)?, tcx.lift(self.1)?, tcx.lift(self.2)?))
2019-12-22 17:42:04 -05:00
}
2016-12-26 14:34:03 +01:00
}
impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Option<T> {
type Lifted = Option<T::Lifted>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
match self {
Some(x) => tcx.lift(x).map(Some),
2019-12-22 17:42:04 -05:00
None => Some(None),
}
}
}
impl<'tcx, T: Lift<'tcx>, E: Lift<'tcx>> Lift<'tcx> for Result<T, E> {
type Lifted = Result<T::Lifted, E::Lifted>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
match self {
Ok(x) => tcx.lift(x).map(Ok),
Err(e) => tcx.lift(e).map(Err),
}
}
}
impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Box<T> {
type Lifted = Box<T::Lifted>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(*self).map(Box::new)
}
}
2020-10-16 21:59:49 +02:00
impl<'tcx, T: Lift<'tcx> + Clone> Lift<'tcx> for Rc<T> {
type Lifted = Rc<T::Lifted>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(self.as_ref().clone()).map(Rc::new)
}
}
2020-10-16 21:59:49 +02:00
impl<'tcx, T: Lift<'tcx> + Clone> Lift<'tcx> for Arc<T> {
2019-06-18 08:15:27 -04:00
type Lifted = Arc<T::Lifted>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(self.as_ref().clone()).map(Arc::new)
2015-09-06 21:51:58 +03:00
}
}
impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Vec<T> {
type Lifted = Vec<T::Lifted>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
self.into_iter().map(|v| tcx.lift(v)).collect()
}
}
impl<'tcx, I: Idx, T: Lift<'tcx>> Lift<'tcx> for IndexVec<I, T> {
type Lifted = IndexVec<I, T::Lifted>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
self.into_iter().map(|e| tcx.lift(e)).collect()
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::TraitRef<'a> {
type Lifted = ty::TraitRef<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(self.substs).map(|substs| ty::TraitRef { def_id: self.def_id, substs })
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialTraitRef<'a> {
type Lifted = ty::ExistentialTraitRef<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(self.substs).map(|substs| ty::ExistentialTraitRef { def_id: self.def_id, substs })
2015-09-06 21:51:58 +03:00
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialPredicate<'a> {
type Lifted = ty::ExistentialPredicate<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
match self {
2019-12-22 17:42:04 -05:00
ty::ExistentialPredicate::Trait(x) => tcx.lift(x).map(ty::ExistentialPredicate::Trait),
ty::ExistentialPredicate::Projection(x) => {
tcx.lift(x).map(ty::ExistentialPredicate::Projection)
}
ty::ExistentialPredicate::AutoTrait(def_id) => {
2020-10-16 21:59:49 +02:00
Some(ty::ExistentialPredicate::AutoTrait(def_id))
}
}
}
}
2015-09-06 21:51:58 +03:00
impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
type Lifted = ty::TraitPredicate<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::TraitPredicate<'tcx>> {
2021-07-22 21:56:07 +08:00
tcx.lift(self.trait_ref)
.map(|trait_ref| ty::TraitPredicate { trait_ref, constness: self.constness })
2015-09-06 21:51:58 +03:00
}
}
2017-03-09 21:47:09 -05:00
impl<'a, 'tcx> Lift<'tcx> for ty::SubtypePredicate<'a> {
type Lifted = ty::SubtypePredicate<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::SubtypePredicate<'tcx>> {
tcx.lift((self.a, self.b)).map(|(a, b)| ty::SubtypePredicate {
2017-03-09 21:47:09 -05:00
a_is_expected: self.a_is_expected,
a,
b,
2017-03-09 21:47:09 -05:00
})
}
}
2020-11-21 07:06:16 -05:00
impl<'a, 'tcx> Lift<'tcx> for ty::CoercePredicate<'a> {
type Lifted = ty::CoercePredicate<'tcx>;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::CoercePredicate<'tcx>> {
tcx.lift((self.a, self.b)).map(|(a, b)| ty::CoercePredicate { a, b })
}
}
impl<'tcx, A: Copy + Lift<'tcx>, B: Copy + Lift<'tcx>> Lift<'tcx> for ty::OutlivesPredicate<A, B> {
2015-09-06 21:51:58 +03:00
type Lifted = ty::OutlivesPredicate<A::Lifted, B::Lifted>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift((self.0, self.1)).map(|(a, b)| ty::OutlivesPredicate(a, b))
2015-09-06 21:51:58 +03:00
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionTy<'a> {
type Lifted = ty::ProjectionTy<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::ProjectionTy<'tcx>> {
tcx.lift(self.substs)
2019-12-22 17:42:04 -05:00
.map(|substs| ty::ProjectionTy { item_def_id: self.item_def_id, substs })
}
}
2015-09-06 21:51:58 +03:00
impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> {
type Lifted = ty::ProjectionPredicate<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::ProjectionPredicate<'tcx>> {
tcx.lift((self.projection_ty, self.ty))
2019-12-22 17:42:04 -05:00
.map(|(projection_ty, ty)| ty::ProjectionPredicate { projection_ty, ty })
2015-09-06 21:51:58 +03:00
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> {
type Lifted = ty::ExistentialProjection<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(self.substs).map(|substs| ty::ExistentialProjection {
2019-12-22 17:42:04 -05:00
substs,
2020-10-16 21:59:49 +02:00
ty: tcx.lift(self.ty).expect("type must lift when substs do"),
2019-12-22 17:42:04 -05:00
item_def_id: self.item_def_id,
})
}
}
2021-01-07 11:20:28 -05:00
impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> {
type Lifted = ty::PredicateKind<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
match self {
2021-07-22 21:56:07 +08:00
ty::PredicateKind::Trait(data) => tcx.lift(data).map(ty::PredicateKind::Trait),
2021-01-07 11:20:28 -05:00
ty::PredicateKind::Subtype(data) => tcx.lift(data).map(ty::PredicateKind::Subtype),
2020-11-21 07:06:16 -05:00
ty::PredicateKind::Coerce(data) => tcx.lift(data).map(ty::PredicateKind::Coerce),
2021-01-07 11:20:28 -05:00
ty::PredicateKind::RegionOutlives(data) => {
tcx.lift(data).map(ty::PredicateKind::RegionOutlives)
}
2021-01-07 11:20:28 -05:00
ty::PredicateKind::TypeOutlives(data) => {
tcx.lift(data).map(ty::PredicateKind::TypeOutlives)
}
2021-01-07 11:20:28 -05:00
ty::PredicateKind::Projection(data) => {
tcx.lift(data).map(ty::PredicateKind::Projection)
}
2021-01-07 11:20:28 -05:00
ty::PredicateKind::WellFormed(ty) => tcx.lift(ty).map(ty::PredicateKind::WellFormed),
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
2020-10-16 21:59:49 +02:00
tcx.lift(closure_substs).map(|closure_substs| {
2021-01-07 11:20:28 -05:00
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind)
2019-12-22 17:42:04 -05:00
})
}
2021-01-07 11:20:28 -05:00
ty::PredicateKind::ObjectSafe(trait_def_id) => {
Some(ty::PredicateKind::ObjectSafe(trait_def_id))
}
ty::PredicateKind::ConstEvaluatable(uv) => {
tcx.lift(uv).map(|uv| ty::PredicateKind::ConstEvaluatable(uv))
}
2021-01-07 11:20:28 -05:00
ty::PredicateKind::ConstEquate(c1, c2) => {
tcx.lift((c1, c2)).map(|(c1, c2)| ty::PredicateKind::ConstEquate(c1, c2))
}
2021-01-07 11:20:28 -05:00
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
tcx.lift(ty).map(ty::PredicateKind::TypeWellFormedFromEnv)
2020-09-01 17:58:34 +02:00
}
}
}
}
2020-10-05 16:51:33 -04:00
impl<'a, 'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<'a, T>
where
<T as Lift<'tcx>>::Lifted: TypeFoldable<'tcx>,
{
type Lifted = ty::Binder<'tcx, T::Lifted>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
2020-10-05 20:41:46 -04:00
let bound_vars = tcx.lift(self.bound_vars());
tcx.lift(self.skip_binder())
.zip(bound_vars)
.map(|(value, vars)| ty::Binder::bind_with_vars(value, vars))
2015-09-06 21:51:58 +03:00
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> {
type Lifted = ty::ParamEnv<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(self.caller_bounds())
2020-09-01 17:58:34 +02:00
.map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal()))
}
}
impl<'a, 'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::ParamEnvAnd<'a, T> {
type Lifted = ty::ParamEnvAnd<'tcx, T::Lifted>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(self.param_env).and_then(|param_env| {
tcx.lift(self.value).map(|value| ty::ParamEnvAnd { param_env, value })
})
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::ClosureSubsts<'a> {
type Lifted = ty::ClosureSubsts<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(self.substs).map(|substs| ty::ClosureSubsts { substs })
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::GeneratorSubsts<'a> {
type Lifted = ty::GeneratorSubsts<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(self.substs).map(|substs| ty::GeneratorSubsts { substs })
2016-12-26 14:34:03 +01:00
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::Adjustment<'a> {
type Lifted = ty::adjustment::Adjustment<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
let ty::adjustment::Adjustment { kind, target } = self;
tcx.lift(kind).and_then(|kind| {
tcx.lift(target).map(|target| ty::adjustment::Adjustment { kind, target })
})
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::Adjust<'a> {
type Lifted = ty::adjustment::Adjust<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
match self {
2019-12-22 17:42:04 -05:00
ty::adjustment::Adjust::NeverToAny => Some(ty::adjustment::Adjust::NeverToAny),
ty::adjustment::Adjust::Pointer(ptr) => Some(ty::adjustment::Adjust::Pointer(ptr)),
2020-10-16 21:59:49 +02:00
ty::adjustment::Adjust::Deref(overloaded) => {
tcx.lift(overloaded).map(ty::adjustment::Adjust::Deref)
}
2020-10-16 21:59:49 +02:00
ty::adjustment::Adjust::Borrow(autoref) => {
tcx.lift(autoref).map(ty::adjustment::Adjust::Borrow)
}
}
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::OverloadedDeref<'a> {
type Lifted = ty::adjustment::OverloadedDeref<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(self.region).map(|region| ty::adjustment::OverloadedDeref {
region,
mutbl: self.mutbl,
span: self.span,
})
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::AutoBorrow<'a> {
type Lifted = ty::adjustment::AutoBorrow<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
match self {
ty::adjustment::AutoBorrow::Ref(r, m) => {
2020-10-16 21:59:49 +02:00
tcx.lift(r).map(|r| ty::adjustment::AutoBorrow::Ref(r, m))
}
2019-12-22 17:42:04 -05:00
ty::adjustment::AutoBorrow::RawPtr(m) => Some(ty::adjustment::AutoBorrow::RawPtr(m)),
}
}
}
2016-12-26 14:34:03 +01:00
impl<'a, 'tcx> Lift<'tcx> for ty::GenSig<'a> {
type Lifted = ty::GenSig<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift((self.resume_ty, self.yield_ty, self.return_ty))
.map(|(resume_ty, yield_ty, return_ty)| ty::GenSig { resume_ty, yield_ty, return_ty })
2016-12-26 14:34:03 +01:00
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::FnSig<'a> {
type Lifted = ty::FnSig<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(self.inputs_and_output).map(|x| ty::FnSig {
2019-12-22 17:42:04 -05:00
inputs_and_output: x,
c_variadic: self.c_variadic,
unsafety: self.unsafety,
abi: self.abi,
})
}
}
impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::error::ExpectedFound<T> {
type Lifted = ty::error::ExpectedFound<T::Lifted>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
let ty::error::ExpectedFound { expected, found } = self;
tcx.lift(expected).and_then(|expected| {
tcx.lift(found).map(|found| ty::error::ExpectedFound { expected, found })
})
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
type Lifted = ty::error::TypeError<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
2019-02-05 11:20:45 -06:00
use crate::ty::error::TypeError::*;
2020-10-16 21:59:49 +02:00
Some(match self {
Mismatch => Mismatch,
2021-07-22 21:56:07 +08:00
ConstnessMismatch(x) => ConstnessMismatch(x),
UnsafetyMismatch(x) => UnsafetyMismatch(x),
AbiMismatch(x) => AbiMismatch(x),
Mutability => Mutability,
ArgumentMutability(i) => ArgumentMutability(i),
TupleSize(x) => TupleSize(x),
FixedArraySize(x) => FixedArraySize(x),
ArgCount => ArgCount,
RegionsDoesNotOutlive(a, b) => {
2020-10-16 21:59:49 +02:00
return tcx.lift((a, b)).map(|(a, b)| RegionsDoesNotOutlive(a, b));
}
2019-02-20 05:39:04 -05:00
RegionsInsufficientlyPolymorphic(a, b) => {
2020-10-16 21:59:49 +02:00
return tcx.lift(b).map(|b| RegionsInsufficientlyPolymorphic(a, b));
2019-02-20 05:39:04 -05:00
}
RegionsOverlyPolymorphic(a, b) => {
2020-10-16 21:59:49 +02:00
return tcx.lift(b).map(|b| RegionsOverlyPolymorphic(a, b));
2019-02-20 05:39:04 -05:00
}
RegionsPlaceholderMismatch => RegionsPlaceholderMismatch,
IntMismatch(x) => IntMismatch(x),
FloatMismatch(x) => FloatMismatch(x),
Traits(x) => Traits(x),
VariadicMismatch(x) => VariadicMismatch(x),
2020-10-16 21:59:49 +02:00
CyclicTy(t) => return tcx.lift(t).map(|t| CyclicTy(t)),
CyclicConst(ct) => return tcx.lift(ct).map(|ct| CyclicConst(ct)),
ProjectionMismatched(x) => ProjectionMismatched(x),
ArgumentSorts(x, i) => return tcx.lift(x).map(|x| ArgumentSorts(x, i)),
2020-10-16 21:59:49 +02:00
Sorts(x) => return tcx.lift(x).map(Sorts),
ExistentialMismatch(x) => return tcx.lift(x).map(ExistentialMismatch),
ConstMismatch(x) => return tcx.lift(x).map(ConstMismatch),
IntrinsicCast => IntrinsicCast,
2020-10-16 21:59:49 +02:00
TargetFeatureCast(x) => TargetFeatureCast(x),
ObjectUnsafeCoercion(x) => return tcx.lift(x).map(ObjectUnsafeCoercion),
})
}
}
2018-01-02 23:22:09 +00:00
impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> {
type Lifted = ty::InstanceDef<'tcx>;
2020-10-16 21:59:49 +02:00
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
match self {
2019-12-22 17:42:04 -05:00
ty::InstanceDef::Item(def_id) => Some(ty::InstanceDef::Item(def_id)),
ty::InstanceDef::VtableShim(def_id) => Some(ty::InstanceDef::VtableShim(def_id)),
ty::InstanceDef::ReifyShim(def_id) => Some(ty::InstanceDef::ReifyShim(def_id)),
ty::InstanceDef::Intrinsic(def_id) => Some(ty::InstanceDef::Intrinsic(def_id)),
2020-10-16 21:59:49 +02:00
ty::InstanceDef::FnPtrShim(def_id, ty) => {
2019-12-22 17:42:04 -05:00
Some(ty::InstanceDef::FnPtrShim(def_id, tcx.lift(ty)?))
}
ty::InstanceDef::Virtual(def_id, n) => Some(ty::InstanceDef::Virtual(def_id, n)),
Support `#[track_caller]` on closures and generators This PR allows applying a `#[track_caller]` attribute to a closure/generator expression. The attribute as interpreted as applying to the compiler-generated implementation of the corresponding trait method (`FnOnce::call_once`, `FnMut::call_mut`, `Fn::call`, or `Generator::resume`). This feature does not have its own feature gate - however, it requires `#![feature(stmt_expr_attributes)]` in order to actually apply an attribute to a closure or generator. This is implemented in the same way as for functions - an extra location argument is appended to the end of the ABI. For closures, this argument is *not* part of the 'tupled' argument storing the parameters - the final closure argument for `#[track_caller]` closures is no longer a tuple. For direct (monomorphized) calls, the necessary support was already implemented - we just needeed to adjust some assertions around checking the ABI and argument count to take closures into account. For calls through a trait object, more work was needed. When creating a `ReifyShim`, we need to create a shim for the trait method (e.g. `FnOnce::call_mut`) - unlike normal functions, closures are never invoked directly, and always go through a trait method. Additional handling was needed for `InstanceDef::ClosureOnceShim`. In order to pass location information throgh a direct (monomorphized) call to `FnOnce::call_once` on an `FnMut` closure, we need to make `ClosureOnceShim` aware of `#[tracked_caller]`. A new field `track_caller` is added to `ClosureOnceShim` - this is used by `InstanceDef::requires_caller` location, allowing codegen to pass through the extra location argument. Since `ClosureOnceShim.track_caller` is only used by codegen, we end up generating two identical MIR shims - one for `track_caller == true`, and one for `track_caller == false`. However, these two shims are used by the entire crate (i.e. it's two shims total, not two shims per unique closure), so this shouldn't a big deal.
2021-06-27 14:01:11 -05:00
ty::InstanceDef::ClosureOnceShim { call_once, track_caller } => {
Some(ty::InstanceDef::ClosureOnceShim { call_once, track_caller })
2019-12-22 17:42:04 -05:00
}
2020-10-16 21:59:49 +02:00
ty::InstanceDef::DropGlue(def_id, ty) => {
2019-12-22 17:42:04 -05:00
Some(ty::InstanceDef::DropGlue(def_id, tcx.lift(ty)?))
}
2020-10-16 21:59:49 +02:00
ty::InstanceDef::CloneShim(def_id, ty) => {
2019-12-22 17:42:04 -05:00
Some(ty::InstanceDef::CloneShim(def_id, tcx.lift(ty)?))
}
2018-01-02 23:22:09 +00:00
}
}
}
2015-09-06 21:51:58 +03:00
///////////////////////////////////////////////////////////////////////////
// TypeFoldable implementations.
//
// Ideally, each type should invoke `folder.fold_foo(self)` and
// nothing else. In some cases, though, we haven't gotten around to
// adding methods on the `folder` yet, and thus the folding is
// hard-coded here. This is less-flexible, because folders cannot
// override the behavior, but there are a lot of random types and one
// can easily refactor the folding into the TypeFolder trait as
// needed.
/// AdtDefs are basically the same as a DefId.
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Self {
self
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
}
impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> (T, U) {
2015-09-06 21:51:58 +03:00
(self.0.fold_with(folder), self.1.fold_with(folder))
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.0.visit_with(visitor)?;
self.1.visit_with(visitor)
}
2015-09-06 21:51:58 +03:00
}
2020-07-08 01:03:19 +02:00
impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>> TypeFoldable<'tcx>
for (A, B, C)
{
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> (A, B, C) {
2020-07-08 01:03:19 +02:00
(self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder))
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.0.visit_with(visitor)?;
self.1.visit_with(visitor)?;
self.2.visit_with(visitor)
2020-07-08 01:03:19 +02:00
}
}
EnumTypeFoldableImpl! {
impl<'tcx, T> TypeFoldable<'tcx> for Option<T> {
(Some)(a),
(None),
} where T: TypeFoldable<'tcx>
2015-09-06 21:51:58 +03:00
}
2019-05-31 10:23:22 +02:00
EnumTypeFoldableImpl! {
impl<'tcx, T, E> TypeFoldable<'tcx> for Result<T, E> {
(Ok)(a),
(Err)(a),
} where T: TypeFoldable<'tcx>, E: TypeFoldable<'tcx>,
}
2015-09-06 21:51:58 +03:00
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
// FIXME: Reuse the `Rc` here.
Rc::new((*self).clone().fold_with(folder))
2015-09-06 21:51:58 +03:00
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
(**self).visit_with(visitor)
}
2015-09-06 21:51:58 +03:00
}
2019-06-18 19:15:31 -04:00
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
// FIXME: Reuse the `Arc` here.
Arc::new((*self).clone().fold_with(folder))
2019-06-18 19:15:31 -04:00
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
2019-06-18 19:15:31 -04:00
(**self).visit_with(visitor)
}
}
2015-09-06 21:51:58 +03:00
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
self.map_id(|value| value.fold_with(folder))
2015-09-06 21:51:58 +03:00
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
(**self).visit_with(visitor)
}
2015-09-06 21:51:58 +03:00
}
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
self.map_id(|t| t.fold_with(folder))
2015-09-06 21:51:58 +03:00
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
2015-09-06 21:51:58 +03:00
}
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
self.map_id(|t| t.fold_with(folder))
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
2020-10-05 16:51:33 -04:00
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
self.map_bound(|ty| ty.fold_with(folder))
}
2020-10-24 02:21:18 +02:00
fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
folder.fold_binder(self)
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
2020-06-24 23:40:33 +02:00
self.as_ref().skip_binder().visit_with(visitor)
}
2020-11-05 17:30:39 +01:00
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_binder(self)
}
2015-09-06 21:51:58 +03:00
}
2020-10-05 16:51:33 -04:00
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
2020-12-11 15:02:46 -05:00
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v))
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|p| p.visit_with(visitor))
}
}
2018-08-22 00:35:01 +01:00
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
2020-10-24 09:27:15 +02:00
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v))
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
2020-10-24 09:27:15 +02:00
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v))
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
2018-01-16 09:24:38 +01:00
impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
2019-02-05 11:20:45 -06:00
use crate::ty::InstanceDef::*;
2018-01-16 09:24:38 +01:00
Self {
substs: self.substs.fold_with(folder),
def: match self.def {
2020-07-03 19:13:39 +02:00
Item(def) => Item(def.fold_with(folder)),
2018-09-10 22:54:48 +09:00
VtableShim(did) => VtableShim(did.fold_with(folder)),
ReifyShim(did) => ReifyShim(did.fold_with(folder)),
2018-01-16 09:24:38 +01:00
Intrinsic(did) => Intrinsic(did.fold_with(folder)),
2019-12-22 17:42:04 -05:00
FnPtrShim(did, ty) => FnPtrShim(did.fold_with(folder), ty.fold_with(folder)),
Virtual(did, i) => Virtual(did.fold_with(folder), i),
Support `#[track_caller]` on closures and generators This PR allows applying a `#[track_caller]` attribute to a closure/generator expression. The attribute as interpreted as applying to the compiler-generated implementation of the corresponding trait method (`FnOnce::call_once`, `FnMut::call_mut`, `Fn::call`, or `Generator::resume`). This feature does not have its own feature gate - however, it requires `#![feature(stmt_expr_attributes)]` in order to actually apply an attribute to a closure or generator. This is implemented in the same way as for functions - an extra location argument is appended to the end of the ABI. For closures, this argument is *not* part of the 'tupled' argument storing the parameters - the final closure argument for `#[track_caller]` closures is no longer a tuple. For direct (monomorphized) calls, the necessary support was already implemented - we just needeed to adjust some assertions around checking the ABI and argument count to take closures into account. For calls through a trait object, more work was needed. When creating a `ReifyShim`, we need to create a shim for the trait method (e.g. `FnOnce::call_mut`) - unlike normal functions, closures are never invoked directly, and always go through a trait method. Additional handling was needed for `InstanceDef::ClosureOnceShim`. In order to pass location information throgh a direct (monomorphized) call to `FnOnce::call_once` on an `FnMut` closure, we need to make `ClosureOnceShim` aware of `#[tracked_caller]`. A new field `track_caller` is added to `ClosureOnceShim` - this is used by `InstanceDef::requires_caller` location, allowing codegen to pass through the extra location argument. Since `ClosureOnceShim.track_caller` is only used by codegen, we end up generating two identical MIR shims - one for `track_caller == true`, and one for `track_caller == false`. However, these two shims are used by the entire crate (i.e. it's two shims total, not two shims per unique closure), so this shouldn't a big deal.
2021-06-27 14:01:11 -05:00
ClosureOnceShim { call_once, track_caller } => {
ClosureOnceShim { call_once: call_once.fold_with(folder), track_caller }
2019-12-22 17:42:04 -05:00
}
DropGlue(did, ty) => DropGlue(did.fold_with(folder), ty.fold_with(folder)),
CloneShim(did, ty) => CloneShim(did.fold_with(folder), ty.fold_with(folder)),
2018-01-16 09:24:38 +01:00
},
}
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
2019-02-05 11:20:45 -06:00
use crate::ty::InstanceDef::*;
self.substs.visit_with(visitor)?;
match self.def {
Item(def) => def.visit_with(visitor),
VtableShim(did) | ReifyShim(did) | Intrinsic(did) | Virtual(did, _) => {
did.visit_with(visitor)
}
FnPtrShim(did, ty) | CloneShim(did, ty) => {
did.visit_with(visitor)?;
ty.visit_with(visitor)
}
DropGlue(did, ty) => {
did.visit_with(visitor)?;
ty.visit_with(visitor)
2019-12-22 17:42:04 -05:00
}
Support `#[track_caller]` on closures and generators This PR allows applying a `#[track_caller]` attribute to a closure/generator expression. The attribute as interpreted as applying to the compiler-generated implementation of the corresponding trait method (`FnOnce::call_once`, `FnMut::call_mut`, `Fn::call`, or `Generator::resume`). This feature does not have its own feature gate - however, it requires `#![feature(stmt_expr_attributes)]` in order to actually apply an attribute to a closure or generator. This is implemented in the same way as for functions - an extra location argument is appended to the end of the ABI. For closures, this argument is *not* part of the 'tupled' argument storing the parameters - the final closure argument for `#[track_caller]` closures is no longer a tuple. For direct (monomorphized) calls, the necessary support was already implemented - we just needeed to adjust some assertions around checking the ABI and argument count to take closures into account. For calls through a trait object, more work was needed. When creating a `ReifyShim`, we need to create a shim for the trait method (e.g. `FnOnce::call_mut`) - unlike normal functions, closures are never invoked directly, and always go through a trait method. Additional handling was needed for `InstanceDef::ClosureOnceShim`. In order to pass location information throgh a direct (monomorphized) call to `FnOnce::call_once` on an `FnMut` closure, we need to make `ClosureOnceShim` aware of `#[tracked_caller]`. A new field `track_caller` is added to `ClosureOnceShim` - this is used by `InstanceDef::requires_caller` location, allowing codegen to pass through the extra location argument. Since `ClosureOnceShim.track_caller` is only used by codegen, we end up generating two identical MIR shims - one for `track_caller == true`, and one for `track_caller == false`. However, these two shims are used by the entire crate (i.e. it's two shims total, not two shims per unique closure), so this shouldn't a big deal.
2021-06-27 14:01:11 -05:00
ClosureOnceShim { call_once, track_caller: _ } => call_once.visit_with(visitor),
}
2018-01-16 09:24:38 +01:00
}
}
2018-01-02 23:22:09 +00:00
impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
2019-12-22 17:42:04 -05:00
Self { instance: self.instance.fold_with(folder), promoted: self.promoted }
2018-01-02 23:22:09 +00:00
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
2018-01-02 23:22:09 +00:00
self.instance.visit_with(visitor)
}
}
2015-09-06 21:51:58 +03:00
impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
2020-10-24 09:27:15 +02:00
let kind = match *self.kind() {
ty::RawPtr(tm) => ty::RawPtr(tm.fold_with(folder)),
ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)),
ty::Slice(typ) => ty::Slice(typ.fold_with(folder)),
2020-10-24 09:27:15 +02:00
ty::Adt(tid, substs) => ty::Adt(tid, substs.fold_with(folder)),
ty::Dynamic(trait_ty, region) => {
2019-12-22 17:42:04 -05:00
ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder))
}
2019-12-22 17:42:04 -05:00
ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)),
2020-10-24 09:27:15 +02:00
ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.fold_with(folder)),
ty::FnPtr(f) => ty::FnPtr(f.fold_with(folder)),
2020-10-24 09:27:15 +02:00
ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl),
ty::Generator(did, substs, movability) => {
2020-10-24 09:27:15 +02:00
ty::Generator(did, substs.fold_with(folder), movability)
2017-07-05 14:57:26 -07:00
}
ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)),
2020-10-24 09:27:15 +02:00
ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)),
ty::Projection(data) => ty::Projection(data.fold_with(folder)),
ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)),
2018-10-22 20:37:56 +02:00
2019-12-22 17:42:04 -05:00
ty::Bool
| ty::Char
| ty::Str
| ty::Int(_)
| ty::Uint(_)
| ty::Float(_)
| ty::Error(_)
2019-12-22 17:42:04 -05:00
| ty::Infer(_)
| ty::Param(..)
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Never
| ty::Foreign(..) => return self,
};
2020-08-03 00:49:11 +02:00
if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) }
}
2020-10-24 02:21:18 +02:00
fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
folder.fold_ty(self)
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
2020-08-03 00:49:11 +02:00
match self.kind() {
ty::RawPtr(ref tm) => tm.visit_with(visitor),
ty::Array(typ, sz) => {
typ.visit_with(visitor)?;
sz.visit_with(visitor)
}
ty::Slice(typ) => typ.visit_with(visitor),
ty::Adt(_, substs) => substs.visit_with(visitor),
2019-12-22 17:42:04 -05:00
ty::Dynamic(ref trait_ty, ref reg) => {
trait_ty.visit_with(visitor)?;
reg.visit_with(visitor)
2019-12-22 17:42:04 -05:00
}
ty::Tuple(ts) => ts.visit_with(visitor),
ty::FnDef(_, substs) => substs.visit_with(visitor),
ty::FnPtr(ref f) => f.visit_with(visitor),
ty::Ref(r, ty, _) => {
r.visit_with(visitor)?;
ty.visit_with(visitor)
}
2019-12-22 17:42:04 -05:00
ty::Generator(_did, ref substs, _) => substs.visit_with(visitor),
ty::GeneratorWitness(ref types) => types.visit_with(visitor),
ty::Closure(_did, ref substs) => substs.visit_with(visitor),
2020-05-12 01:56:29 -04:00
ty::Projection(ref data) => data.visit_with(visitor),
ty::Opaque(_, ref substs) => substs.visit_with(visitor),
2018-10-22 20:37:56 +02:00
2019-12-22 17:42:04 -05:00
ty::Bool
| ty::Char
| ty::Str
| ty::Int(_)
| ty::Uint(_)
| ty::Float(_)
| ty::Error(_)
2019-12-22 17:42:04 -05:00
| ty::Infer(_)
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Param(..)
| ty::Never
| ty::Foreign(..) => ControlFlow::CONTINUE,
}
}
2015-09-06 21:51:58 +03:00
2020-11-05 17:30:39 +01:00
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_ty(self)
2015-09-06 21:51:58 +03:00
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Self {
self
}
2020-10-24 02:21:18 +02:00
fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
folder.fold_region(self)
2015-09-06 21:51:58 +03:00
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
2020-11-05 17:30:39 +01:00
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_region(*self)
}
2015-09-06 21:51:58 +03:00
}
2020-05-11 22:04:22 +02:00
impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
2021-07-19 12:13:25 +02:00
fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
folder.fold_predicate(self)
}
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
2021-01-07 18:01:03 -05:00
let new = self.inner.kind.fold_with(folder);
2020-10-24 02:21:18 +02:00
folder.tcx().reuse_or_mk_predicate(self, new)
2020-05-11 22:04:22 +02:00
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
2021-01-07 18:01:03 -05:00
self.inner.kind.visit_with(visitor)
}
2020-11-05 17:30:39 +01:00
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_predicate(*self)
}
fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
self.inner.outer_exclusive_binder > binder
}
fn has_type_flags(&self, flags: ty::TypeFlags) -> bool {
self.inner.flags.intersects(flags)
}
}
2018-08-22 00:35:01 +01:00
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
2020-10-24 09:27:15 +02:00
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_predicates(v))
2017-05-23 04:19:47 -04:00
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|p| p.visit_with(visitor))
2017-05-23 04:19:47 -04:00
}
}
impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
self.map_id(|x| x.fold_with(folder))
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
2019-03-14 10:19:31 +01:00
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
2019-03-14 10:19:31 +01:00
let ty = self.ty.fold_with(folder);
let val = self.val.fold_with(folder);
2020-05-31 17:16:44 +02:00
if ty != self.ty || val != self.val {
folder.tcx().mk_const(ty::Const { ty, val })
} else {
2020-10-24 02:21:18 +02:00
self
2020-05-31 17:16:44 +02:00
}
}
2020-10-24 02:21:18 +02:00
fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
folder.fold_const(self)
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.ty.visit_with(visitor)?;
self.val.visit_with(visitor)
}
2020-11-05 17:30:39 +01:00
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_const(self)
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
match self {
ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)),
ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)),
2021-03-16 00:05:45 +01:00
ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)),
ty::ConstKind::Value(_)
| ty::ConstKind::Bound(..)
| ty::ConstKind::Placeholder(..)
2020-10-24 02:21:18 +02:00
| ty::ConstKind::Error(_) => self,
2018-12-13 11:11:12 +01:00
}
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
2019-03-14 10:19:31 +01:00
match *self {
ty::ConstKind::Infer(ic) => ic.visit_with(visitor),
ty::ConstKind::Param(p) => p.visit_with(visitor),
2021-03-16 00:05:45 +01:00
ty::ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
ty::ConstKind::Value(_)
| ty::ConstKind::Bound(..)
| ty::ConstKind::Placeholder(_)
| ty::ConstKind::Error(_) => ControlFlow::CONTINUE,
2019-03-14 10:19:31 +01:00
}
}
}
impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
2020-10-24 02:21:18 +02:00
fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Self {
self
}
2020-11-05 17:30:39 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
}
2021-03-16 00:05:45 +01:00
impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
ty::Unevaluated {
def: self.def,
substs_: Some(self.substs(folder.tcx()).fold_with(folder)),
promoted: self.promoted,
}
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_unevaluated_const(*self)
}
2021-03-16 00:05:45 +01:00
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
if let Some(tcx) = visitor.tcx_for_anon_const_substs() {
self.substs(tcx).visit_with(visitor)
} else if let Some(substs) = self.substs_ {
substs.visit_with(visitor)
} else {
debug!("ignoring default substs of `{:?}`", self.def);
ControlFlow::CONTINUE
}
}
}
2021-08-02 08:47:15 +02:00
impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> {
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
ty::Unevaluated {
def: self.def,
substs_: Some(self.substs(folder.tcx()).fold_with(folder)),
promoted: self.promoted,
}
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_unevaluated_const(self.expand())
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
if let Some(tcx) = visitor.tcx_for_anon_const_substs() {
self.substs(tcx).visit_with(visitor)
} else if let Some(substs) = self.substs_ {
substs.visit_with(visitor)
} else {
debug!("ignoring default substs of `{:?}`", self.def);
ControlFlow::CONTINUE
}
}
}