1use std::iter;
9
10use chalk_ir::{BoundVar, Goal, Mutability, TyKind, TyVariableKind, cast::Cast};
11use hir_def::{hir::ExprId, lang_item::LangItem};
12use stdx::always;
13use triomphe::Arc;
14
15use crate::{
16 Canonical, DomainGoal, FnAbi, FnPointer, FnSig, InEnvironment, Interner, Lifetime,
17 Substitution, TraitEnvironment, Ty, TyBuilder, TyExt,
18 autoderef::{Autoderef, AutoderefKind},
19 db::HirDatabase,
20 infer::{
21 Adjust, Adjustment, AutoBorrow, InferOk, InferenceContext, OverloadedDeref, PointerCast,
22 TypeError, TypeMismatch,
23 },
24 traits::NextTraitSolveResult,
25 utils::ClosureSubst,
26};
27
28use super::unify::InferenceTable;
29
30pub(crate) type CoerceResult = Result<InferOk<(Vec<Adjustment>, Ty)>, TypeError>;
31
32fn identity(_: Ty) -> Vec<Adjustment> {
34 vec![]
35}
36
37fn simple(kind: Adjust) -> impl FnOnce(Ty) -> Vec<Adjustment> {
38 move |target| vec![Adjustment { kind, target }]
39}
40
41fn success(
43 adj: Vec<Adjustment>,
44 target: Ty,
45 goals: Vec<InEnvironment<Goal<Interner>>>,
46) -> CoerceResult {
47 Ok(InferOk { goals, value: (adj, target) })
48}
49
50pub(super) enum CoercionCause {
51 Expr(ExprId),
55}
56
57#[derive(Clone, Debug)]
58pub(super) struct CoerceMany {
59 expected_ty: Ty,
60 final_ty: Option<Ty>,
61 expressions: Vec<ExprId>,
62}
63
64impl CoerceMany {
65 pub(super) fn new(expected: Ty) -> Self {
66 CoerceMany { expected_ty: expected, final_ty: None, expressions: vec![] }
67 }
68
69 pub(super) fn expected_ty(&self) -> Ty {
78 self.expected_ty.clone()
79 }
80
81 pub(super) fn merged_ty(&self) -> Ty {
86 self.final_ty.clone().unwrap_or_else(|| self.expected_ty.clone())
87 }
88
89 pub(super) fn complete(self, ctx: &mut InferenceContext<'_>) -> Ty {
90 if let Some(final_ty) = self.final_ty {
91 final_ty
92 } else {
93 ctx.result.standard_types.never.clone()
94 }
95 }
96
97 pub(super) fn coerce_forced_unit(
98 &mut self,
99 ctx: &mut InferenceContext<'_>,
100 cause: CoercionCause,
101 ) {
102 self.coerce(ctx, None, &ctx.result.standard_types.unit.clone(), cause)
103 }
104
105 pub(super) fn coerce(
113 &mut self,
114 ctx: &mut InferenceContext<'_>,
115 expr: Option<ExprId>,
116 expr_ty: &Ty,
117 cause: CoercionCause,
118 ) {
119 let expr_ty = ctx.resolve_ty_shallow(expr_ty);
120 self.expected_ty = ctx.resolve_ty_shallow(&self.expected_ty);
121
122 let sig = match (self.merged_ty().kind(Interner), expr_ty.kind(Interner)) {
126 (TyKind::FnDef(x, _), TyKind::FnDef(y, _))
127 if x == y && ctx.table.unify(&self.merged_ty(), &expr_ty) =>
128 {
129 None
130 }
131 (TyKind::Closure(x, _), TyKind::Closure(y, _)) if x == y => None,
132 (TyKind::FnDef(..) | TyKind::Closure(..), TyKind::FnDef(..) | TyKind::Closure(..)) => {
133 cov_mark::hit!(coerce_fn_reification);
136 let sig =
137 self.merged_ty().callable_sig(ctx.db).expect("FnDef without callable sig");
138 Some(sig)
139 }
140 _ => None,
141 };
142 if let Some(sig) = sig {
143 let target_ty = TyKind::Function(sig.to_fn_ptr()).intern(Interner);
144 let result1 = ctx.table.coerce_inner(self.merged_ty(), &target_ty, CoerceNever::Yes);
145 let result2 = ctx.table.coerce_inner(expr_ty.clone(), &target_ty, CoerceNever::Yes);
146 if let (Ok(result1), Ok(result2)) = (result1, result2) {
147 ctx.table.register_infer_ok(InferOk { value: (), goals: result1.goals });
148 for &e in &self.expressions {
149 ctx.write_expr_adj(e, result1.value.0.clone().into_boxed_slice());
150 }
151 ctx.table.register_infer_ok(InferOk { value: (), goals: result2.goals });
152 if let Some(expr) = expr {
153 ctx.write_expr_adj(expr, result2.value.0.into_boxed_slice());
154 self.expressions.push(expr);
155 }
156 return self.final_ty = Some(target_ty);
157 }
158 }
159
160 if expr.is_none_or(|expr| !ctx.result.expr_adjustments.contains_key(&expr))
169 && let Ok(res) = ctx.coerce(expr, &expr_ty, &self.merged_ty(), CoerceNever::Yes)
170 {
171 self.final_ty = Some(res);
172 if let Some(expr) = expr {
173 self.expressions.push(expr);
174 }
175 return;
176 }
177
178 if let Ok((adjustments, res)) =
179 ctx.coerce_inner(&self.merged_ty(), &expr_ty, CoerceNever::Yes)
180 {
181 self.final_ty = Some(res);
182 for &e in &self.expressions {
183 ctx.write_expr_adj(e, adjustments.clone().into_boxed_slice());
184 }
185 } else {
186 match cause {
187 CoercionCause::Expr(id) => {
188 ctx.result.type_mismatches.insert(
189 id.into(),
190 TypeMismatch { expected: self.merged_ty(), actual: expr_ty.clone() },
191 );
192 }
193 }
194 cov_mark::hit!(coerce_merge_fail_fallback);
195 }
196 if let Some(expr) = expr {
197 self.expressions.push(expr);
198 }
199 }
200}
201
202pub fn could_coerce(
203 db: &dyn HirDatabase,
204 env: Arc<TraitEnvironment>,
205 tys: &Canonical<(Ty, Ty)>,
206) -> bool {
207 coerce(db, env, tys).is_ok()
208}
209
210pub(crate) fn coerce(
211 db: &dyn HirDatabase,
212 env: Arc<TraitEnvironment>,
213 tys: &Canonical<(Ty, Ty)>,
214) -> Result<(Vec<Adjustment>, Ty), TypeError> {
215 let mut table = InferenceTable::new(db, env);
216 let vars = table.fresh_subst(tys.binders.as_slice(Interner));
217 let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner);
218 let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner);
219 let (adjustments, ty) = table.coerce(&ty1_with_vars, &ty2_with_vars, CoerceNever::Yes)?;
220 let find_var = |iv| {
223 vars.iter(Interner).position(|v| match v.interned() {
224 chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(Interner),
225 chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(Interner),
226 chalk_ir::GenericArgData::Const(c) => c.inference_var(Interner),
227 } == Some(iv))
228 };
229 let fallback = |iv, kind, default, binder| match kind {
230 chalk_ir::VariableKind::Ty(_ty_kind) => find_var(iv)
231 .map_or(default, |i| BoundVar::new(binder, i).to_ty(Interner).cast(Interner)),
232 chalk_ir::VariableKind::Lifetime => find_var(iv)
233 .map_or(default, |i| BoundVar::new(binder, i).to_lifetime(Interner).cast(Interner)),
234 chalk_ir::VariableKind::Const(ty) => find_var(iv)
235 .map_or(default, |i| BoundVar::new(binder, i).to_const(Interner, ty).cast(Interner)),
236 };
237 Ok((adjustments, table.resolve_with_fallback(ty, &fallback)))
239}
240
241#[derive(Clone, Copy, PartialEq, Eq)]
242pub(crate) enum CoerceNever {
243 Yes,
244 No,
245}
246
247impl InferenceContext<'_> {
248 pub(super) fn coerce(
251 &mut self,
252 expr: Option<ExprId>,
253 from_ty: &Ty,
254 to_ty: &Ty,
255 coerce_never: CoerceNever,
261 ) -> Result<Ty, TypeError> {
262 let (adjustments, ty) = self.coerce_inner(from_ty, to_ty, coerce_never)?;
263 if let Some(expr) = expr {
264 self.write_expr_adj(expr, adjustments.into_boxed_slice());
265 }
266 Ok(ty)
267 }
268
269 fn coerce_inner(
270 &mut self,
271 from_ty: &Ty,
272 to_ty: &Ty,
273 coerce_never: CoerceNever,
274 ) -> Result<(Vec<Adjustment>, Ty), TypeError> {
275 let from_ty = self.resolve_ty_shallow(from_ty);
276 let to_ty = self.resolve_ty_shallow(to_ty);
277 self.table.coerce(&from_ty, &to_ty, coerce_never)
278 }
279}
280
281impl InferenceTable<'_> {
282 pub(crate) fn coerce(
285 &mut self,
286 from_ty: &Ty,
287 to_ty: &Ty,
288 coerce_never: CoerceNever,
289 ) -> Result<(Vec<Adjustment>, Ty), TypeError> {
290 let from_ty = self.resolve_ty_shallow(from_ty);
291 let to_ty = self.resolve_ty_shallow(to_ty);
292 match self.coerce_inner(from_ty, &to_ty, coerce_never) {
293 Ok(InferOk { value: (adjustments, ty), goals }) => {
294 self.register_infer_ok(InferOk { value: (), goals });
295 Ok((adjustments, ty))
296 }
297 Err(e) => {
298 Err(e)
300 }
301 }
302 }
303
304 fn coerce_inner(&mut self, from_ty: Ty, to_ty: &Ty, coerce_never: CoerceNever) -> CoerceResult {
305 if from_ty.is_never() {
306 if let TyKind::InferenceVar(tv, TyVariableKind::General) = to_ty.kind(Interner) {
307 self.set_diverging(*tv, true);
308 }
309 if coerce_never == CoerceNever::Yes {
310 return success(simple(Adjust::NeverToAny)(to_ty.clone()), to_ty.clone(), vec![]);
318 } else {
319 return self.unify_and(&from_ty, to_ty, identity);
320 }
321 }
322
323 let mut to_ty = to_ty;
325 let _to;
326 if let Some(tait_table) = &self.tait_coercion_table
327 && let TyKind::OpaqueType(opaque_ty_id, _) = to_ty.kind(Interner)
328 && !matches!(from_ty.kind(Interner), TyKind::InferenceVar(..) | TyKind::OpaqueType(..))
329 && let Some(ty) = tait_table.get(opaque_ty_id)
330 {
331 _to = ty.clone();
332 to_ty = &_to;
333 }
334
335 if let Ok(ret) = self.try_coerce_unsized(&from_ty, to_ty) {
337 return Ok(ret);
338 }
339
340 match to_ty.kind(Interner) {
342 TyKind::Raw(mt, _) => return self.coerce_ptr(from_ty, to_ty, *mt),
343 TyKind::Ref(mt, lt, _) => return self.coerce_ref(from_ty, to_ty, *mt, lt),
344 _ => {}
345 }
346
347 match from_ty.kind(Interner) {
348 TyKind::FnDef(..) => {
349 self.coerce_from_fn_item(from_ty, to_ty)
355 }
356 TyKind::Function(from_fn_ptr) => {
357 self.coerce_from_fn_pointer(from_ty.clone(), from_fn_ptr, to_ty)
360 }
361 TyKind::Closure(_, from_substs) => {
362 self.coerce_closure_to_fn(from_ty.clone(), from_substs, to_ty)
366 }
367 _ => {
368 self.unify_and(&from_ty, to_ty, identity)
370 }
371 }
372 }
373
374 fn unify_and<F>(&mut self, t1: &Ty, t2: &Ty, f: F) -> CoerceResult
376 where
377 F: FnOnce(Ty) -> Vec<Adjustment>,
378 {
379 self.try_unify(t1, t2)
380 .and_then(|InferOk { goals, .. }| success(f(t1.clone()), t1.clone(), goals))
381 }
382
383 fn coerce_ptr(&mut self, from_ty: Ty, to_ty: &Ty, to_mt: Mutability) -> CoerceResult {
384 let (is_ref, from_mt, from_inner) = match from_ty.kind(Interner) {
385 TyKind::Ref(mt, _, ty) => (true, mt, ty),
386 TyKind::Raw(mt, ty) => (false, mt, ty),
387 _ => return self.unify_and(&from_ty, to_ty, identity),
388 };
389
390 coerce_mutabilities(*from_mt, to_mt)?;
391
392 let from_raw = TyKind::Raw(to_mt, from_inner.clone()).intern(Interner);
394
395 if is_ref {
399 self.unify_and(&from_raw, to_ty, |target| {
400 vec![
401 Adjustment { kind: Adjust::Deref(None), target: from_inner.clone() },
402 Adjustment { kind: Adjust::Borrow(AutoBorrow::RawPtr(to_mt)), target },
403 ]
404 })
405 } else if *from_mt != to_mt {
406 self.unify_and(
407 &from_raw,
408 to_ty,
409 simple(Adjust::Pointer(PointerCast::MutToConstPointer)),
410 )
411 } else {
412 self.unify_and(&from_raw, to_ty, identity)
413 }
414 }
415
416 fn coerce_ref(
420 &mut self,
421 from_ty: Ty,
422 to_ty: &Ty,
423 to_mt: Mutability,
424 to_lt: &Lifetime,
425 ) -> CoerceResult {
426 let (_from_lt, from_mt) = match from_ty.kind(Interner) {
427 TyKind::Ref(mt, lt, _) => {
428 coerce_mutabilities(*mt, to_mt)?;
429 (lt.clone(), *mt) }
431 _ => return self.unify_and(&from_ty, to_ty, identity),
432 };
433
434 let snapshot = self.snapshot();
441
442 let mut autoderef = Autoderef::new(self, from_ty.clone(), false, false);
443 let mut first_error = None;
444 let mut found = None;
445
446 while let Some((referent_ty, autoderefs)) = autoderef.next() {
447 if autoderefs == 0 {
448 continue;
451 }
452
453 let lt = to_lt; let derefd_from_ty = TyKind::Ref(to_mt, lt.clone(), referent_ty).intern(Interner);
477 match autoderef.table.try_unify(&derefd_from_ty, to_ty) {
478 Ok(result) => {
479 found = Some(result.map(|()| derefd_from_ty));
480 break;
481 }
482 Err(err) => {
483 if first_error.is_none() {
484 first_error = Some(err);
485 }
486 }
487 }
488 }
489
490 let InferOk { value: ty, goals } = match found {
496 Some(d) => d,
497 None => {
498 self.rollback_to(snapshot);
499 let err = first_error.expect("coerce_borrowed_pointer had no error");
500 return Err(err);
501 }
502 };
503 if ty == from_ty && from_mt == Mutability::Not && autoderef.step_count() == 1 {
504 always!(to_mt == Mutability::Not); return success(vec![], ty, goals);
517 }
518
519 let mut adjustments = auto_deref_adjust_steps(&autoderef);
520 adjustments.push(Adjustment {
521 kind: Adjust::Borrow(AutoBorrow::Ref(to_lt.clone(), to_mt)),
522 target: ty.clone(),
523 });
524
525 success(adjustments, ty, goals)
526 }
527
528 fn coerce_from_fn_item(&mut self, from_ty: Ty, to_ty: &Ty) -> CoerceResult {
530 match to_ty.kind(Interner) {
531 TyKind::Function(_) => {
532 let from_sig = from_ty.callable_sig(self.db).expect("FnDef had no sig");
533
534 let from_sig = from_sig.to_fn_ptr();
540 let from_fn_pointer = TyKind::Function(from_sig.clone()).intern(Interner);
541 let ok = self.coerce_from_safe_fn(
542 from_fn_pointer.clone(),
543 &from_sig,
544 to_ty,
545 |unsafe_ty| {
546 vec![
547 Adjustment {
548 kind: Adjust::Pointer(PointerCast::ReifyFnPointer),
549 target: from_fn_pointer,
550 },
551 Adjustment {
552 kind: Adjust::Pointer(PointerCast::UnsafeFnPointer),
553 target: unsafe_ty,
554 },
555 ]
556 },
557 simple(Adjust::Pointer(PointerCast::ReifyFnPointer)),
558 )?;
559
560 Ok(ok)
561 }
562 _ => self.unify_and(&from_ty, to_ty, identity),
563 }
564 }
565
566 fn coerce_from_fn_pointer(
567 &mut self,
568 from_ty: Ty,
569 from_f: &FnPointer,
570 to_ty: &Ty,
571 ) -> CoerceResult {
572 self.coerce_from_safe_fn(
573 from_ty,
574 from_f,
575 to_ty,
576 simple(Adjust::Pointer(PointerCast::UnsafeFnPointer)),
577 identity,
578 )
579 }
580
581 fn coerce_from_safe_fn<F, G>(
582 &mut self,
583 from_ty: Ty,
584 from_fn_ptr: &FnPointer,
585 to_ty: &Ty,
586 to_unsafe: F,
587 normal: G,
588 ) -> CoerceResult
589 where
590 F: FnOnce(Ty) -> Vec<Adjustment>,
591 G: FnOnce(Ty) -> Vec<Adjustment>,
592 {
593 if let TyKind::Function(to_fn_ptr) = to_ty.kind(Interner)
594 && let (chalk_ir::Safety::Safe, chalk_ir::Safety::Unsafe) =
595 (from_fn_ptr.sig.safety, to_fn_ptr.sig.safety)
596 {
597 let from_unsafe =
598 TyKind::Function(safe_to_unsafe_fn_ty(from_fn_ptr.clone())).intern(Interner);
599 return self.unify_and(&from_unsafe, to_ty, to_unsafe);
600 }
601 self.unify_and(&from_ty, to_ty, normal)
602 }
603
604 fn coerce_closure_to_fn(
607 &mut self,
608 from_ty: Ty,
609 from_substs: &Substitution,
610 to_ty: &Ty,
611 ) -> CoerceResult {
612 match to_ty.kind(Interner) {
613 TyKind::Function(fn_ty) => {
615 let safety = fn_ty.sig.safety;
622 let pointer_ty = coerce_closure_fn_ty(from_substs, safety);
623 self.unify_and(
624 &pointer_ty,
625 to_ty,
626 simple(Adjust::Pointer(PointerCast::ClosureFnPointer(safety))),
627 )
628 }
629 _ => self.unify_and(&from_ty, to_ty, identity),
630 }
631 }
632
633 fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty) -> CoerceResult {
637 if from_ty.is_ty_var() {
659 return Err(TypeError);
660 }
661 if to_ty.is_ty_var() {
662 return Err(TypeError);
663 }
664
665 let reborrow = match (from_ty.kind(Interner), to_ty.kind(Interner)) {
667 (TyKind::Ref(from_mt, _, from_inner), &TyKind::Ref(to_mt, _, _)) => {
668 coerce_mutabilities(*from_mt, to_mt)?;
669
670 let lt = self.new_lifetime_var();
671 Some((
672 Adjustment { kind: Adjust::Deref(None), target: from_inner.clone() },
673 Adjustment {
674 kind: Adjust::Borrow(AutoBorrow::Ref(lt.clone(), to_mt)),
675 target: TyKind::Ref(to_mt, lt, from_inner.clone()).intern(Interner),
676 },
677 ))
678 }
679 (TyKind::Ref(from_mt, _, from_inner), &TyKind::Raw(to_mt, _)) => {
680 coerce_mutabilities(*from_mt, to_mt)?;
681
682 Some((
683 Adjustment { kind: Adjust::Deref(None), target: from_inner.clone() },
684 Adjustment {
685 kind: Adjust::Borrow(AutoBorrow::RawPtr(to_mt)),
686 target: TyKind::Raw(to_mt, from_inner.clone()).intern(Interner),
687 },
688 ))
689 }
690 _ => None,
691 };
692 let coerce_from =
693 reborrow.as_ref().map_or_else(|| from_ty.clone(), |(_, adj)| adj.target.clone());
694
695 let krate = self.trait_env.krate;
696 let coerce_unsized_trait = match LangItem::CoerceUnsized.resolve_trait(self.db, krate) {
697 Some(trait_) => trait_,
698 _ => return Err(TypeError),
699 };
700
701 let coerce_unsized_tref = {
702 let b = TyBuilder::trait_ref(self.db, coerce_unsized_trait);
703 if b.remaining() != 2 {
704 return Err(TypeError);
706 }
707 b.push(coerce_from).push(to_ty.clone()).build()
708 };
709
710 let goal: InEnvironment<DomainGoal> =
711 InEnvironment::new(&self.trait_env.env, coerce_unsized_tref.cast(Interner));
712
713 let canonicalized = self.canonicalize_with_free_vars(goal);
714
715 let solution = self.db.trait_solve(
720 krate,
721 self.trait_env.block,
722 canonicalized.value.clone().cast(Interner),
723 );
724
725 match solution {
726 NextTraitSolveResult::Certain(v) => {
731 canonicalized.apply_solution(
732 self,
733 Canonical {
734 binders: v.binders,
735 value: v.value.subst,
737 },
738 );
739 }
740 NextTraitSolveResult::Uncertain(..) | NextTraitSolveResult::NoSolution => {
742 return Err(TypeError);
743 }
744 }
745
746 let unsize =
747 Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), target: to_ty.clone() };
748 let adjustments = match reborrow {
749 None => vec![unsize],
750 Some((deref, autoref)) => vec![deref, autoref, unsize],
751 };
752 success(adjustments, to_ty.clone(), vec![])
753 }
754}
755
756fn coerce_closure_fn_ty(closure_substs: &Substitution, safety: chalk_ir::Safety) -> Ty {
757 let closure_sig = ClosureSubst(closure_substs).sig_ty().clone();
758 match closure_sig.kind(Interner) {
759 TyKind::Function(fn_ty) => TyKind::Function(FnPointer {
760 num_binders: fn_ty.num_binders,
761 sig: FnSig { safety, abi: FnAbi::Rust, variadic: fn_ty.sig.variadic },
762 substitution: fn_ty.substitution.clone(),
763 })
764 .intern(Interner),
765 _ => TyKind::Error.intern(Interner),
766 }
767}
768
769fn safe_to_unsafe_fn_ty(fn_ty: FnPointer) -> FnPointer {
770 FnPointer {
771 num_binders: fn_ty.num_binders,
772 sig: FnSig { safety: chalk_ir::Safety::Unsafe, ..fn_ty.sig },
773 substitution: fn_ty.substitution,
774 }
775}
776
777fn coerce_mutabilities(from: Mutability, to: Mutability) -> Result<(), TypeError> {
778 match (from, to) {
779 (Mutability::Mut, Mutability::Mut | Mutability::Not)
780 | (Mutability::Not, Mutability::Not) => Ok(()),
781 (Mutability::Not, Mutability::Mut) => Err(TypeError),
782 }
783}
784
785pub(super) fn auto_deref_adjust_steps(autoderef: &Autoderef<'_, '_>) -> Vec<Adjustment> {
786 let steps = autoderef.steps();
787 let targets =
788 steps.iter().skip(1).map(|(_, ty)| ty.clone()).chain(iter::once(autoderef.final_ty()));
789 steps
790 .iter()
791 .map(|(kind, _source)| match kind {
792 AutoderefKind::Overloaded => Some(OverloadedDeref(None)),
794 AutoderefKind::Builtin => None,
795 })
796 .zip(targets)
797 .map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target })
798 .collect()
799}