Skip to main content

hir_ty/infer/
coerce.rs

1//! # Type Coercion
2//!
3//! Under certain circumstances we will coerce from one type to another,
4//! for example by auto-borrowing. This occurs in situations where the
5//! compiler has a firm 'expected type' that was supplied from the user,
6//! and where the actual type is similar to that expected type in purpose
7//! but not in representation (so actual subtyping is inappropriate).
8//!
9//! ## Reborrowing
10//!
11//! Note that if we are expecting a reference, we will *reborrow*
12//! even if the argument provided was already a reference. This is
13//! useful for freezing mut things (that is, when the expected type is &T
14//! but you have &mut T) and also for avoiding the linearity
15//! of mut things (when the expected is &mut T and you have &mut T). See
16//! the various `tests/ui/coerce/*.rs` tests for
17//! examples of where this is useful.
18//!
19//! ## Subtle note
20//!
21//! When inferring the generic arguments of functions, the argument
22//! order is relevant, which can lead to the following edge case:
23//!
24//! ```ignore (illustrative)
25//! fn foo<T>(a: T, b: T) {
26//!     // ...
27//! }
28//!
29//! foo(&7i32, &mut 7i32);
30//! // This compiles, as we first infer `T` to be `&i32`,
31//! // and then coerce `&mut 7i32` to `&7i32`.
32//!
33//! foo(&mut 7i32, &7i32);
34//! // This does not compile, as we first infer `T` to be `&mut i32`
35//! // and are then unable to coerce `&7i32` to `&mut i32`.
36//! ```
37
38use std::ops::ControlFlow;
39
40use hir_def::{
41    CallableDefId, TraitId, attrs::AttrFlags, hir::ExprId, signatures::FunctionSignature,
42};
43use rustc_ast_ir::Mutability;
44use rustc_type_ir::{
45    BoundVar, DebruijnIndex, InferTy, TyVid, TypeAndMut, TypeFoldable, TypeFolder,
46    TypeSuperFoldable, TypeVisitableExt,
47    error::TypeError,
48    inherent::{Const as _, GenericArg as _, GenericArgs as _, IntoKind, Safety as _, Ty as _},
49    solve::{Certainty, NoSolution},
50};
51use smallvec::SmallVec;
52use tracing::{debug, instrument};
53
54use crate::{
55    Adjust, Adjustment, AutoBorrow, ParamEnvAndCrate, PointerCast, Span, TargetFeatures,
56    autoderef::Autoderef,
57    db::{HirDatabase, InternedClosure, InternedClosureId},
58    infer::{AllowTwoPhase, AutoBorrowMutability, InferenceContext, expr::ExprIsRead},
59    next_solver::{
60        Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, CallableIdWrapper,
61        Canonical, CoercePredicate, Const, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs,
62        Goal, ParamEnv, PolyFnSig, PredicateKind, Region, RegionKind, TraitRef, Ty, TyKind,
63        TypingMode,
64        abi::Safety,
65        infer::{
66            DbInternerInferExt, InferCtxt, InferOk, InferResult,
67            relate::RelateResult,
68            traits::{Obligation, ObligationCause, PredicateObligations},
69        },
70        inspect::{InspectGoal, ProofTreeVisitor},
71        obligation_ctxt::ObligationCtxt,
72    },
73    upvars::upvars_mentioned,
74    utils::TargetFeatureIsSafeInTarget,
75};
76
77trait CoerceDelegate<'db> {
78    fn infcx(&self) -> &InferCtxt<'db>;
79    fn param_env(&self) -> ParamEnv<'db>;
80    fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget);
81
82    fn set_diverging(&mut self, diverging_ty: Ty<'db>);
83
84    fn type_var_is_sized(&self, var: TyVid) -> bool;
85}
86
87struct Coerce<D> {
88    delegate: D,
89    use_lub: bool,
90    /// Determines whether or not allow_two_phase_borrow is set on any
91    /// autoref adjustments we create while coercing. We don't want to
92    /// allow deref coercions to create two-phase borrows, at least initially,
93    /// but we do need two-phase borrows for function argument reborrows.
94    /// See rust#47489 and rust#48598
95    /// See docs on the "AllowTwoPhase" type for a more detailed discussion
96    allow_two_phase: AllowTwoPhase,
97    /// Whether we allow `NeverToAny` coercions. This is unsound if we're
98    /// coercing a place expression without it counting as a read in the MIR.
99    /// This is a side-effect of HIR not really having a great distinction
100    /// between places and values.
101    coerce_never: bool,
102    cause: ObligationCause,
103}
104
105type CoerceResult<'db> = InferResult<'db, (Vec<Adjustment>, Ty<'db>)>;
106
107/// Coercing a mutable reference to an immutable works, while
108/// coercing `&T` to `&mut T` should be forbidden.
109fn coerce_mutbls<'db>(from_mutbl: Mutability, to_mutbl: Mutability) -> RelateResult<'db, ()> {
110    if from_mutbl >= to_mutbl { Ok(()) } else { Err(TypeError::Mutability) }
111}
112
113/// This always returns `Ok(...)`.
114fn success<'db>(
115    adj: Vec<Adjustment>,
116    target: Ty<'db>,
117    obligations: PredicateObligations<'db>,
118) -> CoerceResult<'db> {
119    Ok(InferOk { value: (adj, target), obligations })
120}
121
122impl<'db, D> Coerce<D>
123where
124    D: CoerceDelegate<'db>,
125{
126    #[inline]
127    fn infcx(&self) -> &InferCtxt<'db> {
128        self.delegate.infcx()
129    }
130
131    #[inline]
132    fn param_env(&self) -> ParamEnv<'db> {
133        self.delegate.param_env()
134    }
135
136    #[inline]
137    fn interner(&self) -> DbInterner<'db> {
138        self.infcx().interner
139    }
140
141    #[inline]
142    fn db(&self) -> &'db dyn HirDatabase {
143        self.interner().db
144    }
145
146    pub(crate) fn commit_if_ok<T, E>(
147        &mut self,
148        f: impl FnOnce(&mut Self) -> Result<T, E>,
149    ) -> Result<T, E> {
150        let snapshot = self.infcx().start_snapshot();
151        let result = f(self);
152        match result {
153            Ok(_) => self.infcx().commit_from(snapshot),
154            Err(_) => self.infcx().rollback_to(snapshot),
155        }
156        result
157    }
158
159    fn unify_raw(&self, a: Ty<'db>, b: Ty<'db>) -> InferResult<'db, Ty<'db>> {
160        debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub);
161        self.infcx().commit_if_ok(|_| {
162            let at = self.infcx().at(&self.cause, self.param_env());
163
164            let res = if self.use_lub {
165                at.lub(b, a)
166            } else {
167                at.sup(b, a)
168                    .map(|InferOk { value: (), obligations }| InferOk { value: b, obligations })
169            };
170
171            // In the new solver, lazy norm may allow us to shallowly equate
172            // more types, but we emit possibly impossible-to-satisfy obligations.
173            // Filter these cases out to make sure our coercion is more accurate.
174            match res {
175                Ok(InferOk { value, obligations }) => {
176                    let mut ocx = ObligationCtxt::new(self.infcx());
177                    ocx.register_obligations(obligations);
178                    if ocx.try_evaluate_obligations().is_empty() {
179                        Ok(InferOk { value, obligations: ocx.into_pending_obligations() })
180                    } else {
181                        Err(TypeError::Mismatch)
182                    }
183                }
184                res => res,
185            }
186        })
187    }
188
189    /// Unify two types (using sub or lub).
190    fn unify(&mut self, a: Ty<'db>, b: Ty<'db>) -> CoerceResult<'db> {
191        self.unify_raw(a, b)
192            .and_then(|InferOk { value: ty, obligations }| success(vec![], ty, obligations))
193    }
194
195    /// Unify two types (using sub or lub) and produce a specific coercion.
196    fn unify_and(
197        &mut self,
198        a: Ty<'db>,
199        b: Ty<'db>,
200        adjustments: impl IntoIterator<Item = Adjustment>,
201        final_adjustment: Adjust,
202    ) -> CoerceResult<'db> {
203        self.unify_raw(a, b).and_then(|InferOk { value: ty, obligations }| {
204            success(
205                adjustments
206                    .into_iter()
207                    .chain(std::iter::once(Adjustment {
208                        target: ty.store(),
209                        kind: final_adjustment,
210                    }))
211                    .collect(),
212                ty,
213                obligations,
214            )
215        })
216    }
217
218    #[instrument(skip(self))]
219    fn coerce(&mut self, a: Ty<'db>, b: Ty<'db>) -> CoerceResult<'db> {
220        // First, remove any resolved type variables (at the top level, at least):
221        let a = self.infcx().shallow_resolve(a);
222        let b = self.infcx().shallow_resolve(b);
223        debug!("Coerce.tys({:?} => {:?})", a, b);
224
225        // Coercing from `!` to any type is allowed:
226        if a.is_never() {
227            // If we're coercing into an inference var, mark it as possibly diverging.
228            if b.is_infer() {
229                self.delegate.set_diverging(b);
230            }
231
232            if self.coerce_never {
233                return success(
234                    vec![Adjustment { kind: Adjust::NeverToAny, target: b.store() }],
235                    b,
236                    PredicateObligations::new(),
237                );
238            } else {
239                // Otherwise the only coercion we can do is unification.
240                return self.unify(a, b);
241            }
242        }
243
244        // Coercing *from* an unresolved inference variable means that
245        // we have no information about the source type. This will always
246        // ultimately fall back to some form of subtyping.
247        if a.is_infer() {
248            return self.coerce_from_inference_variable(a, b);
249        }
250
251        // Consider coercing the subtype to a DST
252        //
253        // NOTE: this is wrapped in a `commit_if_ok` because it creates
254        // a "spurious" type variable, and we don't want to have that
255        // type variable in memory if the coercion fails.
256        let unsize = self.commit_if_ok(|this| this.coerce_unsized(a, b));
257        match unsize {
258            Ok(_) => {
259                debug!("coerce: unsize successful");
260                return unsize;
261            }
262            Err(error) => {
263                debug!(?error, "coerce: unsize failed");
264            }
265        }
266
267        // Examine the supertype and consider type-specific coercions, such
268        // as auto-borrowing, coercing pointer mutability, a `dyn*` coercion,
269        // or pin-ergonomics.
270        match b.kind() {
271            TyKind::RawPtr(_, b_mutbl) => {
272                return self.coerce_raw_ptr(a, b, b_mutbl);
273            }
274            TyKind::Ref(r_b, _, mutbl_b) => {
275                return self.coerce_borrowed_pointer(a, b, r_b, mutbl_b);
276            }
277            _ => {}
278        }
279
280        match a.kind() {
281            TyKind::FnDef(..) => {
282                // Function items are coercible to any closure
283                // type; function pointers are not (that would
284                // require double indirection).
285                // Additionally, we permit coercion of function
286                // items to drop the unsafe qualifier.
287                self.coerce_from_fn_item(a, b)
288            }
289            TyKind::FnPtr(a_sig_tys, a_hdr) => {
290                // We permit coercion of fn pointers to drop the
291                // unsafe qualifier.
292                self.coerce_from_fn_pointer(a_sig_tys.with(a_hdr), b)
293            }
294            TyKind::Closure(closure_def_id_a, args_a) => {
295                // Non-capturing closures are coercible to
296                // function pointers or unsafe function pointers.
297                // It cannot convert closures that require unsafe.
298                self.coerce_closure_to_fn(a, closure_def_id_a.0, args_a, b)
299            }
300            _ => {
301                // Otherwise, just use unification rules.
302                self.unify(a, b)
303            }
304        }
305    }
306
307    /// Coercing *from* an inference variable. In this case, we have no information
308    /// about the source type, so we can't really do a true coercion and we always
309    /// fall back to subtyping (`unify_and`).
310    fn coerce_from_inference_variable(&mut self, a: Ty<'db>, b: Ty<'db>) -> CoerceResult<'db> {
311        debug!("coerce_from_inference_variable(a={:?}, b={:?})", a, b);
312        debug_assert!(a.is_infer() && self.infcx().shallow_resolve(a) == a);
313        debug_assert!(self.infcx().shallow_resolve(b) == b);
314
315        if b.is_infer() {
316            // Two unresolved type variables: create a `Coerce` predicate.
317            let target_ty =
318                if self.use_lub { self.infcx().next_ty_var(self.cause.span()) } else { b };
319
320            let mut obligations = PredicateObligations::with_capacity(2);
321            for &source_ty in &[a, b] {
322                if source_ty != target_ty {
323                    obligations.push(Obligation::new(
324                        self.interner(),
325                        self.cause,
326                        self.param_env(),
327                        Binder::dummy(PredicateKind::Coerce(CoercePredicate {
328                            a: source_ty,
329                            b: target_ty,
330                        })),
331                    ));
332                }
333            }
334
335            debug!(
336                "coerce_from_inference_variable: two inference variables, target_ty={:?}, obligations={:?}",
337                target_ty, obligations
338            );
339            success(vec![], target_ty, obligations)
340        } else {
341            // One unresolved type variable: just apply subtyping, we may be able
342            // to do something useful.
343            self.unify(a, b)
344        }
345    }
346
347    /// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
348    /// To match `A` with `B`, autoderef will be performed,
349    /// calling `deref`/`deref_mut` where necessary.
350    fn coerce_borrowed_pointer(
351        &mut self,
352        a: Ty<'db>,
353        b: Ty<'db>,
354        r_b: Region<'db>,
355        mutbl_b: Mutability,
356    ) -> CoerceResult<'db> {
357        debug!("coerce_borrowed_pointer(a={:?}, b={:?})", a, b);
358        debug_assert!(self.infcx().shallow_resolve(a) == a);
359        debug_assert!(self.infcx().shallow_resolve(b) == b);
360
361        // If we have a parameter of type `&M T_a` and the value
362        // provided is `expr`, we will be adding an implicit borrow,
363        // meaning that we convert `f(expr)` to `f(&M *expr)`. Therefore,
364        // to type check, we will construct the type that `&M*expr` would
365        // yield.
366
367        let (r_a, mt_a) = match a.kind() {
368            TyKind::Ref(r_a, ty, mutbl) => {
369                let mt_a = TypeAndMut::<DbInterner<'db>> { ty, mutbl };
370                coerce_mutbls(mt_a.mutbl, mutbl_b)?;
371                (r_a, mt_a)
372            }
373            _ => return self.unify(a, b),
374        };
375
376        let mut first_error = None;
377        let mut r_borrow_var = None;
378        let mut autoderef =
379            Autoderef::new_with_tracking(self.infcx(), self.param_env(), a, self.cause.span());
380        let mut found = None;
381
382        for (referent_ty, autoderefs) in autoderef.by_ref() {
383            if autoderefs == 0 {
384                // Don't let this pass, otherwise it would cause
385                // &T to autoref to &&T.
386                continue;
387            }
388
389            // At this point, we have deref'd `a` to `referent_ty`. So
390            // imagine we are coercing from `&'a mut Vec<T>` to `&'b mut [T]`.
391            // In the autoderef loop for `&'a mut Vec<T>`, we would get
392            // three callbacks:
393            //
394            // - `&'a mut Vec<T>` -- 0 derefs, just ignore it
395            // - `Vec<T>` -- 1 deref
396            // - `[T]` -- 2 deref
397            //
398            // At each point after the first callback, we want to
399            // check to see whether this would match out target type
400            // (`&'b mut [T]`) if we autoref'd it. We can't just
401            // compare the referent types, though, because we still
402            // have to consider the mutability. E.g., in the case
403            // we've been considering, we have an `&mut` reference, so
404            // the `T` in `[T]` needs to be unified with equality.
405            //
406            // Therefore, we construct reference types reflecting what
407            // the types will be after we do the final auto-ref and
408            // compare those. Note that this means we use the target
409            // mutability [1], since it may be that we are coercing
410            // from `&mut T` to `&U`.
411            //
412            // One fine point concerns the region that we use. We
413            // choose the region such that the region of the final
414            // type that results from `unify` will be the region we
415            // want for the autoref:
416            //
417            // - if in sub mode, that means we want to use `'b` (the
418            //   region from the target reference) for both
419            //   pointers [2]. This is because sub mode (somewhat
420            //   arbitrarily) returns the subtype region. In the case
421            //   where we are coercing to a target type, we know we
422            //   want to use that target type region (`'b`) because --
423            //   for the program to type-check -- it must be the
424            //   smaller of the two.
425            //   - One fine point. It may be surprising that we can
426            //     use `'b` without relating `'a` and `'b`. The reason
427            //     that this is ok is that what we produce is
428            //     effectively a `&'b *x` expression (if you could
429            //     annotate the region of a borrow), and regionck has
430            //     code that adds edges from the region of a borrow
431            //     (`'b`, here) into the regions in the borrowed
432            //     expression (`*x`, here). (Search for "link".)
433            // - if in lub mode, things can get fairly complicated. The
434            //   easiest thing is just to make a fresh
435            //   region variable [4], which effectively means we defer
436            //   the decision to region inference (and regionck, which will add
437            //   some more edges to this variable). However, this can wind up
438            //   creating a crippling number of variables in some cases --
439            //   e.g., #32278 -- so we optimize one particular case [3].
440            //   Let me try to explain with some examples:
441            //   - The "running example" above represents the simple case,
442            //     where we have one `&` reference at the outer level and
443            //     ownership all the rest of the way down. In this case,
444            //     we want `LUB('a, 'b)` as the resulting region.
445            //   - However, if there are nested borrows, that region is
446            //     too strong. Consider a coercion from `&'a &'x Rc<T>` to
447            //     `&'b T`. In this case, `'a` is actually irrelevant.
448            //     The pointer we want is `LUB('x, 'b`). If we choose `LUB('a,'b)`
449            //     we get spurious errors (`ui/regions-lub-ref-ref-rc.rs`).
450            //     (The errors actually show up in borrowck, typically, because
451            //     this extra edge causes the region `'a` to be inferred to something
452            //     too big, which then results in borrowck errors.)
453            //   - We could track the innermost shared reference, but there is already
454            //     code in regionck that has the job of creating links between
455            //     the region of a borrow and the regions in the thing being
456            //     borrowed (here, `'a` and `'x`), and it knows how to handle
457            //     all the various cases. So instead we just make a region variable
458            //     and let regionck figure it out.
459            let r = if !self.use_lub {
460                r_b // [2] above
461            } else if autoderefs == 1 {
462                r_a // [3] above
463            } else {
464                if r_borrow_var.is_none() {
465                    // create var lazily, at most once
466                    let r = self.infcx().next_region_var(self.cause.span());
467                    r_borrow_var = Some(r); // [4] above
468                }
469                r_borrow_var.unwrap()
470            };
471            let derefd_ty_a = Ty::new_ref(
472                self.interner(),
473                r,
474                referent_ty,
475                mutbl_b, // [1] above
476            );
477            match self.unify_raw(derefd_ty_a, b) {
478                Ok(ok) => {
479                    found = Some(ok);
480                    break;
481                }
482                Err(err) => {
483                    if first_error.is_none() {
484                        first_error = Some(err);
485                    }
486                }
487            }
488        }
489
490        // Extract type or return an error. We return the first error
491        // we got, which should be from relating the "base" type
492        // (e.g., in example above, the failure from relating `Vec<T>`
493        // to the target type), since that should be the least
494        // confusing.
495        let Some(InferOk { value: ty, mut obligations }) = found else {
496            if let Some(first_error) = first_error {
497                debug!("coerce_borrowed_pointer: failed with err = {:?}", first_error);
498                return Err(first_error);
499            } else {
500                // This may happen in the new trait solver since autoderef requires
501                // the pointee to be structurally normalizable, or else it'll just bail.
502                // So when we have a type like `&<not well formed>`, then we get no
503                // autoderef steps (even though there should be at least one). That means
504                // we get no type mismatches, since the loop above just exits early.
505                return Err(TypeError::Mismatch);
506            }
507        };
508
509        if ty == a && mt_a.mutbl.is_not() && autoderef.step_count() == 1 {
510            // As a special case, if we would produce `&'a *x`, that's
511            // a total no-op. We end up with the type `&'a T` just as
512            // we started with. In that case, just skip it
513            // altogether. This is just an optimization.
514            //
515            // Note that for `&mut`, we DO want to reborrow --
516            // otherwise, this would be a move, which might be an
517            // error. For example `foo(self.x)` where `self` and
518            // `self.x` both have `&mut `type would be a move of
519            // `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
520            // which is a borrow.
521            assert!(mutbl_b.is_not()); // can only coerce &T -> &U
522            return success(vec![], ty, obligations);
523        }
524
525        let InferOk { value: mut adjustments, obligations: o } =
526            autoderef.adjust_steps_as_infer_ok();
527        obligations.extend(o);
528
529        // Now apply the autoref.
530        let mutbl = AutoBorrowMutability::new(mutbl_b, self.allow_two_phase);
531        adjustments
532            .push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)), target: ty.store() });
533
534        debug!("coerce_borrowed_pointer: succeeded ty={:?} adjustments={:?}", ty, adjustments);
535
536        success(adjustments, ty, obligations)
537    }
538
539    /// Performs [unsized coercion] by emulating a fulfillment loop on a
540    /// `CoerceUnsized` goal until all `CoerceUnsized` and `Unsize` goals
541    /// are successfully selected.
542    ///
543    /// [unsized coercion](https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions)
544    #[instrument(skip(self), level = "debug")]
545    fn coerce_unsized(&mut self, source: Ty<'db>, target: Ty<'db>) -> CoerceResult<'db> {
546        debug!(?source, ?target);
547        debug_assert!(self.infcx().shallow_resolve(source) == source);
548        debug_assert!(self.infcx().shallow_resolve(target) == target);
549
550        // We don't apply any coercions incase either the source or target
551        // aren't sufficiently well known but tend to instead just equate
552        // them both.
553        if source.is_infer() {
554            debug!("coerce_unsized: source is a TyVar, bailing out");
555            return Err(TypeError::Mismatch);
556        }
557        if target.is_infer() {
558            debug!("coerce_unsized: target is a TyVar, bailing out");
559            return Err(TypeError::Mismatch);
560        }
561
562        // This is an optimization because coercion is one of the most common
563        // operations that we do in typeck, since it happens at every assignment
564        // and call arg (among other positions).
565        //
566        // These targets are known to never be RHS in `LHS: CoerceUnsized<RHS>`.
567        // That's because these are built-in types for which a core-provided impl
568        // doesn't exist, and for which a user-written impl is invalid.
569        //
570        // This is technically incomplete when users write impossible bounds like
571        // `where T: CoerceUnsized<usize>`, for example, but that trait is unstable
572        // and coercion is allowed to be incomplete. The only case where this matters
573        // is impossible bounds.
574        //
575        // Note that some of these types implement `LHS: Unsize<RHS>`, but they
576        // do not implement *`CoerceUnsized`* which is the root obligation of the
577        // check below.
578        match target.kind() {
579            TyKind::Bool
580            | TyKind::Char
581            | TyKind::Int(_)
582            | TyKind::Uint(_)
583            | TyKind::Float(_)
584            | TyKind::Infer(rustc_type_ir::IntVar(_) | rustc_type_ir::FloatVar(_))
585            | TyKind::Str
586            | TyKind::Array(_, _)
587            | TyKind::Slice(_)
588            | TyKind::FnDef(_, _)
589            | TyKind::FnPtr(_, _)
590            | TyKind::Dynamic(_, _)
591            | TyKind::Closure(_, _)
592            | TyKind::CoroutineClosure(_, _)
593            | TyKind::Coroutine(_, _)
594            | TyKind::CoroutineWitness(_, _)
595            | TyKind::Never
596            | TyKind::Tuple(_) => return Err(TypeError::Mismatch),
597            _ => {}
598        }
599        // Additionally, we ignore `&str -> &str` coercions, which happen very
600        // commonly since strings are one of the most used argument types in Rust,
601        // we do coercions when type checking call expressions.
602        if let TyKind::Ref(_, source_pointee, Mutability::Not) = source.kind()
603            && source_pointee.is_str()
604            && let TyKind::Ref(_, target_pointee, Mutability::Not) = target.kind()
605            && target_pointee.is_str()
606        {
607            return Err(TypeError::Mismatch);
608        }
609
610        let lang_items = self.interner().lang_items();
611        let traits = (lang_items.Unsize, lang_items.CoerceUnsized);
612        let (Some(unsize_did), Some(coerce_unsized_did)) = traits else {
613            debug!("missing Unsize or CoerceUnsized traits");
614            return Err(TypeError::Mismatch);
615        };
616
617        // Note, we want to avoid unnecessary unsizing. We don't want to coerce to
618        // a DST unless we have to. This currently comes out in the wash since
619        // we can't unify [T] with U. But to properly support DST, we need to allow
620        // that, at which point we will need extra checks on the target here.
621
622        // Handle reborrows before selecting `Source: CoerceUnsized<Target>`.
623        let reborrow = match (source.kind(), target.kind()) {
624            (TyKind::Ref(_, ty_a, mutbl_a), TyKind::Ref(_, _, mutbl_b)) => {
625                coerce_mutbls(mutbl_a, mutbl_b)?;
626
627                let r_borrow = self.infcx().next_region_var(self.cause.span());
628
629                // We don't allow two-phase borrows here, at least for initial
630                // implementation. If it happens that this coercion is a function argument,
631                // the reborrow in coerce_borrowed_ptr will pick it up.
632                let mutbl = AutoBorrowMutability::new(mutbl_b, AllowTwoPhase::No);
633
634                Some((
635                    Adjustment { kind: Adjust::Deref(None), target: ty_a.store() },
636                    Adjustment {
637                        kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
638                        target: Ty::new_ref(self.interner(), r_borrow, ty_a, mutbl_b).store(),
639                    },
640                ))
641            }
642            (TyKind::Ref(_, ty_a, mt_a), TyKind::RawPtr(_, mt_b)) => {
643                coerce_mutbls(mt_a, mt_b)?;
644
645                Some((
646                    Adjustment { kind: Adjust::Deref(None), target: ty_a.store() },
647                    Adjustment {
648                        kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b)),
649                        target: Ty::new_ptr(self.interner(), ty_a, mt_b).store(),
650                    },
651                ))
652            }
653            _ => None,
654        };
655        let coerce_source = reborrow.as_ref().map_or(source, |(_, r)| r.target.as_ref());
656
657        // Setup either a subtyping or a LUB relationship between
658        // the `CoerceUnsized` target type and the expected type.
659        // We only have the latter, so we use an inference variable
660        // for the former and let type inference do the rest.
661        let coerce_target = self.infcx().next_ty_var(self.cause.span());
662
663        let mut coercion = self.unify_and(
664            coerce_target,
665            target,
666            reborrow.into_iter().flat_map(|(deref, autoref)| [deref, autoref]),
667            Adjust::Pointer(PointerCast::Unsize),
668        )?;
669
670        // Create an obligation for `Source: CoerceUnsized<Target>`.
671        let cause = self.cause;
672        let pred = TraitRef::new(
673            self.interner(),
674            coerce_unsized_did.into(),
675            [coerce_source, coerce_target],
676        );
677        let obligation = Obligation::new(self.interner(), cause, self.param_env(), pred);
678
679        coercion.obligations.push(obligation);
680
681        if self
682            .delegate
683            .infcx()
684            .visit_proof_tree(
685                Goal::new(self.infcx().interner, self.param_env(), pred),
686                &mut CoerceVisitor {
687                    delegate: &self.delegate,
688                    errored: false,
689                    unsize_did,
690                    coerce_unsized_did,
691                    span: self.cause.span(),
692                },
693            )
694            .is_break()
695        {
696            return Err(TypeError::Mismatch);
697        }
698
699        Ok(coercion)
700    }
701
702    fn coerce_from_safe_fn(
703        &mut self,
704        fn_ty_a: PolyFnSig<'db>,
705        b: Ty<'db>,
706        adjustment: Option<Adjust>,
707    ) -> CoerceResult<'db> {
708        debug_assert!(self.infcx().shallow_resolve(b) == b);
709
710        self.commit_if_ok(|this| {
711            if let TyKind::FnPtr(_, hdr_b) = b.kind()
712                && fn_ty_a.safety().is_safe()
713                && !hdr_b.safety().is_safe()
714            {
715                let unsafe_a = Ty::safe_to_unsafe_fn_ty(this.interner(), fn_ty_a);
716                this.unify_and(
717                    unsafe_a,
718                    b,
719                    adjustment.map(|kind| Adjustment {
720                        kind,
721                        target: Ty::new_fn_ptr(this.interner(), fn_ty_a).store(),
722                    }),
723                    Adjust::Pointer(PointerCast::UnsafeFnPointer),
724                )
725            } else {
726                let a = Ty::new_fn_ptr(this.interner(), fn_ty_a);
727                match adjustment {
728                    Some(adjust) => this.unify_and(a, b, [], adjust),
729                    None => this.unify(a, b),
730                }
731            }
732        })
733    }
734
735    fn coerce_from_fn_pointer(&mut self, fn_ty_a: PolyFnSig<'db>, b: Ty<'db>) -> CoerceResult<'db> {
736        debug!(?fn_ty_a, ?b, "coerce_from_fn_pointer");
737        debug_assert!(self.infcx().shallow_resolve(b) == b);
738
739        self.coerce_from_safe_fn(fn_ty_a, b, None)
740    }
741
742    fn coerce_from_fn_item(&mut self, a: Ty<'db>, b: Ty<'db>) -> CoerceResult<'db> {
743        debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
744        debug_assert!(self.infcx().shallow_resolve(a) == a);
745        debug_assert!(self.infcx().shallow_resolve(b) == b);
746
747        match b.kind() {
748            TyKind::FnPtr(_, b_hdr) => {
749                let a_sig = a.fn_sig(self.interner());
750                if let TyKind::FnDef(def_id, _) = a.kind() {
751                    // Intrinsics are not coercible to function pointers
752                    if let CallableDefId::FunctionId(def_id) = def_id.0 {
753                        if FunctionSignature::is_intrinsic(self.db(), def_id) {
754                            return Err(TypeError::IntrinsicCast);
755                        }
756
757                        let attrs = AttrFlags::query(self.db(), def_id.into());
758                        if attrs.contains(AttrFlags::RUSTC_FORCE_INLINE) {
759                            return Err(TypeError::ForceInlineCast);
760                        }
761
762                        if b_hdr.safety().is_safe() && attrs.contains(AttrFlags::HAS_TARGET_FEATURE)
763                        {
764                            let fn_target_features =
765                                TargetFeatures::from_fn_no_implications(self.db(), def_id);
766                            // Allow the coercion if the current function has all the features that would be
767                            // needed to call the coercee safely.
768                            let (target_features, target_feature_is_safe) =
769                                self.delegate.target_features();
770                            if target_feature_is_safe == TargetFeatureIsSafeInTarget::No
771                                && !target_features.enabled.is_superset(&fn_target_features.enabled)
772                            {
773                                return Err(TypeError::TargetFeatureCast(
774                                    CallableIdWrapper(def_id.into()).into(),
775                                ));
776                            }
777                        }
778                    }
779                }
780
781                self.coerce_from_safe_fn(
782                    a_sig,
783                    b,
784                    Some(Adjust::Pointer(PointerCast::ReifyFnPointer)),
785                )
786            }
787            _ => self.unify(a, b),
788        }
789    }
790
791    /// Attempts to coerce from the type of a non-capturing closure
792    /// into a function pointer.
793    fn coerce_closure_to_fn(
794        &mut self,
795        a: Ty<'db>,
796        closure_def_id_a: InternedClosureId<'db>,
797        args_a: GenericArgs<'db>,
798        b: Ty<'db>,
799    ) -> CoerceResult<'db> {
800        debug_assert!(self.infcx().shallow_resolve(a) == a);
801        debug_assert!(self.infcx().shallow_resolve(b) == b);
802
803        match b.kind() {
804            TyKind::FnPtr(_, hdr) if !is_capturing_closure(self.db(), closure_def_id_a) => {
805                // We coerce the closure, which has fn type
806                //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
807                // to
808                //     `fn(arg0,arg1,...) -> _`
809                // or
810                //     `unsafe fn(arg0,arg1,...) -> _`
811                let safety = hdr.safety();
812                let closure_sig =
813                    self.interner().signature_unclosure(args_a.as_closure().sig(), safety);
814                let pointer_ty = Ty::new_fn_ptr(self.interner(), closure_sig);
815                debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty);
816                self.unify_and(
817                    pointer_ty,
818                    b,
819                    [],
820                    Adjust::Pointer(PointerCast::ClosureFnPointer(safety)),
821                )
822            }
823            _ => self.unify(a, b),
824        }
825    }
826
827    fn coerce_raw_ptr(&mut self, a: Ty<'db>, b: Ty<'db>, mutbl_b: Mutability) -> CoerceResult<'db> {
828        debug!("coerce_raw_ptr(a={:?}, b={:?})", a, b);
829        debug_assert!(self.infcx().shallow_resolve(a) == a);
830        debug_assert!(self.infcx().shallow_resolve(b) == b);
831
832        let (is_ref, mt_a) = match a.kind() {
833            TyKind::Ref(_, ty, mutbl) => (true, TypeAndMut::<DbInterner<'db>> { ty, mutbl }),
834            TyKind::RawPtr(ty, mutbl) => (false, TypeAndMut { ty, mutbl }),
835            _ => return self.unify(a, b),
836        };
837        coerce_mutbls(mt_a.mutbl, mutbl_b)?;
838
839        // Check that the types which they point at are compatible.
840        let a_raw = Ty::new_ptr(self.interner(), mt_a.ty, mutbl_b);
841        // Although references and raw ptrs have the same
842        // representation, we still register an Adjust::DerefRef so that
843        // regionck knows that the region for `a` must be valid here.
844        if is_ref {
845            self.unify_and(
846                a_raw,
847                b,
848                [Adjustment { kind: Adjust::Deref(None), target: mt_a.ty.store() }],
849                Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)),
850            )
851        } else if mt_a.mutbl != mutbl_b {
852            self.unify_and(a_raw, b, [], Adjust::Pointer(PointerCast::MutToConstPointer))
853        } else {
854            self.unify(a_raw, b)
855        }
856    }
857}
858
859struct InferenceCoercionDelegate<'a, 'db>(&'a mut InferenceContext<'db>);
860
861impl<'db> CoerceDelegate<'db> for InferenceCoercionDelegate<'_, 'db> {
862    #[inline]
863    fn infcx(&self) -> &InferCtxt<'db> {
864        &self.0.table.infer_ctxt
865    }
866    #[inline]
867    fn param_env(&self) -> ParamEnv<'db> {
868        self.0.table.param_env
869    }
870
871    #[inline]
872    fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget) {
873        self.0.target_features()
874    }
875
876    #[inline]
877    fn set_diverging(&mut self, diverging_ty: Ty<'db>) {
878        self.0.table.set_diverging(diverging_ty);
879    }
880
881    #[inline]
882    fn type_var_is_sized(&self, var: TyVid) -> bool {
883        self.0.table.type_var_is_sized(var)
884    }
885}
886
887impl<'db> InferenceContext<'db> {
888    /// Attempt to coerce an expression to a type, and return the
889    /// adjusted type of the expression, if successful.
890    /// Adjustments are only recorded if the coercion succeeded.
891    /// The expressions *must not* have any preexisting adjustments.
892    pub(crate) fn coerce(
893        &mut self,
894        expr: ExprId,
895        expr_ty: Ty<'db>,
896        mut target: Ty<'db>,
897        allow_two_phase: AllowTwoPhase,
898        expr_is_read: ExprIsRead,
899    ) -> RelateResult<'db, Ty<'db>> {
900        let source = self.table.try_structurally_resolve_type(expr.into(), expr_ty);
901        target = self.table.try_structurally_resolve_type(expr.into(), target);
902        debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
903
904        let cause = ObligationCause::new(expr);
905        let coerce_never = self.expr_guaranteed_to_constitute_read_for_never(expr, expr_is_read);
906        let mut coerce = Coerce {
907            delegate: InferenceCoercionDelegate(self),
908            cause,
909            allow_two_phase,
910            coerce_never,
911            use_lub: false,
912        };
913        let ok = coerce.commit_if_ok(|coerce| coerce.coerce(source, target))?;
914
915        let (adjustments, _) = self.table.register_infer_ok(ok);
916        self.write_expr_adj(expr, adjustments.into_boxed_slice());
917        Ok(target)
918    }
919
920    /// Given some expressions, their known unified type and another expression,
921    /// tries to unify the types, potentially inserting coercions on any of the
922    /// provided expressions and returns their LUB (aka "common supertype").
923    ///
924    /// This is really an internal helper. From outside the coercion
925    /// module, you should instantiate a `CoerceMany` instance.
926    fn try_find_coercion_lub(
927        &mut self,
928        exprs: &[ExprId],
929        prev_ty: Ty<'db>,
930        new: ExprId,
931        new_ty: Ty<'db>,
932    ) -> RelateResult<'db, Ty<'db>> {
933        let prev_ty = self.table.try_structurally_resolve_type(new.into(), prev_ty);
934        let new_ty = self.table.try_structurally_resolve_type(new.into(), new_ty);
935        debug!(
936            "coercion::try_find_coercion_lub({:?}, {:?}, exprs={:?} exprs)",
937            prev_ty,
938            new_ty,
939            exprs.len()
940        );
941
942        // The following check fixes #88097, where the compiler erroneously
943        // attempted to coerce a closure type to itself via a function pointer.
944        if prev_ty == new_ty {
945            return Ok(prev_ty);
946        }
947
948        let is_force_inline = |ty: Ty<'db>| {
949            if let TyKind::FnDef(CallableIdWrapper(CallableDefId::FunctionId(did)), _) = ty.kind() {
950                AttrFlags::query(self.db, did.into()).contains(AttrFlags::RUSTC_FORCE_INLINE)
951            } else {
952                false
953            }
954        };
955        if is_force_inline(prev_ty) || is_force_inline(new_ty) {
956            return Err(TypeError::ForceInlineCast);
957        }
958
959        // Special-case that coercion alone cannot handle:
960        // Function items or non-capturing closures of differing IDs or GenericArgs.
961        let (a_sig, b_sig) = {
962            let is_capturing_closure = |ty: Ty<'db>| {
963                if let TyKind::Closure(closure_def_id, _args) = ty.kind() {
964                    is_capturing_closure(self.db, closure_def_id.0)
965                } else {
966                    false
967                }
968            };
969            if is_capturing_closure(prev_ty) || is_capturing_closure(new_ty) {
970                (None, None)
971            } else {
972                match (prev_ty.kind(), new_ty.kind()) {
973                    (TyKind::FnDef(..), TyKind::FnDef(..)) => {
974                        // Don't reify if the function types have a LUB, i.e., they
975                        // are the same function and their parameters have a LUB.
976                        match self.table.commit_if_ok(|table| {
977                            // We need to eagerly handle nested obligations due to lazy norm.
978                            let mut ocx = ObligationCtxt::new(&table.infer_ctxt);
979                            let value = ocx.lub(
980                                &ObligationCause::new(new),
981                                table.param_env,
982                                prev_ty,
983                                new_ty,
984                            )?;
985                            if ocx.try_evaluate_obligations().is_empty() {
986                                Ok(InferOk { value, obligations: ocx.into_pending_obligations() })
987                            } else {
988                                Err(TypeError::Mismatch)
989                            }
990                        }) {
991                            // We have a LUB of prev_ty and new_ty, just return it.
992                            Ok(ok) => return Ok(self.table.register_infer_ok(ok)),
993                            Err(_) => (
994                                Some(prev_ty.fn_sig(self.table.interner())),
995                                Some(new_ty.fn_sig(self.table.interner())),
996                            ),
997                        }
998                    }
999                    (TyKind::Closure(_, args), TyKind::FnDef(..)) => {
1000                        let b_sig = new_ty.fn_sig(self.table.interner());
1001                        let a_sig = self
1002                            .interner()
1003                            .signature_unclosure(args.as_closure().sig(), b_sig.safety());
1004                        (Some(a_sig), Some(b_sig))
1005                    }
1006                    (TyKind::FnDef(..), TyKind::Closure(_, args)) => {
1007                        let a_sig = prev_ty.fn_sig(self.table.interner());
1008                        let b_sig = self
1009                            .interner()
1010                            .signature_unclosure(args.as_closure().sig(), a_sig.safety());
1011                        (Some(a_sig), Some(b_sig))
1012                    }
1013                    (TyKind::Closure(_, args_a), TyKind::Closure(_, args_b)) => (
1014                        Some(
1015                            self.interner()
1016                                .signature_unclosure(args_a.as_closure().sig(), Safety::Safe),
1017                        ),
1018                        Some(
1019                            self.interner()
1020                                .signature_unclosure(args_b.as_closure().sig(), Safety::Safe),
1021                        ),
1022                    ),
1023                    _ => (None, None),
1024                }
1025            }
1026        };
1027        if let (Some(a_sig), Some(b_sig)) = (a_sig, b_sig) {
1028            // The signature must match.
1029            let sig = self
1030                .table
1031                .infer_ctxt
1032                .at(&ObligationCause::new(new), self.table.param_env)
1033                .lub(a_sig, b_sig)
1034                .map(|ok| self.table.register_infer_ok(ok))?;
1035
1036            // Reify both sides and return the reified fn pointer type.
1037            let fn_ptr = Ty::new_fn_ptr(self.table.interner(), sig);
1038            let prev_adjustment = match prev_ty.kind() {
1039                TyKind::Closure(..) => {
1040                    Adjust::Pointer(PointerCast::ClosureFnPointer(a_sig.safety()))
1041                }
1042                TyKind::FnDef(..) => Adjust::Pointer(PointerCast::ReifyFnPointer),
1043                _ => panic!("should not try to coerce a {prev_ty:?} to a fn pointer"),
1044            };
1045            let next_adjustment = match new_ty.kind() {
1046                TyKind::Closure(..) => {
1047                    Adjust::Pointer(PointerCast::ClosureFnPointer(b_sig.safety()))
1048                }
1049                TyKind::FnDef(..) => Adjust::Pointer(PointerCast::ReifyFnPointer),
1050                _ => panic!("should not try to coerce a {new_ty:?} to a fn pointer"),
1051            };
1052            for &expr in exprs {
1053                self.write_expr_adj(
1054                    expr,
1055                    Box::new([Adjustment {
1056                        kind: prev_adjustment.clone(),
1057                        target: fn_ptr.store(),
1058                    }]),
1059                );
1060            }
1061            self.write_expr_adj(
1062                new,
1063                Box::new([Adjustment { kind: next_adjustment, target: fn_ptr.store() }]),
1064            );
1065            return Ok(fn_ptr);
1066        }
1067
1068        // Configure a Coerce instance to compute the LUB.
1069        // We don't allow two-phase borrows on any autorefs this creates since we
1070        // probably aren't processing function arguments here and even if we were,
1071        // they're going to get autorefed again anyway and we can apply 2-phase borrows
1072        // at that time.
1073        //
1074        // NOTE: we set `coerce_never` to `true` here because coercion LUBs only
1075        // operate on values and not places, so a never coercion is valid.
1076        let mut coerce = Coerce {
1077            delegate: InferenceCoercionDelegate(self),
1078            cause: ObligationCause::new(new),
1079            allow_two_phase: AllowTwoPhase::No,
1080            coerce_never: true,
1081            use_lub: true,
1082        };
1083
1084        // First try to coerce the new expression to the type of the previous ones,
1085        // but only if the new expression has no coercion already applied to it.
1086        let mut first_error = None;
1087        if !coerce.delegate.0.result.expr_adjustments.contains_key(&new) {
1088            let result = coerce.commit_if_ok(|coerce| coerce.coerce(new_ty, prev_ty));
1089            match result {
1090                Ok(ok) => {
1091                    let (adjustments, target) = self.table.register_infer_ok(ok);
1092                    self.write_expr_adj(new, adjustments.into_boxed_slice());
1093                    debug!(
1094                        "coercion::try_find_coercion_lub: was able to coerce from new type {:?} to previous type {:?} ({:?})",
1095                        new_ty, prev_ty, target
1096                    );
1097                    return Ok(target);
1098                }
1099                Err(e) => first_error = Some(e),
1100            }
1101        }
1102
1103        match coerce.commit_if_ok(|coerce| coerce.coerce(prev_ty, new_ty)) {
1104            Err(_) => {
1105                // Avoid giving strange errors on failed attempts.
1106                if let Some(e) = first_error {
1107                    Err(e)
1108                } else {
1109                    Err(self
1110                        .table
1111                        .commit_if_ok(|table| {
1112                            table
1113                                .infer_ctxt
1114                                .at(&ObligationCause::new(new), table.param_env)
1115                                .lub(prev_ty, new_ty)
1116                        })
1117                        .unwrap_err())
1118                }
1119            }
1120            Ok(ok) => {
1121                let (adjustments, target) = self.table.register_infer_ok(ok);
1122                for &expr in exprs {
1123                    self.write_expr_adj(expr, adjustments.as_slice().into());
1124                }
1125                debug!(
1126                    "coercion::try_find_coercion_lub: was able to coerce previous type {:?} to new type {:?} ({:?})",
1127                    prev_ty, new_ty, target
1128                );
1129                Ok(target)
1130            }
1131        }
1132    }
1133}
1134
1135/// CoerceMany encapsulates the pattern you should use when you have
1136/// many expressions that are all getting coerced to a common
1137/// type. This arises, for example, when you have a match (the result
1138/// of each arm is coerced to a common type). It also arises in less
1139/// obvious places, such as when you have many `break foo` expressions
1140/// that target the same loop, or the various `return` expressions in
1141/// a function.
1142///
1143/// The basic protocol is as follows:
1144///
1145/// - Instantiate the `CoerceMany` with an initial `expected_ty`.
1146///   This will also serve as the "starting LUB". The expectation is
1147///   that this type is something which all of the expressions *must*
1148///   be coercible to. Use a fresh type variable if needed.
1149/// - For each expression whose result is to be coerced, invoke `coerce()` with.
1150///   - In some cases we wish to coerce "non-expressions" whose types are implicitly
1151///     unit. This happens for example if you have a `break` with no expression,
1152///     or an `if` with no `else`. In that case, invoke `coerce_forced_unit()`.
1153///   - `coerce()` and `coerce_forced_unit()` may report errors. They hide this
1154///     from you so that you don't have to worry your pretty head about it.
1155///     But if an error is reported, the final type will be `err`.
1156///   - Invoking `coerce()` may cause us to go and adjust the "adjustments" on
1157///     previously coerced expressions.
1158/// - When all done, invoke `complete()`. This will return the LUB of
1159///   all your expressions.
1160///   - WARNING: I don't believe this final type is guaranteed to be
1161///     related to your initial `expected_ty` in any particular way,
1162///     although it will typically be a subtype, so you should check it.
1163///   - Invoking `complete()` may cause us to go and adjust the "adjustments" on
1164///     previously coerced expressions.
1165///
1166/// Example:
1167///
1168/// ```ignore (illustrative)
1169/// let mut coerce = CoerceMany::new(expected_ty);
1170/// for expr in exprs {
1171///     let expr_ty = fcx.check_expr_with_expectation(expr, expected);
1172///     coerce.coerce(fcx, &cause, expr, expr_ty);
1173/// }
1174/// let final_ty = coerce.complete(fcx);
1175/// ```
1176#[derive(Debug, Clone)]
1177pub(crate) struct CoerceMany<'db, 'exprs> {
1178    expected_ty: Ty<'db>,
1179    final_ty: Option<Ty<'db>>,
1180    expressions: Expressions<'exprs>,
1181    pushed: usize,
1182}
1183
1184/// The type of a `CoerceMany` that is storing up the expressions into
1185/// a buffer. We use this for things like `break`.
1186pub(crate) type DynamicCoerceMany<'db> = CoerceMany<'db, 'db>;
1187
1188#[derive(Debug, Clone)]
1189enum Expressions<'exprs> {
1190    Dynamic(SmallVec<[ExprId; 4]>),
1191    UpFront(&'exprs [ExprId]),
1192}
1193
1194impl<'db, 'exprs> CoerceMany<'db, 'exprs> {
1195    /// The usual case; collect the set of expressions dynamically.
1196    /// If the full set of coercion sites is known before hand,
1197    /// consider `with_coercion_sites()` instead to avoid allocation.
1198    pub(crate) fn new(expected_ty: Ty<'db>) -> Self {
1199        Self::make(expected_ty, Expressions::Dynamic(SmallVec::new()))
1200    }
1201
1202    /// As an optimization, you can create a `CoerceMany` with a
1203    /// preexisting slice of expressions. In this case, you are
1204    /// expected to pass each element in the slice to `coerce(...)` in
1205    /// order. This is used with arrays in particular to avoid
1206    /// needlessly cloning the slice.
1207    pub(crate) fn with_coercion_sites(
1208        expected_ty: Ty<'db>,
1209        coercion_sites: &'exprs [ExprId],
1210    ) -> Self {
1211        Self::make(expected_ty, Expressions::UpFront(coercion_sites))
1212    }
1213
1214    fn make(expected_ty: Ty<'db>, expressions: Expressions<'exprs>) -> Self {
1215        CoerceMany { expected_ty, final_ty: None, expressions, pushed: 0 }
1216    }
1217
1218    /// Returns the "expected type" with which this coercion was
1219    /// constructed. This represents the "downward propagated" type
1220    /// that was given to us at the start of typing whatever construct
1221    /// we are typing (e.g., the match expression).
1222    ///
1223    /// Typically, this is used as the expected type when
1224    /// type-checking each of the alternative expressions whose types
1225    /// we are trying to merge.
1226    pub(crate) fn expected_ty(&self) -> Ty<'db> {
1227        self.expected_ty
1228    }
1229
1230    /// Returns the current "merged type", representing our best-guess
1231    /// at the LUB of the expressions we've seen so far (if any). This
1232    /// isn't *final* until you call `self.complete()`, which will return
1233    /// the merged type.
1234    pub(crate) fn merged_ty(&self) -> Ty<'db> {
1235        self.final_ty.unwrap_or(self.expected_ty)
1236    }
1237
1238    /// Indicates that the value generated by `expression`, which is
1239    /// of type `expression_ty`, is one of the possibilities that we
1240    /// could coerce from. This will record `expression`, and later
1241    /// calls to `coerce` may come back and add adjustments and things
1242    /// if necessary.
1243    pub(crate) fn coerce(
1244        &mut self,
1245        icx: &mut InferenceContext<'db>,
1246        cause: &ObligationCause,
1247        expression: ExprId,
1248        expression_ty: Ty<'db>,
1249        expr_is_read: ExprIsRead,
1250    ) {
1251        self.coerce_inner(icx, cause, expression, expression_ty, false, false, expr_is_read)
1252    }
1253
1254    /// Indicates that one of the inputs is a "forced unit". This
1255    /// occurs in a case like `if foo { ... };`, where the missing else
1256    /// generates a "forced unit". Another example is a `loop { break;
1257    /// }`, where the `break` has no argument expression. We treat
1258    /// these cases slightly differently for error-reporting
1259    /// purposes. Note that these tend to correspond to cases where
1260    /// the `()` expression is implicit in the source, and hence we do
1261    /// not take an expression argument.
1262    ///
1263    /// The `augment_error` gives you a chance to extend the error
1264    /// message, in case any results (e.g., we use this to suggest
1265    /// removing a `;`).
1266    pub(crate) fn coerce_forced_unit(
1267        &mut self,
1268        icx: &mut InferenceContext<'db>,
1269        expr: ExprId,
1270        cause: &ObligationCause,
1271        label_unit_as_expected: bool,
1272        expr_is_read: ExprIsRead,
1273    ) {
1274        self.coerce_inner(
1275            icx,
1276            cause,
1277            expr,
1278            icx.types.types.unit,
1279            true,
1280            label_unit_as_expected,
1281            expr_is_read,
1282        )
1283    }
1284
1285    /// The inner coercion "engine". If `expression` is `None`, this
1286    /// is a forced-unit case, and hence `expression_ty` must be
1287    /// `Nil`.
1288    pub(crate) fn coerce_inner(
1289        &mut self,
1290        icx: &mut InferenceContext<'db>,
1291        cause: &ObligationCause,
1292        expression: ExprId,
1293        mut expression_ty: Ty<'db>,
1294        force_unit: bool,
1295        label_expression_as_expected: bool,
1296        expr_is_read: ExprIsRead,
1297    ) {
1298        // Incorporate whatever type inference information we have
1299        // until now; in principle we might also want to process
1300        // pending obligations, but doing so should only improve
1301        // compatibility (hopefully that is true) by helping us
1302        // uncover never types better.
1303        if expression_ty.is_ty_var() {
1304            expression_ty = icx.shallow_resolve(expression_ty);
1305        }
1306
1307        let (expected, found) = if label_expression_as_expected {
1308            // In the case where this is a "forced unit", like
1309            // `break`, we want to call the `()` "expected"
1310            // since it is implied by the syntax.
1311            // (Note: not all force-units work this way.)"
1312            (expression_ty, self.merged_ty())
1313        } else {
1314            // Otherwise, the "expected" type for error
1315            // reporting is the current unification type,
1316            // which is basically the LUB of the expressions
1317            // we've seen so far (combined with the expected
1318            // type)
1319            (self.merged_ty(), expression_ty)
1320        };
1321
1322        // Handle the actual type unification etc.
1323        let result = if !force_unit {
1324            if self.pushed == 0 {
1325                // Special-case the first expression we are coercing.
1326                // To be honest, I'm not entirely sure why we do this.
1327                // We don't allow two-phase borrows, see comment in try_find_coercion_lub for why
1328                icx.coerce(
1329                    expression,
1330                    expression_ty,
1331                    self.expected_ty,
1332                    AllowTwoPhase::No,
1333                    expr_is_read,
1334                )
1335            } else {
1336                match self.expressions {
1337                    Expressions::Dynamic(ref exprs) => icx.try_find_coercion_lub(
1338                        exprs,
1339                        self.merged_ty(),
1340                        expression,
1341                        expression_ty,
1342                    ),
1343                    Expressions::UpFront(coercion_sites) => icx.try_find_coercion_lub(
1344                        &coercion_sites[0..self.pushed],
1345                        self.merged_ty(),
1346                        expression,
1347                        expression_ty,
1348                    ),
1349                }
1350            }
1351        } else {
1352            // this is a hack for cases where we default to `()` because
1353            // the expression etc has been omitted from the source. An
1354            // example is an `if let` without an else:
1355            //
1356            //     if let Some(x) = ... { }
1357            //
1358            // we wind up with a second match arm that is like `_ =>
1359            // ()`. That is the case we are considering here. We take
1360            // a different path to get the right "expected, found"
1361            // message and so forth (and because we know that
1362            // `expression_ty` will be unit).
1363            //
1364            // Another example is `break` with no argument expression.
1365            assert!(expression_ty.is_unit(), "if let hack without unit type");
1366            icx.table.infer_ctxt.at(cause, icx.table.param_env).eq(expected, found).map(
1367                |infer_ok| {
1368                    icx.table.register_infer_ok(infer_ok);
1369                    expression_ty
1370                },
1371            )
1372        };
1373
1374        debug!(?result);
1375        match result {
1376            Ok(v) => {
1377                self.final_ty = Some(v);
1378                match self.expressions {
1379                    Expressions::Dynamic(ref mut buffer) => buffer.push(expression),
1380                    Expressions::UpFront(coercion_sites) => {
1381                        // if the user gave us an array to validate, check that we got
1382                        // the next expression in the list, as expected
1383                        assert_eq!(coercion_sites[self.pushed], expression);
1384                    }
1385                }
1386            }
1387            Err(_coercion_error) => {
1388                // Mark that we've failed to coerce the types here to suppress
1389                // any superfluous errors we might encounter while trying to
1390                // emit or provide suggestions on how to fix the initial error.
1391                icx.set_tainted_by_errors();
1392
1393                self.final_ty = Some(icx.types.types.error);
1394
1395                if label_expression_as_expected {
1396                    icx.emit_type_mismatch(expression.into(), found, expected);
1397                } else {
1398                    icx.emit_type_mismatch(expression.into(), expected, found);
1399                }
1400            }
1401        }
1402
1403        self.pushed += 1;
1404    }
1405
1406    pub(crate) fn complete(self, icx: &mut InferenceContext<'db>) -> Ty<'db> {
1407        if let Some(final_ty) = self.final_ty {
1408            final_ty
1409        } else {
1410            // If we only had inputs that were of type `!` (or no
1411            // inputs at all), then the final type is `!`.
1412            assert_eq!(self.pushed, 0);
1413            icx.types.types.never
1414        }
1415    }
1416}
1417
1418pub fn could_coerce<'db>(
1419    db: &'db dyn HirDatabase,
1420    env: ParamEnvAndCrate<'db>,
1421    tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>,
1422) -> bool {
1423    coerce(db, env, tys).is_ok()
1424}
1425
1426struct HirCoercionDelegate<'a, 'db> {
1427    infcx: &'a InferCtxt<'db>,
1428    param_env: ParamEnv<'db>,
1429    target_features: &'a TargetFeatures<'db>,
1430}
1431
1432impl<'db> CoerceDelegate<'db> for HirCoercionDelegate<'_, 'db> {
1433    #[inline]
1434    fn infcx(&self) -> &InferCtxt<'db> {
1435        self.infcx
1436    }
1437    #[inline]
1438    fn param_env(&self) -> ParamEnv<'db> {
1439        self.param_env
1440    }
1441    fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget) {
1442        (self.target_features, TargetFeatureIsSafeInTarget::No)
1443    }
1444    fn set_diverging(&mut self, _diverging_ty: Ty<'db>) {}
1445    fn type_var_is_sized(&self, _var: TyVid) -> bool {
1446        false
1447    }
1448}
1449
1450fn coerce<'db>(
1451    db: &'db dyn HirDatabase,
1452    env: ParamEnvAndCrate<'db>,
1453    tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>,
1454) -> Result<(Vec<Adjustment>, Ty<'db>), TypeError<DbInterner<'db>>> {
1455    let interner = DbInterner::new_with(db, env.krate);
1456    let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
1457    let ((ty1_with_vars, ty2_with_vars), vars) = infcx.instantiate_canonical(Span::Dummy, tys);
1458
1459    let cause = ObligationCause::dummy();
1460    // FIXME: Target features.
1461    let target_features = TargetFeatures::default();
1462    let mut coerce = Coerce {
1463        delegate: HirCoercionDelegate {
1464            infcx: &infcx,
1465            param_env: env.param_env,
1466            target_features: &target_features,
1467        },
1468        cause,
1469        allow_two_phase: AllowTwoPhase::No,
1470        coerce_never: true,
1471        use_lub: false,
1472    };
1473    let infer_ok = coerce.coerce(ty1_with_vars, ty2_with_vars)?;
1474    let mut ocx = ObligationCtxt::new(&infcx);
1475    let (adjustments, ty) = ocx.register_infer_ok_obligations(infer_ok);
1476    _ = ocx.try_evaluate_obligations();
1477
1478    // default any type vars that weren't unified back to their original bound vars
1479    // (kind of hacky)
1480
1481    struct Resolver<'db> {
1482        interner: DbInterner<'db>,
1483        debruijn: DebruijnIndex,
1484        var_values: GenericArgs<'db>,
1485    }
1486
1487    impl<'db> TypeFolder<DbInterner<'db>> for Resolver<'db> {
1488        fn cx(&self) -> DbInterner<'db> {
1489            self.interner
1490        }
1491
1492        fn fold_binder<T>(&mut self, t: Binder<'db, T>) -> Binder<'db, T>
1493        where
1494            T: TypeFoldable<DbInterner<'db>>,
1495        {
1496            self.debruijn.shift_in(1);
1497            let result = t.super_fold_with(self);
1498            self.debruijn.shift_out(1);
1499            result
1500        }
1501
1502        fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> {
1503            if !t.has_infer() {
1504                return t;
1505            }
1506
1507            if let TyKind::Infer(infer) = t.kind() {
1508                let var = self.var_values.iter().position(|arg| {
1509                    arg.as_type().is_some_and(|ty| match ty.kind() {
1510                        TyKind::Infer(it) => infer == it,
1511                        _ => false,
1512                    })
1513                });
1514                var.map_or_else(
1515                    || Ty::new_error(self.interner, ErrorGuaranteed),
1516                    |i| {
1517                        Ty::new_bound(
1518                            self.interner,
1519                            self.debruijn,
1520                            BoundTy { kind: BoundTyKind::Anon, var: BoundVar::from_usize(i) },
1521                        )
1522                    },
1523                )
1524            } else {
1525                t.super_fold_with(self)
1526            }
1527        }
1528
1529        fn fold_const(&mut self, c: Const<'db>) -> Const<'db> {
1530            if !c.has_infer() {
1531                return c;
1532            }
1533
1534            if let ConstKind::Infer(infer) = c.kind() {
1535                let var = self.var_values.iter().position(|arg| {
1536                    arg.as_const().is_some_and(|ty| match ty.kind() {
1537                        ConstKind::Infer(it) => infer == it,
1538                        _ => false,
1539                    })
1540                });
1541                var.map_or_else(
1542                    || Const::new_error(self.interner, ErrorGuaranteed),
1543                    |i| {
1544                        Const::new_bound(
1545                            self.interner,
1546                            self.debruijn,
1547                            BoundConst::new(BoundVar::from_usize(i)),
1548                        )
1549                    },
1550                )
1551            } else {
1552                c.super_fold_with(self)
1553            }
1554        }
1555
1556        fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
1557            if let RegionKind::ReVar(infer) = r.kind() {
1558                let var = self.var_values.iter().position(|arg| {
1559                    arg.as_region().is_some_and(|ty| match ty.kind() {
1560                        RegionKind::ReVar(it) => infer == it,
1561                        _ => false,
1562                    })
1563                });
1564                var.map_or_else(
1565                    || Region::error(self.interner),
1566                    |i| {
1567                        Region::new_bound(
1568                            self.interner,
1569                            self.debruijn,
1570                            BoundRegion {
1571                                kind: BoundRegionKind::Anon,
1572                                var: BoundVar::from_usize(i),
1573                            },
1574                        )
1575                    },
1576                )
1577            } else {
1578                r
1579            }
1580        }
1581    }
1582
1583    // FIXME: We don't fallback correctly since this is done on `InferenceContext` and we only have `InferCtxt`.
1584    let mut resolver =
1585        Resolver { interner, debruijn: DebruijnIndex::ZERO, var_values: vars.var_values };
1586    let ty = infcx.resolve_vars_if_possible(ty).fold_with(&mut resolver);
1587    let adjustments = adjustments
1588        .into_iter()
1589        .map(|adjustment| Adjustment {
1590            kind: adjustment.kind,
1591            target: infcx
1592                .resolve_vars_if_possible(adjustment.target.as_ref())
1593                .fold_with(&mut resolver)
1594                .store(),
1595        })
1596        .collect();
1597    Ok((adjustments, ty))
1598}
1599
1600fn is_capturing_closure(db: &dyn HirDatabase, closure: InternedClosureId<'_>) -> bool {
1601    let InternedClosure { owner, expr, .. } = closure.loc(db);
1602    upvars_mentioned(db, owner.expression_store_owner(db))
1603        .is_some_and(|upvars| upvars.get(&expr).is_some_and(|upvars| !upvars.is_empty()))
1604}
1605
1606/// Recursively visit goals to decide whether an unsizing is possible.
1607/// `Break`s when it isn't, and an error should be raised.
1608/// `Continue`s when an unsizing ok based on an implementation of the `Unsize` trait / lang item.
1609struct CoerceVisitor<'a, D> {
1610    delegate: &'a D,
1611    /// Whether the coercion is impossible. If so we sometimes still try to
1612    /// coerce in these cases to emit better errors. This changes the behavior
1613    /// when hitting the recursion limit.
1614    errored: bool,
1615    unsize_did: TraitId,
1616    coerce_unsized_did: TraitId,
1617    span: Span,
1618}
1619
1620impl<'a, 'db, D: CoerceDelegate<'db>> ProofTreeVisitor<'db> for CoerceVisitor<'a, D> {
1621    type Result = ControlFlow<()>;
1622
1623    fn span(&self) -> Span {
1624        self.span
1625    }
1626
1627    fn visit_goal(&mut self, goal: &InspectGoal<'_, 'db>) -> Self::Result {
1628        let Some(pred) = goal.goal().predicate.as_trait_clause() else {
1629            return ControlFlow::Continue(());
1630        };
1631
1632        // Make sure this predicate is referring to either an `Unsize` or `CoerceUnsized` trait,
1633        // Otherwise there's nothing to do.
1634        let def_id = pred.def_id().0;
1635        if def_id != self.unsize_did && def_id != self.coerce_unsized_did {
1636            return ControlFlow::Continue(());
1637        }
1638
1639        match goal.result() {
1640            // If we prove the `Unsize` or `CoerceUnsized` goal, continue recursing.
1641            Ok(Certainty::Yes) => ControlFlow::Continue(()),
1642            Err(NoSolution) => {
1643                self.errored = true;
1644                // Even if we find no solution, continue recursing if we find a single candidate
1645                // for which we're shallowly certain it holds to get the right error source.
1646                if let [only_candidate] = &goal.candidates()[..]
1647                    && only_candidate.shallow_certainty() == Certainty::Yes
1648                {
1649                    only_candidate.visit_nested_no_probe(self)
1650                } else {
1651                    ControlFlow::Break(())
1652                }
1653            }
1654            Ok(Certainty::Maybe { .. }) => {
1655                // FIXME: structurally normalize?
1656                if def_id == self.unsize_did
1657                    && let TyKind::Dynamic(..) = pred.skip_binder().trait_ref.args.type_at(1).kind()
1658                    && let TyKind::Infer(InferTy::TyVar(vid)) = pred.self_ty().skip_binder().kind()
1659                    && self.delegate.type_var_is_sized(vid)
1660                {
1661                    // We get here when trying to unsize a type variable to a `dyn Trait`,
1662                    // knowing that that variable is sized. Unsizing definitely has to happen in that case.
1663                    // If the variable weren't sized, we may not need an unsizing coercion.
1664                    // In general, we don't want to add coercions too eagerly since it makes error messages much worse.
1665                    ControlFlow::Continue(())
1666                } else if let Some(cand) = goal.unique_applicable_candidate()
1667                    && cand.shallow_certainty() == Certainty::Yes
1668                {
1669                    cand.visit_nested_no_probe(self)
1670                } else {
1671                    ControlFlow::Break(())
1672                }
1673            }
1674        }
1675    }
1676
1677    fn on_recursion_limit(&mut self) -> Self::Result {
1678        if self.errored {
1679            // This prevents accidentally committing unfulfilled unsized coercions while trying to
1680            // find the error source for diagnostics.
1681            // See https://github.com/rust-lang/trait-system-refactor-initiative/issues/266.
1682            ControlFlow::Break(())
1683        } else {
1684            ControlFlow::Continue(())
1685        }
1686    }
1687}