Auto merge of #96883 - jackh726:early-binder-2, r=oli-obk
Add EarlyBinder Chalk has no concept of `Param` (e0ade19d13/chalk-ir/src/lib.rs (L579)) or `ReEarlyBound` (e0ade19d13/chalk-ir/src/lib.rs (L1308)). Everything is just "bound" - the equivalent of rustc's late-bound. It's not completely clear yet whether to move everything to the same time of binder in rustc or add `Param` and `ReEarlyBound` in Chalk. Either way, tracking when we have or haven't already substituted out these in rustc can be helpful. As a first step, I'm just adding a `EarlyBinder` newtype that is required to call `subst`. I also add a couple "transparent" `bound_*` wrappers around a couple query that are often immediately substituted. r? `@nikomatsakis`
This commit is contained in:
commit
2a8a0fc423
67 changed files with 400 additions and 217 deletions
|
|
@ -2393,7 +2393,7 @@ impl<'tcx> Operand<'tcx> {
|
|||
substs: SubstsRef<'tcx>,
|
||||
span: Span,
|
||||
) -> Self {
|
||||
let ty = tcx.type_of(def_id).subst(tcx, substs);
|
||||
let ty = tcx.bound_type_of(def_id).subst(tcx, substs);
|
||||
Operand::Constant(Box::new(Constant {
|
||||
span,
|
||||
user_ty: None,
|
||||
|
|
|
|||
|
|
@ -202,7 +202,9 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
Rvalue::Aggregate(ref ak, ref ops) => match **ak {
|
||||
AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64),
|
||||
AggregateKind::Tuple => tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))),
|
||||
AggregateKind::Adt(did, _, substs, _, _) => tcx.type_of(did).subst(tcx, substs),
|
||||
AggregateKind::Adt(did, _, substs, _, _) => {
|
||||
tcx.bound_type_of(did).subst(tcx, substs)
|
||||
}
|
||||
AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs),
|
||||
AggregateKind::Generator(did, substs, movability) => {
|
||||
tcx.mk_generator(did, substs, movability)
|
||||
|
|
|
|||
|
|
@ -1603,7 +1603,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
pub fn caller_location_ty(self) -> Ty<'tcx> {
|
||||
self.mk_imm_ref(
|
||||
self.lifetimes.re_static,
|
||||
self.type_of(self.require_lang_item(LangItem::PanicLocation, None))
|
||||
self.bound_type_of(self.require_lang_item(LangItem::PanicLocation, None))
|
||||
.subst(self, self.mk_substs([self.lifetimes.re_static.into()].iter())),
|
||||
)
|
||||
}
|
||||
|
|
@ -2332,7 +2332,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
ty_param.into()
|
||||
} else {
|
||||
assert!(has_default);
|
||||
self.type_of(param.def_id).subst(self, substs).into()
|
||||
self.bound_type_of(param.def_id).subst(self, substs).into()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
|
||||
use crate::ty;
|
||||
use crate::ty::subst::{Subst, SubstsRef};
|
||||
use crate::ty::EarlyBinder;
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
|
@ -229,7 +230,11 @@ impl<'tcx> GenericPredicates<'tcx> {
|
|||
substs: SubstsRef<'tcx>,
|
||||
) -> InstantiatedPredicates<'tcx> {
|
||||
InstantiatedPredicates {
|
||||
predicates: self.predicates.iter().map(|(p, _)| p.subst(tcx, substs)).collect(),
|
||||
predicates: self
|
||||
.predicates
|
||||
.iter()
|
||||
.map(|(p, _)| EarlyBinder(*p).subst(tcx, substs))
|
||||
.collect(),
|
||||
spans: self.predicates.iter().map(|(_, sp)| *sp).collect(),
|
||||
}
|
||||
}
|
||||
|
|
@ -243,7 +248,9 @@ impl<'tcx> GenericPredicates<'tcx> {
|
|||
if let Some(def_id) = self.parent {
|
||||
tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs);
|
||||
}
|
||||
instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| p.subst(tcx, substs)));
|
||||
instantiated
|
||||
.predicates
|
||||
.extend(self.predicates.iter().map(|(p, _)| EarlyBinder(*p).subst(tcx, substs)));
|
||||
instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use crate::ty::print::{FmtPrinter, Printer};
|
||||
use crate::ty::subst::{InternalSubsts, Subst};
|
||||
use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable};
|
||||
use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::def::Namespace;
|
||||
use rustc_hir::def_id::{CrateNum, DefId};
|
||||
|
|
@ -558,7 +558,11 @@ impl<'tcx> Instance<'tcx> {
|
|||
where
|
||||
T: TypeFoldable<'tcx> + Copy,
|
||||
{
|
||||
if let Some(substs) = self.substs_for_mir_body() { v.subst(tcx, substs) } else { *v }
|
||||
if let Some(substs) = self.substs_for_mir_body() {
|
||||
EarlyBinder(*v).subst(tcx, substs)
|
||||
} else {
|
||||
*v
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
|||
use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
|
||||
use crate::ty::normalize_erasing_regions::NormalizationError;
|
||||
use crate::ty::subst::Subst;
|
||||
use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
|
||||
use crate::ty::{self, subst::SubstsRef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_ast as ast;
|
||||
use rustc_attr as attr;
|
||||
use rustc_hir as hir;
|
||||
|
|
@ -1706,7 +1706,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
|
||||
use SavedLocalEligibility::*;
|
||||
let tcx = self.tcx;
|
||||
let subst_field = |ty: Ty<'tcx>| ty.subst(tcx, substs);
|
||||
let subst_field = |ty: Ty<'tcx>| EarlyBinder(ty).subst(tcx, substs);
|
||||
|
||||
let Some(info) = tcx.generator_layout(def_id) else {
|
||||
return Err(LayoutError::Unknown(ty));
|
||||
|
|
@ -2750,7 +2750,7 @@ impl<'tcx> ty::Instance<'tcx> {
|
|||
// track of a polymorphization `ParamEnv` to allow normalizing later.
|
||||
let mut sig = match *ty.kind() {
|
||||
ty::FnDef(def_id, substs) => tcx
|
||||
.normalize_erasing_regions(tcx.param_env(def_id), tcx.fn_sig(def_id))
|
||||
.normalize_erasing_regions(tcx.param_env(def_id), tcx.bound_fn_sig(def_id))
|
||||
.subst(tcx, substs),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ pub use self::sty::RegionKind::*;
|
|||
pub use self::sty::TyKind::*;
|
||||
pub use self::sty::{
|
||||
Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind,
|
||||
CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion,
|
||||
CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBinder, EarlyBoundRegion,
|
||||
ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig,
|
||||
GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, InlineConstSubstsParts, ParamConst,
|
||||
ParamTy, PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig,
|
||||
|
|
@ -735,7 +735,7 @@ impl<'tcx> Predicate<'tcx> {
|
|||
let shifted_pred =
|
||||
tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
|
||||
// 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
|
||||
let new = shifted_pred.subst(tcx, trait_ref.skip_binder().substs);
|
||||
let new = EarlyBinder(shifted_pred).subst(tcx, trait_ref.skip_binder().substs);
|
||||
// 3) ['x] + ['b] -> ['x, 'b]
|
||||
let bound_vars =
|
||||
tcx.mk_bound_variable_kinds(trait_bound_vars.iter().chain(pred_bound_vars));
|
||||
|
|
@ -1931,7 +1931,7 @@ impl<'tcx> FieldDef {
|
|||
/// Returns the type of this field. The resulting type is not normalized. The `subst` is
|
||||
/// typically obtained via the second field of [`TyKind::Adt`].
|
||||
pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
|
||||
tcx.type_of(self.did).subst(tcx, subst)
|
||||
tcx.bound_type_of(self.did).subst(tcx, subst)
|
||||
}
|
||||
|
||||
/// Computes the `Ident` of this variant by looking up the `Span`
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::mir;
|
|||
use crate::traits::query::NoSolution;
|
||||
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder};
|
||||
use crate::ty::subst::{Subst, SubstsRef};
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use crate::ty::{self, EarlyBinder, Ty, TyCtxt};
|
||||
|
||||
#[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)]
|
||||
pub enum NormalizationError<'tcx> {
|
||||
|
|
@ -133,7 +133,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
param_env={:?})",
|
||||
param_substs, value, param_env,
|
||||
);
|
||||
let substituted = value.subst(self, param_substs);
|
||||
let substituted = EarlyBinder(value).subst(self, param_substs);
|
||||
self.normalize_erasing_regions(param_env, substituted)
|
||||
}
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
param_env={:?})",
|
||||
param_substs, value, param_env,
|
||||
);
|
||||
let substituted = value.subst(self, param_substs);
|
||||
let substituted = EarlyBinder(value).subst(self, param_substs);
|
||||
self.try_normalize_erasing_regions(param_env, substituted)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,12 +115,16 @@ pub trait Printer<'tcx>: Sized {
|
|||
|
||||
DefPathData::Impl => {
|
||||
let generics = self.tcx().generics_of(def_id);
|
||||
let mut self_ty = self.tcx().type_of(def_id);
|
||||
let mut impl_trait_ref = self.tcx().impl_trait_ref(def_id);
|
||||
if substs.len() >= generics.count() {
|
||||
self_ty = self_ty.subst(self.tcx(), substs);
|
||||
impl_trait_ref = impl_trait_ref.subst(self.tcx(), substs);
|
||||
}
|
||||
let self_ty = self.tcx().bound_type_of(def_id);
|
||||
let impl_trait_ref = self.tcx().bound_impl_trait_ref(def_id);
|
||||
let (self_ty, impl_trait_ref) = if substs.len() >= generics.count() {
|
||||
(
|
||||
self_ty.subst(self.tcx(), substs),
|
||||
impl_trait_ref.map(|i| i.subst(self.tcx(), substs)),
|
||||
)
|
||||
} else {
|
||||
(self_ty.0, impl_trait_ref.map(|i| i.0))
|
||||
};
|
||||
self.print_impl_path(def_id, substs, self_ty, impl_trait_ref)
|
||||
}
|
||||
|
||||
|
|
@ -203,7 +207,7 @@ pub trait Printer<'tcx>: Sized {
|
|||
has_default
|
||||
&& substs[param.index as usize]
|
||||
== GenericArg::from(
|
||||
self.tcx().type_of(param.def_id).subst(self.tcx(), substs),
|
||||
self.tcx().bound_type_of(param.def_id).subst(self.tcx(), substs),
|
||||
)
|
||||
}
|
||||
ty::GenericParamDefKind::Const { has_default } => {
|
||||
|
|
|
|||
|
|
@ -587,7 +587,7 @@ pub trait PrettyPrinter<'tcx>:
|
|||
p!(")")
|
||||
}
|
||||
ty::FnDef(def_id, substs) => {
|
||||
let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
|
||||
let sig = self.tcx().bound_fn_sig(def_id).subst(self.tcx(), substs);
|
||||
p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
|
||||
}
|
||||
ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
|
||||
|
|
@ -774,13 +774,13 @@ pub trait PrettyPrinter<'tcx>:
|
|||
|
||||
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
|
||||
// by looking up the projections associated with the def_id.
|
||||
let bounds = self.tcx().explicit_item_bounds(def_id);
|
||||
let bounds = self.tcx().bound_explicit_item_bounds(def_id);
|
||||
|
||||
let mut traits = BTreeMap::new();
|
||||
let mut fn_traits = BTreeMap::new();
|
||||
let mut is_sized = false;
|
||||
|
||||
for (predicate, _) in bounds {
|
||||
for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
|
||||
let predicate = predicate.subst(self.tcx(), substs);
|
||||
let bound_predicate = predicate.kind();
|
||||
|
||||
|
|
|
|||
|
|
@ -159,7 +159,8 @@ pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>(
|
|||
let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| {
|
||||
let variance = variances[i];
|
||||
let variance_info = if variance == ty::Invariant {
|
||||
let ty = *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst));
|
||||
let ty =
|
||||
*cached_ty.get_or_insert_with(|| tcx.bound_type_of(ty_def_id).subst(tcx, a_subst));
|
||||
ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
|
||||
} else {
|
||||
ty::VarianceDiagInfo::default()
|
||||
|
|
|
|||
|
|
@ -860,6 +860,27 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::EarlyBinder<T> {
|
||||
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
self.try_map_bound(|ty| ty.try_fold_with(folder))
|
||||
}
|
||||
|
||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
self.try_map_bound(|ty| ty.try_fold_with(folder))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.as_ref().0.visit_with(visitor)
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.as_ref().0.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> {
|
||||
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -713,7 +713,9 @@ impl<'tcx> GeneratorSubsts<'tcx> {
|
|||
) -> impl Iterator<Item = impl Iterator<Item = Ty<'tcx>> + Captures<'tcx>> {
|
||||
let layout = tcx.generator_layout(def_id).unwrap();
|
||||
layout.variant_fields.iter().map(move |variant| {
|
||||
variant.iter().map(move |field| layout.field_tys[*field].subst(tcx, self.substs))
|
||||
variant
|
||||
.iter()
|
||||
.map(move |field| EarlyBinder(layout.field_tys[*field]).subst(tcx, self.substs))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1068,6 +1070,69 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
#[derive(Encodable, Decodable, HashStable)]
|
||||
pub struct EarlyBinder<T>(pub T);
|
||||
|
||||
impl<T> EarlyBinder<T> {
|
||||
pub fn as_ref(&self) -> EarlyBinder<&T> {
|
||||
EarlyBinder(&self.0)
|
||||
}
|
||||
|
||||
pub fn map_bound_ref<F, U>(&self, f: F) -> EarlyBinder<U>
|
||||
where
|
||||
F: FnOnce(&T) -> U,
|
||||
{
|
||||
self.as_ref().map_bound(f)
|
||||
}
|
||||
|
||||
pub fn map_bound<F, U>(self, f: F) -> EarlyBinder<U>
|
||||
where
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
let value = f(self.0);
|
||||
EarlyBinder(value)
|
||||
}
|
||||
|
||||
pub fn try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E>
|
||||
where
|
||||
F: FnOnce(T) -> Result<U, E>,
|
||||
{
|
||||
let value = f(self.0)?;
|
||||
Ok(EarlyBinder(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> EarlyBinder<Option<T>> {
|
||||
pub fn transpose(self) -> Option<EarlyBinder<T>> {
|
||||
self.0.map(|v| EarlyBinder(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> EarlyBinder<(T, U)> {
|
||||
pub fn transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>) {
|
||||
(EarlyBinder(self.0.0), EarlyBinder(self.0.1))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EarlyBinderIter<T> {
|
||||
t: T,
|
||||
}
|
||||
|
||||
impl<T: IntoIterator> EarlyBinder<T> {
|
||||
pub fn transpose_iter(self) -> EarlyBinderIter<T::IntoIter> {
|
||||
EarlyBinderIter { t: self.0.into_iter() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Iterator> Iterator for EarlyBinderIter<T> {
|
||||
type Item = EarlyBinder<T::Item>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.t.next().map(|i| EarlyBinder(i))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable)]
|
||||
pub enum BoundVariableKind {
|
||||
|
|
@ -2139,7 +2204,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
|
||||
pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
|
||||
match self.kind() {
|
||||
FnDef(def_id, substs) => tcx.fn_sig(*def_id).subst(tcx, substs),
|
||||
FnDef(def_id, substs) => tcx.bound_fn_sig(*def_id).subst(tcx, substs),
|
||||
FnPtr(f) => *f,
|
||||
Error(_) => {
|
||||
// ignore errors (#54954)
|
||||
|
|
@ -2306,7 +2371,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
ty::Str | ty::Slice(_) => (tcx.types.usize, false),
|
||||
ty::Dynamic(..) => {
|
||||
let dyn_metadata = tcx.lang_items().dyn_metadata().unwrap();
|
||||
(tcx.type_of(dyn_metadata).subst(tcx, &[tail.into()]), false)
|
||||
(tcx.bound_type_of(dyn_metadata).subst(tcx, &[tail.into()]), false)
|
||||
},
|
||||
|
||||
// type parameters only have unit metadata if they're sized, so return true
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use crate::mir;
|
|||
use crate::ty::codec::{TyDecoder, TyEncoder};
|
||||
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeVisitor};
|
||||
use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
|
||||
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
|
||||
use crate::ty::{self, EarlyBinder, Lift, List, ParamConst, Ty, TyCtxt};
|
||||
|
||||
use rustc_data_structures::intern::{Interned, WithStableHash};
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
|
@ -499,14 +499,19 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
|
|||
}
|
||||
|
||||
// Just call `foo.subst(tcx, substs)` to perform a substitution across `foo`.
|
||||
#[rustc_on_unimplemented(message = "Calling `subst` must now be done through an `EarlyBinder`")]
|
||||
pub trait Subst<'tcx>: Sized {
|
||||
fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> Self;
|
||||
type Inner;
|
||||
|
||||
fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> Self::Inner;
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> Subst<'tcx> for T {
|
||||
fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> T {
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> Subst<'tcx> for EarlyBinder<T> {
|
||||
type Inner = T;
|
||||
|
||||
fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> Self::Inner {
|
||||
let mut folder = SubstFolder { tcx, substs, binders_passed: 0 };
|
||||
self.fold_with(&mut folder)
|
||||
self.0.fold_with(&mut folder)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ use crate::ty::layout::IntegerExt;
|
|||
use crate::ty::query::TyCtxtAt;
|
||||
use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
|
||||
use crate::ty::{
|
||||
self, Const, DebruijnIndex, DefIdTree, List, ReEarlyBound, Ty, TyCtxt, TyKind::*, TypeFoldable,
|
||||
self, Const, DebruijnIndex, DefIdTree, EarlyBinder, List, ReEarlyBound, Ty, TyCtxt, TyKind::*,
|
||||
TypeFoldable,
|
||||
};
|
||||
use rustc_apfloat::Float as _;
|
||||
use rustc_ast as ast;
|
||||
|
|
@ -591,6 +592,32 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
trace!(?expanded_type);
|
||||
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
|
||||
}
|
||||
|
||||
pub fn bound_type_of(self, def_id: DefId) -> EarlyBinder<Ty<'tcx>> {
|
||||
EarlyBinder(self.type_of(def_id))
|
||||
}
|
||||
|
||||
pub fn bound_fn_sig(self, def_id: DefId) -> EarlyBinder<ty::PolyFnSig<'tcx>> {
|
||||
EarlyBinder(self.fn_sig(def_id))
|
||||
}
|
||||
|
||||
pub fn bound_impl_trait_ref(self, def_id: DefId) -> Option<EarlyBinder<ty::TraitRef<'tcx>>> {
|
||||
self.impl_trait_ref(def_id).map(|i| EarlyBinder(i))
|
||||
}
|
||||
|
||||
pub fn bound_explicit_item_bounds(
|
||||
self,
|
||||
def_id: DefId,
|
||||
) -> EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> {
|
||||
EarlyBinder(self.explicit_item_bounds(def_id))
|
||||
}
|
||||
|
||||
pub fn bound_item_bounds(
|
||||
self,
|
||||
def_id: DefId,
|
||||
) -> EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
|
||||
EarlyBinder(self.item_bounds(def_id))
|
||||
}
|
||||
}
|
||||
|
||||
struct OpaqueTypeExpander<'tcx> {
|
||||
|
|
@ -622,7 +649,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
|
|||
let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
|
||||
Some(expanded_ty) => *expanded_ty,
|
||||
None => {
|
||||
let generic_ty = self.tcx.type_of(def_id);
|
||||
let generic_ty = self.tcx.bound_type_of(def_id);
|
||||
let concrete_ty = generic_ty.subst(self.tcx, substs);
|
||||
let expanded_ty = self.fold_ty(concrete_ty);
|
||||
self.expanded_cache.insert((def_id, substs), expanded_ty);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue