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.rs245
1 files changed, 115 insertions, 130 deletions
diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs
index 0ca696ed08..4620da7147 100644
--- a/crates/hir-ty/src/infer/coerce.rs
+++ b/crates/hir-ty/src/infer/coerce.rs
@@ -35,7 +35,6 @@
//! // and are then unable to coerce `&7i32` to `&mut i32`.
//! ```
-use chalk_ir::cast::Cast;
use hir_def::{
CallableDefId,
hir::{ExprId, ExprOrPatId},
@@ -45,29 +44,30 @@ use hir_def::{
use intern::sym;
use rustc_ast_ir::Mutability;
use rustc_type_ir::{
- TypeAndMut,
+ BoundVar, TypeAndMut,
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},
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, SolverDefId, TraitRef, Ty,
+ TyKind,
infer::{
DefineOpaqueTypes, InferCtxt, InferOk, InferResult,
relate::RelateResult,
select::{ImplSource, SelectionError},
traits::{Obligation, ObligationCause, PredicateObligation, PredicateObligations},
},
- mapping::{ChalkToNextSolver, NextSolverToChalk},
obligation_ctxt::ObligationCtxt,
},
utils::TargetFeatureIsSafeInTarget,
@@ -93,7 +93,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,7 +103,7 @@ 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> {
@@ -118,7 +118,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
#[inline]
fn interner(&self) -> DbInterner<'db> {
- self.table.interner
+ self.table.interner()
}
#[inline]
@@ -182,17 +182,14 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
&mut self,
a: Ty<'db>,
b: Ty<'db>,
- adjustments: impl IntoIterator<Item = Adjustment>,
- final_adjustment: Adjust,
+ adjustments: impl IntoIterator<Item = Adjustment<'db>>,
+ final_adjustment: Adjust<'db>,
) -> 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,
@@ -216,10 +213,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
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(),
);
@@ -241,10 +235,9 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
&& 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())
+ && let Some(ty) = tait_table.get(&opaque_ty_id)
{
- b = ty.to_nextsolver(self.interner());
- b = self.table.shallow_resolve(b);
+ b = self.table.shallow_resolve(*ty);
}
let b = b;
@@ -474,7 +467,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
r_borrow_var.unwrap()
};
let derefd_ty_a = Ty::new_ref(
- autoderef.table.interner,
+ autoderef.table.interner(),
r,
referent_ty,
mutbl_b, // [1] above
@@ -547,11 +540,8 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
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()),
+ kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl_b)),
+ target: ty,
});
debug!("coerce_borrowed_pointer: succeeded ty={:?} adjustments={:?}", ty, adjustments);
@@ -655,20 +645,13 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
// 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 = mutbl_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::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(r_borrow, mutbl)),
+ target: Ty::new_ref(self.interner(), r_borrow, ty_a, mutbl_b),
},
))
}
@@ -676,20 +659,16 @@ 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.
@@ -834,7 +813,7 @@ impl<'a, 'b, 'db> Coerce<'a, 'b, 'db> {
&mut self,
fn_ty_a: PolyFnSig<'db>,
b: Ty<'db>,
- adjustment: Option<Adjust>,
+ adjustment: Option<Adjust<'db>>,
) -> CoerceResult<'db> {
debug_assert!(self.table.shallow_resolve(b) == b);
@@ -849,7 +828,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),
)
@@ -961,9 +940,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),
@@ -991,11 +968,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))
@@ -1011,7 +985,7 @@ pub(crate) enum CoerceNever {
Yes,
}
-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.
@@ -1128,13 +1102,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
@@ -1142,7 +1116,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
@@ -1166,36 +1140,30 @@ impl<'db> InferenceContext<'db> {
.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);
}
@@ -1382,7 +1350,7 @@ 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>,
@@ -1404,19 +1372,12 @@ 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,
) {
- self.coerce_inner(
- icx,
- cause,
- expr,
- icx.result.standard_types.unit.to_nextsolver(icx.table.interner),
- true,
- label_unit_as_expected,
- )
+ self.coerce_inner(icx, cause, expr, icx.types.unit, true, label_unit_as_expected)
}
/// The inner coercion "engine". If `expression` is `None`, this
@@ -1424,7 +1385,7 @@ 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>,
@@ -1533,20 +1494,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(
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 }
},
);
}
@@ -1555,14 +1510,14 @@ 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
}
}
}
@@ -1570,7 +1525,7 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
pub fn could_coerce<'db>(
db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment<'db>>,
- tys: &crate::Canonical<(crate::Ty, crate::Ty)>,
+ tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>,
) -> bool {
coerce(db, env, tys).is_ok()
}
@@ -1578,12 +1533,11 @@ pub fn could_coerce<'db>(
fn coerce<'db>(
db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment<'db>>,
- tys: &crate::Canonical<(crate::Ty, crate::Ty)>,
-) -> Result<(Vec<Adjustment>, crate::Ty), TypeError<DbInterner<'db>>> {
+ tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>,
+) -> Result<(Vec<Adjustment<'db>>, Ty<'db>), 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);
+ let interner = table.interner();
+ let ((ty1_with_vars, ty2_with_vars), vars) = table.infer_ctxt.instantiate_canonical(tys);
let cause = ObligationCause::new();
// FIXME: Target features.
@@ -1597,36 +1551,67 @@ fn coerce<'db>(
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),
- )?;
+ let InferOk { value: (adjustments, ty), obligations } =
+ coerce.coerce(ty1_with_vars, ty2_with_vars)?;
table.register_predicates(obligations);
// 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 mut fallback_ty = |debruijn, infer| {
+ let var = vars.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(interner, ErrorGuaranteed),
+ |i| {
+ Ty::new_bound(
+ interner,
+ debruijn,
+ BoundTy { kind: BoundTyKind::Anon, var: BoundVar::from_usize(i) },
+ )
+ },
+ )
+ };
+ let mut fallback_const = |debruijn, infer| {
+ let var = vars.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(interner, ErrorGuaranteed),
+ |i| Const::new_bound(interner, debruijn, BoundConst { var: BoundVar::from_usize(i) }),
+ )
};
- let fallback = |iv, kind, binder| match kind {
- chalk_ir::VariableKind::Ty(_ty_kind) => find_var(iv).map_or_else(
- || chalk_ir::TyKind::Error.intern(Interner).cast(Interner),
- |i| crate::BoundVar::new(binder, i).to_ty(Interner).cast(Interner),
- ),
- chalk_ir::VariableKind::Lifetime => find_var(iv).map_or_else(
- || crate::LifetimeData::Error.intern(Interner).cast(Interner),
- |i| crate::BoundVar::new(binder, i).to_lifetime(Interner).cast(Interner),
- ),
- chalk_ir::VariableKind::Const(ty) => find_var(iv).map_or_else(
- || crate::unknown_const(ty.clone()).cast(Interner),
- |i| crate::BoundVar::new(binder, i).to_const(Interner, ty.clone()).cast(Interner),
- ),
+ let mut fallback_region = |debruijn, infer| {
+ let var = vars.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(interner),
+ |i| {
+ Region::new_bound(
+ interner,
+ debruijn,
+ BoundRegion { kind: BoundRegionKind::Anon, var: BoundVar::from_usize(i) },
+ )
+ },
+ )
};
// FIXME also map the types in the adjustments
// FIXME: We don't fallback correctly since this is done on `InferenceContext` and we only have `InferenceTable`.
- Ok((adjustments, table.resolve_with_fallback(ty.to_chalk(table.interner), &fallback)))
+ let ty = table.resolve_with_fallback(
+ ty,
+ &mut fallback_ty,
+ &mut fallback_const,
+ &mut fallback_region,
+ );
+ Ok((adjustments, ty))
}