Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/coerce.rs')
-rw-r--r--crates/hir-ty/src/infer/coerce.rs623
1 files changed, 357 insertions, 266 deletions
diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs
index 7930d8b0ed..df24148920 100644
--- a/crates/hir-ty/src/infer/coerce.rs
+++ b/crates/hir-ty/src/infer/coerce.rs
@@ -35,48 +35,60 @@
//! // and are then unable to coerce `&7i32` to `&mut i32`.
//! ```
-use chalk_ir::cast::Cast;
use hir_def::{
CallableDefId,
+ attrs::AttrFlags,
hir::{ExprId, ExprOrPatId},
- lang_item::LangItem,
signatures::FunctionSignature,
};
-use intern::sym;
use rustc_ast_ir::Mutability;
use rustc_type_ir::{
- TypeAndMut,
+ BoundVar, DebruijnIndex, TyVid, TypeAndMut, TypeFoldable, TypeFolder, TypeSuperFoldable,
+ TypeVisitableExt,
error::TypeError,
- inherent::{IntoKind, Safety, Ty as _},
+ inherent::{Const as _, GenericArg as _, IntoKind, Safety, SliceLike, Ty as _},
};
use smallvec::{SmallVec, smallvec};
use tracing::{debug, instrument};
use triomphe::Arc;
use crate::{
- Adjust, Adjustment, AutoBorrow, Interner, PointerCast, TargetFeatures, TraitEnvironment,
+ Adjust, Adjustment, AutoBorrow, PointerCast, TargetFeatures, TraitEnvironment,
autoderef::Autoderef,
db::{HirDatabase, InternedClosureId},
- infer::{AllowTwoPhase, InferenceContext, TypeMismatch, unify::InferenceTable},
+ infer::{
+ AllowTwoPhase, AutoBorrowMutability, InferenceContext, TypeMismatch, expr::ExprIsRead,
+ },
next_solver::{
- Binder, CallableIdWrapper, ClauseKind, CoercePredicate, DbInterner, ErrorGuaranteed,
- GenericArgs, PolyFnSig, PredicateKind, Region, SolverDefId, TraitRef, Ty, TyKind,
+ Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, CallableIdWrapper,
+ Canonical, ClauseKind, CoercePredicate, Const, ConstKind, DbInterner, ErrorGuaranteed,
+ GenericArgs, PolyFnSig, PredicateKind, Region, RegionKind, TraitRef, Ty, TyKind,
+ TypingMode,
infer::{
- DefineOpaqueTypes, InferCtxt, InferOk, InferResult,
+ DbInternerInferExt, InferCtxt, InferOk, InferResult,
relate::RelateResult,
select::{ImplSource, SelectionError},
traits::{Obligation, ObligationCause, PredicateObligation, PredicateObligations},
},
- mapping::{ChalkToNextSolver, NextSolverToChalk},
obligation_ctxt::ObligationCtxt,
},
utils::TargetFeatureIsSafeInTarget,
};
-struct Coerce<'a, 'b, 'db> {
- table: &'a mut InferenceTable<'db>,
- has_errors: &'a mut bool,
- target_features: &'a mut dyn FnMut() -> (&'b TargetFeatures, TargetFeatureIsSafeInTarget),
+trait CoerceDelegate<'db> {
+ fn infcx(&self) -> &InferCtxt<'db>;
+ fn env(&self) -> &TraitEnvironment<'db>;
+ fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget);
+
+ fn set_diverging(&mut self, diverging_ty: Ty<'db>);
+
+ fn set_tainted_by_errors(&mut self);
+
+ fn type_var_is_sized(&mut self, var: TyVid) -> bool;
+}
+
+struct Coerce<D> {
+ delegate: D,
use_lub: bool,
/// Determines whether or not allow_two_phase_borrow is set on any
/// autoref adjustments we create while coercing. We don't want to
@@ -93,7 +105,7 @@ struct Coerce<'a, 'b, 'db> {
cause: ObligationCause,
}
-type CoerceResult<'db> = InferResult<'db, (Vec<Adjustment>, Ty<'db>)>;
+type CoerceResult<'db> = InferResult<'db, (Vec<Adjustment<'db>>, Ty<'db>)>;
/// Coercing a mutable reference to an immutable works, while
/// coercing `&T` to `&mut T` should be forbidden.
@@ -103,53 +115,66 @@ fn coerce_mutbls<'db>(from_mutbl: Mutability, to_mutbl: Mutability) -> RelateRes
/// This always returns `Ok(...)`.
fn success<'db>(
- adj: Vec<Adjustment>,
+ adj: Vec<Adjustment<'db>>,
target: Ty<'db>,
obligations: PredicateObligations<'db>,
) -> CoerceResult<'db> {
Ok(InferOk { value: (adj, target), obligations })
}
-impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
+impl<'db, D> Coerce<D>
+where
+ D: CoerceDelegate<'db>,
+{
#[inline]
fn set_tainted_by_errors(&mut self) {
- *self.has_errors = true;
+ self.delegate.set_tainted_by_errors();
+ }
+
+ #[inline]
+ fn infcx(&self) -> &InferCtxt<'db> {
+ self.delegate.infcx()
+ }
+
+ #[inline]
+ fn env(&self) -> &TraitEnvironment<'db> {
+ self.delegate.env()
}
#[inline]
fn interner(&self) -> DbInterner<'db> {
- self.table.interner
+ self.infcx().interner
}
#[inline]
- fn infer_ctxt(&self) -> &InferCtxt<'db> {
- &self.table.infer_ctxt
+ fn db(&self) -> &'db dyn HirDatabase {
+ self.interner().db
}
pub(crate) fn commit_if_ok<T, E>(
&mut self,
f: impl FnOnce(&mut Self) -> Result<T, E>,
) -> Result<T, E> {
- let snapshot = self.table.snapshot();
+ let snapshot = self.infcx().start_snapshot();
let result = f(self);
match result {
Ok(_) => {}
Err(_) => {
- self.table.rollback_to(snapshot);
+ self.infcx().rollback_to(snapshot);
}
}
result
}
- fn unify_raw(&mut self, a: Ty<'db>, b: Ty<'db>) -> InferResult<'db, Ty<'db>> {
+ fn unify_raw(&self, a: Ty<'db>, b: Ty<'db>) -> InferResult<'db, Ty<'db>> {
debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub);
- self.commit_if_ok(|this| {
- let at = this.infer_ctxt().at(&this.cause, this.table.param_env);
+ self.infcx().commit_if_ok(|_| {
+ let at = self.infcx().at(&self.cause, self.env().env);
- let res = if this.use_lub {
+ let res = if self.use_lub {
at.lub(b, a)
} else {
- at.sup(DefineOpaqueTypes::Yes, b, a)
+ at.sup(b, a)
.map(|InferOk { value: (), obligations }| InferOk { value: b, obligations })
};
@@ -158,9 +183,9 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
// Filter these cases out to make sure our coercion is more accurate.
match res {
Ok(InferOk { value, obligations }) => {
- let mut ocx = ObligationCtxt::new(this.infer_ctxt());
+ let mut ocx = ObligationCtxt::new(self.infcx());
ocx.register_obligations(obligations);
- if ocx.select_where_possible().is_empty() {
+ if ocx.try_evaluate_obligations().is_empty() {
Ok(InferOk { value, obligations: ocx.into_pending_obligations() })
} else {
Err(TypeError::Mismatch)
@@ -182,17 +207,14 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
&mut self,
a: Ty<'db>,
b: Ty<'db>,
- adjustments: impl IntoIterator<Item = Adjustment>,
+ adjustments: impl IntoIterator<Item = Adjustment<'db>>,
final_adjustment: Adjust,
) -> CoerceResult<'db> {
self.unify_raw(a, b).and_then(|InferOk { value: ty, obligations }| {
success(
adjustments
.into_iter()
- .chain(std::iter::once(Adjustment {
- target: ty.to_chalk(self.interner()),
- kind: final_adjustment,
- }))
+ .chain(std::iter::once(Adjustment { target: ty, kind: final_adjustment }))
.collect(),
ty,
obligations,
@@ -203,24 +225,20 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
#[instrument(skip(self))]
fn coerce(&mut self, a: Ty<'db>, b: Ty<'db>) -> CoerceResult<'db> {
// First, remove any resolved type variables (at the top level, at least):
- let a = self.table.shallow_resolve(a);
- let b = self.table.shallow_resolve(b);
+ let a = self.infcx().shallow_resolve(a);
+ let b = self.infcx().shallow_resolve(b);
debug!("Coerce.tys({:?} => {:?})", a, b);
// Coercing from `!` to any type is allowed:
if a.is_never() {
// If we're coercing into an inference var, mark it as possibly diverging.
- // FIXME: rustc does this differently.
- if let TyKind::Infer(rustc_type_ir::TyVar(b)) = b.kind() {
- self.table.set_diverging(b.as_u32().into(), chalk_ir::TyVariableKind::General);
+ if b.is_infer() {
+ self.delegate.set_diverging(b);
}
if self.coerce_never {
return success(
- vec![Adjustment {
- kind: Adjust::NeverToAny,
- target: b.to_chalk(self.interner()),
- }],
+ vec![Adjustment { kind: Adjust::NeverToAny, target: b }],
b,
PredicateObligations::new(),
);
@@ -230,25 +248,6 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
}
}
- // If we are coercing into a TAIT, coerce into its proxy inference var, instead.
- // FIXME(next-solver): This should not be here. This is not how rustc does thing, and it also not allows us
- // to normalize opaques defined in our scopes. Instead, we should properly register
- // `TypingMode::Analysis::defining_opaque_types_and_generators`, and rely on the solver to reveal
- // them for us (we'll also need some global-like registry for the values, something we cannot
- // really implement, therefore we can really support only RPITs and ITIAT or the new `#[define_opaque]`
- // TAIT, not the old global TAIT).
- let mut b = b;
- if let Some(tait_table) = &self.table.tait_coercion_table
- && let TyKind::Alias(rustc_type_ir::Opaque, opaque_ty) = b.kind()
- && let SolverDefId::InternedOpaqueTyId(opaque_ty_id) = opaque_ty.def_id
- && !matches!(a.kind(), TyKind::Infer(..) | TyKind::Alias(rustc_type_ir::Opaque, _))
- && let Some(ty) = tait_table.get(&opaque_ty_id.into())
- {
- b = ty.to_nextsolver(self.interner());
- b = self.table.shallow_resolve(b);
- }
- let b = b;
-
// Coercing *from* an unresolved inference variable means that
// we have no information about the source type. This will always
// ultimately fall back to some form of subtyping.
@@ -317,12 +316,12 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
/// fall back to subtyping (`unify_and`).
fn coerce_from_inference_variable(&mut self, a: Ty<'db>, b: Ty<'db>) -> CoerceResult<'db> {
debug!("coerce_from_inference_variable(a={:?}, b={:?})", a, b);
- debug_assert!(a.is_infer() && self.table.shallow_resolve(a) == a);
- debug_assert!(self.table.shallow_resolve(b) == b);
+ debug_assert!(a.is_infer() && self.infcx().shallow_resolve(a) == a);
+ debug_assert!(self.infcx().shallow_resolve(b) == b);
if b.is_infer() {
// Two unresolved type variables: create a `Coerce` predicate.
- let target_ty = if self.use_lub { self.table.next_ty_var() } else { b };
+ let target_ty = if self.use_lub { self.infcx().next_ty_var() } else { b };
let mut obligations = PredicateObligations::with_capacity(2);
for &source_ty in &[a, b] {
@@ -330,7 +329,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
obligations.push(Obligation::new(
self.interner(),
self.cause.clone(),
- self.table.param_env,
+ self.env().env,
Binder::dummy(PredicateKind::Coerce(CoercePredicate {
a: source_ty,
b: target_ty,
@@ -362,8 +361,8 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
mutbl_b: Mutability,
) -> CoerceResult<'db> {
debug!("coerce_borrowed_pointer(a={:?}, b={:?})", a, b);
- debug_assert!(self.table.shallow_resolve(a) == a);
- debug_assert!(self.table.shallow_resolve(b) == b);
+ debug_assert!(self.infcx().shallow_resolve(a) == a);
+ debug_assert!(self.infcx().shallow_resolve(b) == b);
// If we have a parameter of type `&M T_a` and the value
// provided is `expr`, we will be adding an implicit borrow,
@@ -382,10 +381,10 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
let mut first_error = None;
let mut r_borrow_var = None;
- let mut autoderef = Autoderef::new(self.table, a);
+ let mut autoderef = Autoderef::new_with_tracking(self.infcx(), self.env(), a);
let mut found = None;
- while let Some((referent_ty, autoderefs)) = autoderef.next() {
+ for (referent_ty, autoderefs) in autoderef.by_ref() {
if autoderefs == 0 {
// Don't let this pass, otherwise it would cause
// &T to autoref to &&T.
@@ -469,28 +468,18 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
} else {
if r_borrow_var.is_none() {
// create var lazily, at most once
- let r = autoderef.table.next_region_var();
+ let r = self.infcx().next_region_var();
r_borrow_var = Some(r); // [4] above
}
r_borrow_var.unwrap()
};
let derefd_ty_a = Ty::new_ref(
- autoderef.table.interner,
+ self.interner(),
r,
referent_ty,
mutbl_b, // [1] above
);
- // We need to construct a new `Coerce` because of lifetimes.
- let mut coerce = Coerce {
- table: autoderef.table,
- has_errors: self.has_errors,
- target_features: self.target_features,
- use_lub: self.use_lub,
- allow_two_phase: self.allow_two_phase,
- coerce_never: self.coerce_never,
- cause: self.cause.clone(),
- };
- match coerce.unify_raw(derefd_ty_a, b) {
+ match self.unify_raw(derefd_ty_a, b) {
Ok(ok) => {
found = Some(ok);
break;
@@ -542,18 +531,9 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
autoderef.adjust_steps_as_infer_ok();
obligations.extend(o);
- // Now apply the autoref. We have to extract the region out of
- // the final ref type we got.
- let TyKind::Ref(region, _, _) = ty.kind() else {
- panic!("expected a ref type, got {:?}", ty);
- };
- adjustments.push(Adjustment {
- kind: Adjust::Borrow(AutoBorrow::Ref(
- region.to_chalk(self.interner()),
- mutbl_b.to_chalk(self.interner()),
- )),
- target: ty.to_chalk(self.interner()),
- });
+ // Now apply the autoref.
+ let mutbl = AutoBorrowMutability::new(mutbl_b, self.allow_two_phase);
+ adjustments.push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)), target: ty });
debug!("coerce_borrowed_pointer: succeeded ty={:?} adjustments={:?}", ty, adjustments);
@@ -568,8 +548,8 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
#[instrument(skip(self), level = "debug")]
fn coerce_unsized(&mut self, source: Ty<'db>, target: Ty<'db>) -> CoerceResult<'db> {
debug!(?source, ?target);
- debug_assert!(self.table.shallow_resolve(source) == source);
- debug_assert!(self.table.shallow_resolve(target) == target);
+ debug_assert!(self.infcx().shallow_resolve(source) == source);
+ debug_assert!(self.infcx().shallow_resolve(target) == target);
// We don't apply any coercions incase either the source or target
// aren't sufficiently well known but tend to instead just equate
@@ -631,10 +611,8 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
return Err(TypeError::Mismatch);
}
- let traits = (
- LangItem::Unsize.resolve_trait(self.table.db, self.table.trait_env.krate),
- LangItem::CoerceUnsized.resolve_trait(self.table.db, self.table.trait_env.krate),
- );
+ let lang_items = self.interner().lang_items();
+ let traits = (lang_items.Unsize, lang_items.CoerceUnsized);
let (Some(unsize_did), Some(coerce_unsized_did)) = traits else {
debug!("missing Unsize or CoerceUnsized traits");
return Err(TypeError::Mismatch);
@@ -650,26 +628,18 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
(TyKind::Ref(_, ty_a, mutbl_a), TyKind::Ref(_, _, mutbl_b)) => {
coerce_mutbls(mutbl_a, mutbl_b)?;
- let r_borrow = self.table.next_region_var();
+ let r_borrow = self.infcx().next_region_var();
// We don't allow two-phase borrows here, at least for initial
// implementation. If it happens that this coercion is a function argument,
// the reborrow in coerce_borrowed_ptr will pick it up.
- // let mutbl = AutoBorrowMutability::new(mutbl_b, AllowTwoPhase::No);
- let mutbl = mutbl_b.to_chalk(self.interner());
+ let mutbl = AutoBorrowMutability::new(mutbl_b, AllowTwoPhase::No);
Some((
+ Adjustment { kind: Adjust::Deref(None), target: ty_a },
Adjustment {
- kind: Adjust::Deref(None),
- target: ty_a.to_chalk(self.interner()),
- },
- Adjustment {
- kind: Adjust::Borrow(AutoBorrow::Ref(
- r_borrow.to_chalk(self.interner()),
- mutbl,
- )),
- target: Ty::new_ref(self.interner(), r_borrow, ty_a, mutbl_b)
- .to_chalk(self.interner()),
+ kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
+ target: Ty::new_ref(self.interner(), r_borrow, ty_a, mutbl_b),
},
))
}
@@ -677,26 +647,22 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
coerce_mutbls(mt_a, mt_b)?;
Some((
+ Adjustment { kind: Adjust::Deref(None), target: ty_a },
Adjustment {
- kind: Adjust::Deref(None),
- target: ty_a.to_chalk(self.interner()),
- },
- Adjustment {
- kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b.to_chalk(self.interner()))),
- target: Ty::new_ptr(self.interner(), ty_a, mt_b).to_chalk(self.interner()),
+ kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b)),
+ target: Ty::new_ptr(self.interner(), ty_a, mt_b),
},
))
}
_ => None,
};
- let coerce_source =
- reborrow.as_ref().map_or(source, |(_, r)| r.target.to_nextsolver(self.interner()));
+ let coerce_source = reborrow.as_ref().map_or(source, |(_, r)| r.target);
// Setup either a subtyping or a LUB relationship between
// the `CoerceUnsized` target type and the expected type.
// We only have the latter, so we use an inference variable
// for the former and let type inference do the rest.
- let coerce_target = self.table.next_ty_var();
+ let coerce_target = self.infcx().next_ty_var();
let mut coercion = self.unify_and(
coerce_target,
@@ -718,7 +684,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
let mut queue: SmallVec<[PredicateObligation<'db>; 4]> = smallvec![Obligation::new(
self.interner(),
cause,
- self.table.param_env,
+ self.env().env,
TraitRef::new(
self.interner(),
coerce_unsized_did.into(),
@@ -735,16 +701,16 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
Some(PredicateKind::Clause(ClauseKind::Trait(trait_pred)))
if traits.contains(&trait_pred.def_id().0) =>
{
- self.infer_ctxt().resolve_vars_if_possible(trait_pred)
+ self.infcx().resolve_vars_if_possible(trait_pred)
}
// Eagerly process alias-relate obligations in new trait solver,
// since these can be emitted in the process of solving trait goals,
// but we need to constrain vars before processing goals mentioning
// them.
Some(PredicateKind::AliasRelate(..)) => {
- let mut ocx = ObligationCtxt::new(self.infer_ctxt());
+ let mut ocx = ObligationCtxt::new(self.infcx());
ocx.register_obligation(obligation);
- if !ocx.select_where_possible().is_empty() {
+ if !ocx.try_evaluate_obligations().is_empty() {
return Err(TypeError::Mismatch);
}
coercion.obligations.extend(ocx.into_pending_obligations());
@@ -756,7 +722,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
}
};
debug!("coerce_unsized resolve step: {:?}", trait_pred);
- match self.infer_ctxt().select(&obligation.with(self.interner(), trait_pred)) {
+ match self.infcx().select(&obligation.with(self.interner(), trait_pred)) {
// Uncertain or unimplemented.
Ok(None) => {
if trait_pred.def_id().0 == unsize_did {
@@ -765,7 +731,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_pred);
match (self_ty.kind(), unsize_ty.kind()) {
(TyKind::Infer(rustc_type_ir::TyVar(v)), TyKind::Dynamic(..))
- if self.table.type_var_is_sized(v) =>
+ if self.delegate.type_var_is_sized(v) =>
{
debug!("coerce_unsized: have sized infer {:?}", v);
coercion.obligations.push(obligation);
@@ -837,7 +803,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
b: Ty<'db>,
adjustment: Option<Adjust>,
) -> CoerceResult<'db> {
- debug_assert!(self.table.shallow_resolve(b) == b);
+ debug_assert!(self.infcx().shallow_resolve(b) == b);
self.commit_if_ok(|this| {
if let TyKind::FnPtr(_, hdr_b) = b.kind()
@@ -850,7 +816,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
b,
adjustment.map(|kind| Adjustment {
kind,
- target: Ty::new_fn_ptr(this.interner(), fn_ty_a).to_chalk(this.interner()),
+ target: Ty::new_fn_ptr(this.interner(), fn_ty_a),
}),
Adjust::Pointer(PointerCast::UnsafeFnPointer),
)
@@ -866,15 +832,15 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
fn coerce_from_fn_pointer(&mut self, fn_ty_a: PolyFnSig<'db>, b: Ty<'db>) -> CoerceResult<'db> {
debug!(?fn_ty_a, ?b, "coerce_from_fn_pointer");
- debug_assert!(self.table.shallow_resolve(b) == b);
+ debug_assert!(self.infcx().shallow_resolve(b) == b);
self.coerce_from_safe_fn(fn_ty_a, b, None)
}
fn coerce_from_fn_item(&mut self, a: Ty<'db>, b: Ty<'db>) -> CoerceResult<'db> {
debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
- debug_assert!(self.table.shallow_resolve(a) == a);
- debug_assert!(self.table.shallow_resolve(b) == b);
+ debug_assert!(self.infcx().shallow_resolve(a) == a);
+ debug_assert!(self.infcx().shallow_resolve(b) == b);
match b.kind() {
TyKind::FnPtr(_, b_hdr) => {
@@ -882,22 +848,22 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
if let TyKind::FnDef(def_id, _) = a.kind() {
// Intrinsics are not coercible to function pointers
if let CallableDefId::FunctionId(def_id) = def_id.0 {
- if FunctionSignature::is_intrinsic(self.table.db, def_id) {
+ if FunctionSignature::is_intrinsic(self.db(), def_id) {
return Err(TypeError::IntrinsicCast);
}
- let attrs = self.table.db.attrs(def_id.into());
- if attrs.by_key(sym::rustc_force_inline).exists() {
+ let attrs = AttrFlags::query(self.db(), def_id.into());
+ if attrs.contains(AttrFlags::RUSTC_FORCE_INLINE) {
return Err(TypeError::ForceInlineCast);
}
- if b_hdr.safety.is_safe() && attrs.by_key(sym::target_feature).exists() {
+ if b_hdr.safety.is_safe() && attrs.contains(AttrFlags::HAS_TARGET_FEATURE) {
let fn_target_features =
- TargetFeatures::from_attrs_no_implications(&attrs);
+ TargetFeatures::from_fn_no_implications(self.db(), def_id);
// Allow the coercion if the current function has all the features that would be
// needed to call the coercee safely.
let (target_features, target_feature_is_safe) =
- (self.target_features)();
+ self.delegate.target_features();
if target_feature_is_safe == TargetFeatureIsSafeInTarget::No
&& !target_features.enabled.is_superset(&fn_target_features.enabled)
{
@@ -928,8 +894,8 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
args_a: GenericArgs<'db>,
b: Ty<'db>,
) -> CoerceResult<'db> {
- debug_assert!(self.table.shallow_resolve(a) == a);
- debug_assert!(self.table.shallow_resolve(b) == b);
+ debug_assert!(self.infcx().shallow_resolve(a) == a);
+ debug_assert!(self.infcx().shallow_resolve(b) == b);
match b.kind() {
// FIXME: We need to have an `upvars_mentioned()` query:
@@ -962,9 +928,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
pointer_ty,
b,
[],
- Adjust::Pointer(PointerCast::ClosureFnPointer(
- safety.to_chalk(self.interner()),
- )),
+ Adjust::Pointer(PointerCast::ClosureFnPointer(safety)),
)
}
_ => self.unify(a, b),
@@ -973,8 +937,8 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
fn coerce_raw_ptr(&mut self, a: Ty<'db>, b: Ty<'db>, mutbl_b: Mutability) -> CoerceResult<'db> {
debug!("coerce_raw_ptr(a={:?}, b={:?})", a, b);
- debug_assert!(self.table.shallow_resolve(a) == a);
- debug_assert!(self.table.shallow_resolve(b) == b);
+ debug_assert!(self.infcx().shallow_resolve(a) == a);
+ debug_assert!(self.infcx().shallow_resolve(b) == b);
let (is_ref, mt_a) = match a.kind() {
TyKind::Ref(_, ty, mutbl) => (true, TypeAndMut::<DbInterner<'db>> { ty, mutbl }),
@@ -992,11 +956,8 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
self.unify_and(
a_raw,
b,
- [Adjustment {
- kind: Adjust::Deref(None),
- target: mt_a.ty.to_chalk(self.interner()),
- }],
- Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b.to_chalk(self.interner()))),
+ [Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }],
+ Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)),
)
} else if mt_a.mutbl != mutbl_b {
self.unify_and(a_raw, b, [], Adjust::Pointer(PointerCast::MutToConstPointer))
@@ -1006,13 +967,40 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
}
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub(crate) enum CoerceNever {
- No,
- Yes,
+struct InferenceCoercionDelegate<'a, 'b, 'db>(&'a mut InferenceContext<'b, 'db>);
+
+impl<'db> CoerceDelegate<'db> for InferenceCoercionDelegate<'_, '_, 'db> {
+ #[inline]
+ fn infcx(&self) -> &InferCtxt<'db> {
+ &self.0.table.infer_ctxt
+ }
+ #[inline]
+ fn env(&self) -> &TraitEnvironment<'db> {
+ &self.0.table.trait_env
+ }
+
+ #[inline]
+ fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget) {
+ self.0.target_features()
+ }
+
+ #[inline]
+ fn set_diverging(&mut self, diverging_ty: Ty<'db>) {
+ self.0.table.set_diverging(diverging_ty);
+ }
+
+ #[inline]
+ fn set_tainted_by_errors(&mut self) {
+ self.0.set_tainted_by_errors();
+ }
+
+ #[inline]
+ fn type_var_is_sized(&mut self, var: TyVid) -> bool {
+ self.0.table.type_var_is_sized(var)
+ }
}
-impl<'db> InferenceContext<'db> {
+impl<'db> InferenceContext<'_, 'db> {
/// Attempt to coerce an expression to a type, and return the
/// adjusted type of the expression, if successful.
/// Adjustments are only recorded if the coercion succeeded.
@@ -1023,24 +1011,26 @@ impl<'db> InferenceContext<'db> {
expr_ty: Ty<'db>,
mut target: Ty<'db>,
allow_two_phase: AllowTwoPhase,
- coerce_never: CoerceNever,
+ expr_is_read: ExprIsRead,
) -> RelateResult<'db, Ty<'db>> {
let source = self.table.try_structurally_resolve_type(expr_ty);
target = self.table.try_structurally_resolve_type(target);
debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
let cause = ObligationCause::new();
- let krate = self.krate();
+ let coerce_never = match expr {
+ ExprOrPatId::ExprId(idx) => {
+ self.expr_guaranteed_to_constitute_read_for_never(idx, expr_is_read)
+ }
+ // `PatId` is passed for `PatKind::Path`.
+ ExprOrPatId::PatId(_) => false,
+ };
let mut coerce = Coerce {
- table: &mut self.table,
- has_errors: &mut self.result.has_errors,
+ delegate: InferenceCoercionDelegate(self),
cause,
allow_two_phase,
- coerce_never: matches!(coerce_never, CoerceNever::Yes),
+ coerce_never,
use_lub: false,
- target_features: &mut || {
- Self::target_features(self.db, &self.target_features, self.owner, krate)
- },
};
let ok = coerce.commit_if_ok(|coerce| coerce.coerce(source, target))?;
@@ -1083,7 +1073,7 @@ impl<'db> InferenceContext<'db> {
let is_force_inline = |ty: Ty<'db>| {
if let TyKind::FnDef(CallableIdWrapper(CallableDefId::FunctionId(did)), _) = ty.kind() {
- self.db.attrs(did.into()).by_key(sym::rustc_force_inline).exists()
+ AttrFlags::query(self.db, did.into()).contains(AttrFlags::RUSTC_FORCE_INLINE)
} else {
false
}
@@ -1114,9 +1104,13 @@ impl<'db> InferenceContext<'db> {
match self.table.commit_if_ok(|table| {
// We need to eagerly handle nested obligations due to lazy norm.
let mut ocx = ObligationCtxt::new(&table.infer_ctxt);
- let value =
- ocx.lub(&ObligationCause::new(), table.param_env, prev_ty, new_ty)?;
- if ocx.select_where_possible().is_empty() {
+ let value = ocx.lub(
+ &ObligationCause::new(),
+ table.trait_env.env,
+ prev_ty,
+ new_ty,
+ )?;
+ if ocx.try_evaluate_obligations().is_empty() {
Ok(InferOk { value, obligations: ocx.into_pending_obligations() })
} else {
Err(TypeError::Mismatch)
@@ -1125,13 +1119,13 @@ impl<'db> InferenceContext<'db> {
// We have a LUB of prev_ty and new_ty, just return it.
Ok(ok) => return Ok(self.table.register_infer_ok(ok)),
Err(_) => (
- Some(prev_ty.fn_sig(self.table.interner)),
- Some(new_ty.fn_sig(self.table.interner)),
+ Some(prev_ty.fn_sig(self.table.interner())),
+ Some(new_ty.fn_sig(self.table.interner())),
),
}
}
(TyKind::Closure(_, args), TyKind::FnDef(..)) => {
- let b_sig = new_ty.fn_sig(self.table.interner);
+ let b_sig = new_ty.fn_sig(self.table.interner());
let a_sig = args.closure_sig_untupled().map_bound(|mut sig| {
sig.safety = b_sig.safety();
sig
@@ -1139,7 +1133,7 @@ impl<'db> InferenceContext<'db> {
(Some(a_sig), Some(b_sig))
}
(TyKind::FnDef(..), TyKind::Closure(_, args)) => {
- let a_sig = prev_ty.fn_sig(self.table.interner);
+ let a_sig = prev_ty.fn_sig(self.table.interner());
let b_sig = args.closure_sig_untupled().map_bound(|mut sig| {
sig.safety = a_sig.safety();
sig
@@ -1158,41 +1152,35 @@ impl<'db> InferenceContext<'db> {
let sig = self
.table
.infer_ctxt
- .at(&ObligationCause::new(), self.table.param_env)
+ .at(&ObligationCause::new(), self.table.trait_env.env)
.lub(a_sig, b_sig)
.map(|ok| self.table.register_infer_ok(ok))?;
// Reify both sides and return the reified fn pointer type.
- let fn_ptr = Ty::new_fn_ptr(self.table.interner, sig);
+ let fn_ptr = Ty::new_fn_ptr(self.table.interner(), sig);
let prev_adjustment = match prev_ty.kind() {
- TyKind::Closure(..) => Adjust::Pointer(PointerCast::ClosureFnPointer(
- a_sig.safety().to_chalk(self.table.interner),
- )),
+ TyKind::Closure(..) => {
+ Adjust::Pointer(PointerCast::ClosureFnPointer(a_sig.safety()))
+ }
TyKind::FnDef(..) => Adjust::Pointer(PointerCast::ReifyFnPointer),
_ => panic!("should not try to coerce a {prev_ty:?} to a fn pointer"),
};
let next_adjustment = match new_ty.kind() {
- TyKind::Closure(..) => Adjust::Pointer(PointerCast::ClosureFnPointer(
- b_sig.safety().to_chalk(self.table.interner),
- )),
+ TyKind::Closure(..) => {
+ Adjust::Pointer(PointerCast::ClosureFnPointer(b_sig.safety()))
+ }
TyKind::FnDef(..) => Adjust::Pointer(PointerCast::ReifyFnPointer),
_ => panic!("should not try to coerce a {new_ty:?} to a fn pointer"),
};
for &expr in exprs {
self.write_expr_adj(
expr,
- Box::new([Adjustment {
- kind: prev_adjustment.clone(),
- target: fn_ptr.to_chalk(self.table.interner),
- }]),
+ Box::new([Adjustment { kind: prev_adjustment.clone(), target: fn_ptr }]),
);
}
self.write_expr_adj(
new,
- Box::new([Adjustment {
- kind: next_adjustment,
- target: fn_ptr.to_chalk(self.table.interner),
- }]),
+ Box::new([Adjustment { kind: next_adjustment, target: fn_ptr }]),
);
return Ok(fn_ptr);
}
@@ -1205,23 +1193,18 @@ impl<'db> InferenceContext<'db> {
//
// NOTE: we set `coerce_never` to `true` here because coercion LUBs only
// operate on values and not places, so a never coercion is valid.
- let krate = self.krate();
let mut coerce = Coerce {
- table: &mut self.table,
- has_errors: &mut self.result.has_errors,
+ delegate: InferenceCoercionDelegate(self),
cause: ObligationCause::new(),
allow_two_phase: AllowTwoPhase::No,
coerce_never: true,
use_lub: true,
- target_features: &mut || {
- Self::target_features(self.db, &self.target_features, self.owner, krate)
- },
};
// First try to coerce the new expression to the type of the previous ones,
// but only if the new expression has no coercion already applied to it.
let mut first_error = None;
- if !self.result.expr_adjustments.contains_key(&new) {
+ if !coerce.delegate.0.result.expr_adjustments.contains_key(&new) {
let result = coerce.commit_if_ok(|coerce| coerce.coerce(new_ty, prev_ty));
match result {
Ok(ok) => {
@@ -1248,7 +1231,7 @@ impl<'db> InferenceContext<'db> {
.commit_if_ok(|table| {
table
.infer_ctxt
- .at(&ObligationCause::new(), table.param_env)
+ .at(&ObligationCause::new(), table.trait_env.env)
.lub(prev_ty, new_ty)
})
.unwrap_err())
@@ -1379,12 +1362,13 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
/// if necessary.
pub(crate) fn coerce(
&mut self,
- icx: &mut InferenceContext<'db>,
+ icx: &mut InferenceContext<'_, 'db>,
cause: &ObligationCause,
expression: ExprId,
expression_ty: Ty<'db>,
+ expr_is_read: ExprIsRead,
) {
- self.coerce_inner(icx, cause, expression, expression_ty, false, false)
+ self.coerce_inner(icx, cause, expression, expression_ty, false, false, expr_is_read)
}
/// Indicates that one of the inputs is a "forced unit". This
@@ -1401,18 +1385,20 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
/// removing a `;`).
pub(crate) fn coerce_forced_unit(
&mut self,
- icx: &mut InferenceContext<'db>,
+ icx: &mut InferenceContext<'_, 'db>,
expr: ExprId,
cause: &ObligationCause,
label_unit_as_expected: bool,
+ expr_is_read: ExprIsRead,
) {
self.coerce_inner(
icx,
cause,
expr,
- icx.result.standard_types.unit.to_nextsolver(icx.table.interner),
+ icx.types.unit,
true,
label_unit_as_expected,
+ expr_is_read,
)
}
@@ -1421,12 +1407,13 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
/// `Nil`.
pub(crate) fn coerce_inner(
&mut self,
- icx: &mut InferenceContext<'db>,
+ icx: &mut InferenceContext<'_, 'db>,
cause: &ObligationCause,
expression: ExprId,
mut expression_ty: Ty<'db>,
force_unit: bool,
label_expression_as_expected: bool,
+ expr_is_read: ExprIsRead,
) {
// Incorporate whatever type inference information we have
// until now; in principle we might also want to process
@@ -1463,7 +1450,7 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
expression_ty,
self.expected_ty,
AllowTwoPhase::No,
- CoerceNever::Yes,
+ expr_is_read,
)
} else {
match self.expressions {
@@ -1496,19 +1483,12 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
//
// Another example is `break` with no argument expression.
assert!(expression_ty.is_unit(), "if let hack without unit type");
- icx.table
- .infer_ctxt
- .at(cause, icx.table.param_env)
- .eq(
- // needed for tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
- DefineOpaqueTypes::Yes,
- expected,
- found,
- )
- .map(|infer_ok| {
+ icx.table.infer_ctxt.at(cause, icx.table.trait_env.env).eq(expected, found).map(
+ |infer_ok| {
icx.table.register_infer_ok(infer_ok);
expression_ty
- })
+ },
+ )
};
debug!(?result);
@@ -1530,20 +1510,14 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
// emit or provide suggestions on how to fix the initial error.
icx.set_tainted_by_errors();
- self.final_ty = Some(Ty::new_error(icx.table.interner, ErrorGuaranteed));
+ self.final_ty = Some(icx.types.error);
- icx.result.type_mismatches.insert(
+ icx.result.type_mismatches.get_or_insert_default().insert(
expression.into(),
if label_expression_as_expected {
- TypeMismatch {
- expected: found.to_chalk(icx.table.interner),
- actual: expected.to_chalk(icx.table.interner),
- }
+ TypeMismatch { expected: found, actual: expected }
} else {
- TypeMismatch {
- expected: expected.to_chalk(icx.table.interner),
- actual: found.to_chalk(icx.table.interner),
- }
+ TypeMismatch { expected, actual: found }
},
);
}
@@ -1552,73 +1526,190 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
self.pushed += 1;
}
- pub(crate) fn complete(self, icx: &mut InferenceContext<'db>) -> Ty<'db> {
+ pub(crate) fn complete(self, icx: &mut InferenceContext<'_, 'db>) -> Ty<'db> {
if let Some(final_ty) = self.final_ty {
final_ty
} else {
// If we only had inputs that were of type `!` (or no
// inputs at all), then the final type is `!`.
assert_eq!(self.pushed, 0);
- icx.result.standard_types.never.to_nextsolver(icx.table.interner)
+ icx.types.never
}
}
}
-pub fn could_coerce(
- db: &dyn HirDatabase,
- env: Arc<TraitEnvironment>,
- tys: &crate::Canonical<(crate::Ty, crate::Ty)>,
+pub fn could_coerce<'db>(
+ db: &'db dyn HirDatabase,
+ env: Arc<TraitEnvironment<'db>>,
+ tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>,
) -> bool {
coerce(db, env, tys).is_ok()
}
+struct HirCoercionDelegate<'a, 'db> {
+ infcx: &'a InferCtxt<'db>,
+ env: &'a TraitEnvironment<'db>,
+ target_features: &'a TargetFeatures<'db>,
+}
+
+impl<'db> CoerceDelegate<'db> for HirCoercionDelegate<'_, 'db> {
+ #[inline]
+ fn infcx(&self) -> &InferCtxt<'db> {
+ self.infcx
+ }
+ #[inline]
+ fn env(&self) -> &TraitEnvironment<'db> {
+ self.env
+ }
+ fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget) {
+ (self.target_features, TargetFeatureIsSafeInTarget::No)
+ }
+ fn set_diverging(&mut self, _diverging_ty: Ty<'db>) {}
+ fn set_tainted_by_errors(&mut self) {}
+ fn type_var_is_sized(&mut self, _var: TyVid) -> bool {
+ false
+ }
+}
+
fn coerce<'db>(
db: &'db dyn HirDatabase,
- env: Arc<TraitEnvironment>,
- tys: &crate::Canonical<(crate::Ty, crate::Ty)>,
-) -> Result<(Vec<Adjustment>, crate::Ty), TypeError<DbInterner<'db>>> {
- let mut table = InferenceTable::new(db, env);
- let vars = table.fresh_subst(tys.binders.as_slice(Interner));
- let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner);
- let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner);
+ env: Arc<TraitEnvironment<'db>>,
+ tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>,
+) -> Result<(Vec<Adjustment<'db>>, Ty<'db>), TypeError<DbInterner<'db>>> {
+ let interner = DbInterner::new_with(db, env.krate);
+ let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
+ let ((ty1_with_vars, ty2_with_vars), vars) = infcx.instantiate_canonical(tys);
let cause = ObligationCause::new();
// FIXME: Target features.
let target_features = TargetFeatures::default();
let mut coerce = Coerce {
- table: &mut table,
- has_errors: &mut false,
+ delegate: HirCoercionDelegate {
+ infcx: &infcx,
+ env: &env,
+ target_features: &target_features,
+ },
cause,
allow_two_phase: AllowTwoPhase::No,
coerce_never: true,
use_lub: false,
- target_features: &mut || (&target_features, TargetFeatureIsSafeInTarget::No),
};
- let InferOk { value: (adjustments, ty), obligations } = coerce.coerce(
- ty1_with_vars.to_nextsolver(coerce.table.interner),
- ty2_with_vars.to_nextsolver(coerce.table.interner),
- )?;
- table.register_predicates(obligations);
+ let infer_ok = coerce.coerce(ty1_with_vars, ty2_with_vars)?;
+ let mut ocx = ObligationCtxt::new(&infcx);
+ let (adjustments, ty) = ocx.register_infer_ok_obligations(infer_ok);
+ _ = ocx.try_evaluate_obligations();
+ let (adjustments, ty) = infcx.resolve_vars_if_possible((adjustments, ty));
// default any type vars that weren't unified back to their original bound vars
// (kind of hacky)
- let find_var = |iv| {
- vars.iter(Interner).position(|v| match v.interned() {
- chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(Interner),
- chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(Interner),
- chalk_ir::GenericArgData::Const(c) => c.inference_var(Interner),
- } == Some(iv))
- };
- let fallback = |iv, kind, default, binder| match kind {
- chalk_ir::VariableKind::Ty(_ty_kind) => find_var(iv)
- .map_or(default, |i| crate::BoundVar::new(binder, i).to_ty(Interner).cast(Interner)),
- chalk_ir::VariableKind::Lifetime => find_var(iv).map_or(default, |i| {
- crate::BoundVar::new(binder, i).to_lifetime(Interner).cast(Interner)
- }),
- chalk_ir::VariableKind::Const(ty) => find_var(iv).map_or(default, |i| {
- crate::BoundVar::new(binder, i).to_const(Interner, ty).cast(Interner)
- }),
- };
- // FIXME also map the types in the adjustments
- Ok((adjustments, table.resolve_with_fallback(ty.to_chalk(table.interner), &fallback)))
+
+ struct Resolver<'db> {
+ interner: DbInterner<'db>,
+ debruijn: DebruijnIndex,
+ var_values: GenericArgs<'db>,
+ }
+
+ impl<'db> TypeFolder<DbInterner<'db>> for Resolver<'db> {
+ fn cx(&self) -> DbInterner<'db> {
+ self.interner
+ }
+
+ fn fold_binder<T>(&mut self, t: Binder<'db, T>) -> Binder<'db, T>
+ where
+ T: TypeFoldable<DbInterner<'db>>,
+ {
+ self.debruijn.shift_in(1);
+ let result = t.super_fold_with(self);
+ self.debruijn.shift_out(1);
+ result
+ }
+
+ fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> {
+ if !t.has_infer() {
+ return t;
+ }
+
+ if let TyKind::Infer(infer) = t.kind() {
+ let var = self.var_values.iter().position(|arg| {
+ arg.as_type().is_some_and(|ty| match ty.kind() {
+ TyKind::Infer(it) => infer == it,
+ _ => false,
+ })
+ });
+ var.map_or_else(
+ || Ty::new_error(self.interner, ErrorGuaranteed),
+ |i| {
+ Ty::new_bound(
+ self.interner,
+ self.debruijn,
+ BoundTy { kind: BoundTyKind::Anon, var: BoundVar::from_usize(i) },
+ )
+ },
+ )
+ } else {
+ t.super_fold_with(self)
+ }
+ }
+
+ fn fold_const(&mut self, c: Const<'db>) -> Const<'db> {
+ if !c.has_infer() {
+ return c;
+ }
+
+ if let ConstKind::Infer(infer) = c.kind() {
+ let var = self.var_values.iter().position(|arg| {
+ arg.as_const().is_some_and(|ty| match ty.kind() {
+ ConstKind::Infer(it) => infer == it,
+ _ => false,
+ })
+ });
+ var.map_or_else(
+ || Const::new_error(self.interner, ErrorGuaranteed),
+ |i| {
+ Const::new_bound(
+ self.interner,
+ self.debruijn,
+ BoundConst { var: BoundVar::from_usize(i) },
+ )
+ },
+ )
+ } else {
+ c.super_fold_with(self)
+ }
+ }
+
+ fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
+ if let RegionKind::ReVar(infer) = r.kind() {
+ let var = self.var_values.iter().position(|arg| {
+ arg.as_region().is_some_and(|ty| match ty.kind() {
+ RegionKind::ReVar(it) => infer == it,
+ _ => false,
+ })
+ });
+ var.map_or_else(
+ || Region::error(self.interner),
+ |i| {
+ Region::new_bound(
+ self.interner,
+ self.debruijn,
+ BoundRegion {
+ kind: BoundRegionKind::Anon,
+ var: BoundVar::from_usize(i),
+ },
+ )
+ },
+ )
+ } else {
+ r
+ }
+ }
+ }
+
+ // FIXME: We don't fallback correctly since this is done on `InferenceContext` and we only have `InferCtxt`.
+ let (adjustments, ty) = (adjustments, ty).fold_with(&mut Resolver {
+ interner,
+ debruijn: DebruijnIndex::ZERO,
+ var_values: vars.var_values,
+ });
+ Ok((adjustments, ty))
}