Skip to content

Commit 6133e6a

Browse files
committed
Extract coercion logic to InferenceTable
To make it accessible without an InferenceContext.
1 parent 6a0b199 commit 6133e6a

File tree

2 files changed

+34
-18
lines changed

2 files changed

+34
-18
lines changed

crates/hir_ty/src/infer/coerce.rs

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ use crate::{
2222
Solution, Substitution, Ty, TyBuilder, TyExt, TyKind,
2323
};
2424

25+
use super::unify::InferenceTable;
26+
2527
pub(crate) type CoerceResult = Result<InferOk<(Vec<Adjustment>, Ty)>, TypeError>;
2628

2729
/// Do not require any adjustments, i.e. coerce `x -> x`.
@@ -84,8 +86,8 @@ impl CoerceMany {
8486
};
8587
if let Some(sig) = sig {
8688
let target_ty = TyKind::Function(sig.to_fn_ptr()).intern(Interner);
87-
let result1 = ctx.coerce_inner(self.expected_ty.clone(), &target_ty);
88-
let result2 = ctx.coerce_inner(expr_ty.clone(), &target_ty);
89+
let result1 = ctx.table.coerce_inner(self.expected_ty.clone(), &target_ty);
90+
let result2 = ctx.table.coerce_inner(expr_ty.clone(), &target_ty);
8991
if let (Ok(result1), Ok(result2)) = (result1, result2) {
9092
ctx.table.register_infer_ok(result1);
9193
ctx.table.register_infer_ok(result2);
@@ -126,16 +128,31 @@ impl<'a> InferenceContext<'a> {
126128
expr: Option<ExprId>,
127129
from_ty: &Ty,
128130
to_ty: &Ty,
129-
) -> InferResult<Ty> {
131+
) -> Result<Ty, TypeError> {
132+
let from_ty = self.resolve_ty_shallow(from_ty);
133+
let to_ty = self.resolve_ty_shallow(to_ty);
134+
let (adjustments, ty) = self.table.coerce(&from_ty, &to_ty)?;
135+
if let Some(expr) = expr {
136+
self.write_expr_adj(expr, adjustments);
137+
}
138+
Ok(ty)
139+
}
140+
}
141+
142+
impl<'a> InferenceTable<'a> {
143+
/// Unify two types, but may coerce the first one to the second one
144+
/// using "implicit coercion rules" if needed.
145+
pub(crate) fn coerce(
146+
&mut self,
147+
from_ty: &Ty,
148+
to_ty: &Ty,
149+
) -> Result<(Vec<Adjustment>, Ty), TypeError> {
130150
let from_ty = self.resolve_ty_shallow(from_ty);
131151
let to_ty = self.resolve_ty_shallow(to_ty);
132152
match self.coerce_inner(from_ty, &to_ty) {
133153
Ok(InferOk { value: (adjustments, ty), goals }) => {
134-
if let Some(expr) = expr {
135-
self.write_expr_adj(expr, adjustments);
136-
}
137-
self.table.register_infer_ok(InferOk { value: (), goals });
138-
Ok(InferOk { value: ty, goals: Vec::new() })
154+
self.register_infer_ok(InferOk { value: (), goals });
155+
Ok((adjustments, ty))
139156
}
140157
Err(e) => {
141158
// FIXME deal with error
@@ -154,7 +171,7 @@ impl<'a> InferenceContext<'a> {
154171
//
155172
// here, we would coerce from `!` to `?T`.
156173
if let TyKind::InferenceVar(tv, TyVariableKind::General) = to_ty.kind(Interner) {
157-
self.table.set_diverging(*tv, true);
174+
self.set_diverging(*tv, true);
158175
}
159176
return success(simple(Adjust::NeverToAny)(to_ty.clone()), to_ty.clone(), vec![]);
160177
}
@@ -203,8 +220,7 @@ impl<'a> InferenceContext<'a> {
203220
where
204221
F: FnOnce(Ty) -> Vec<Adjustment>,
205222
{
206-
self.table
207-
.try_unify(t1, t2)
223+
self.try_unify(t1, t2)
208224
.and_then(|InferOk { goals, .. }| success(f(t1.clone()), t1.clone(), goals))
209225
}
210226

@@ -259,9 +275,9 @@ impl<'a> InferenceContext<'a> {
259275
// details of coercion errors though, so I think it's useful to leave
260276
// the structure like it is.
261277

262-
let snapshot = self.table.snapshot();
278+
let snapshot = self.snapshot();
263279

264-
let mut autoderef = Autoderef::new(&mut self.table, from_ty.clone());
280+
let mut autoderef = Autoderef::new(self, from_ty.clone());
265281
let mut first_error = None;
266282
let mut found = None;
267283

@@ -317,7 +333,7 @@ impl<'a> InferenceContext<'a> {
317333
let InferOk { value: ty, goals } = match found {
318334
Some(d) => d,
319335
None => {
320-
self.table.rollback_to(snapshot);
336+
self.rollback_to(snapshot);
321337
let err = first_error.expect("coerce_borrowed_pointer had no error");
322338
return Err(err);
323339
}
@@ -513,7 +529,7 @@ impl<'a> InferenceContext<'a> {
513529
let coerce_from =
514530
reborrow.as_ref().map_or_else(|| from_ty.clone(), |(_, adj)| adj.target.clone());
515531

516-
let krate = self.resolver.krate().unwrap();
532+
let krate = self.trait_env.krate;
517533
let coerce_unsized_trait =
518534
match self.db.lang_item(krate, SmolStr::new_inline("coerce_unsized")) {
519535
Some(LangItemTarget::TraitId(trait_)) => trait_,
@@ -546,7 +562,7 @@ impl<'a> InferenceContext<'a> {
546562
match solution {
547563
Solution::Unique(v) => {
548564
canonicalized.apply_solution(
549-
&mut self.table,
565+
self,
550566
Canonical {
551567
binders: v.binders,
552568
// FIXME handle constraints
@@ -556,7 +572,7 @@ impl<'a> InferenceContext<'a> {
556572
}
557573
Solution::Ambig(Guidance::Definite(subst)) => {
558574
// FIXME need to record an obligation here
559-
canonicalized.apply_solution(&mut self.table, subst)
575+
canonicalized.apply_solution(self, subst)
560576
}
561577
// FIXME actually we maybe should also accept unknown guidance here
562578
_ => return Err(TypeError),

crates/hir_ty/src/infer/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<'a> InferenceContext<'a> {
6767
let ty = self.infer_expr_inner(expr, expected);
6868
if let Some(target) = expected.only_has_type(&mut self.table) {
6969
match self.coerce(Some(expr), &ty, &target) {
70-
Ok(res) => res.value,
70+
Ok(res) => res,
7171
Err(_) => {
7272
self.result
7373
.type_mismatches

0 commit comments

Comments
 (0)