Repository: rust-lang/rust
File: compiler/rustc_hir_typeck/src/coercion.rs (Rust)

Code before:
                ),
            ))
        } else {
            false
        }
    }

    pub(crate) fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
        if let Some(final_ty) = self.final_ty {
            final_ty
        } else {
            // If we only had inputs that were of type `!` (or no
            // inputs at all), then the final type is `!`.
            assert!(self.expressions.is_empty());
            fcx.tcx.types.never
        }
    }
}

/// Recursively visit goals to decide whether an unsizing is possible.
/// `Break`s when it isn't, and an error should be raised.
/// `Continue`s when an unsizing ok based on an implementation of the `Unsize` trait / lang item.
struct CoerceVisitor<'a, 'tcx> {
    fcx: &'a FnCtxt<'a, 'tcx>,
    span: Span,
    // Whether the coercion is impossible and just continuing to visit to locate the error source.
    errored: bool,
}

impl<'tcx> ProofTreeVisitor<'tcx> for CoerceVisitor<'_, 'tcx> {
    type Result = ControlFlow<()>;

    fn span(&self) -> Span {
        self.span
    }

    fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
        let Some(pred) = goal.goal().predicate.as_trait_clause() else {
            return ControlFlow::Continue(());
        };

        // Make sure this predicate is referring to either an `Unsize` or `CoerceUnsized` trait,
        // Otherwise there's nothing to do.
        if !self.fcx.tcx.is_lang_item(pred.def_id(), LangItem::Unsize)
            && !self.fcx.tcx.is_lang_item(pred.def_id(), LangItem::CoerceUnsized)
        {
            return ControlFlow::Continue(());
        }

        match goal.result() {
            // If we prove the `Unsize` or `CoerceUnsized` goal, continue recursing.

Review comment (suggestion):
```suggestion
    /// Whether the coercion is impossible. If so we someties still try to
    /// coerce in these cases to emit better errors. This impacts changes the
    /// behavior when hitting the recursion limit.
```

Code after:
                ),
            ))
        } else {
            false
        }
    }

    pub(crate) fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
        if let Some(final_ty) = self.final_ty {
            final_ty
        } else {
            // If we only had inputs that were of type `!` (or no
            // inputs at all), then the final type is `!`.
            assert!(self.expressions.is_empty());
            fcx.tcx.types.never
        }
    }
}

/// Recursively visit goals to decide whether an unsizing is possible.
/// `Break`s when it isn't, and an error should be raised.
/// `Continue`s when an unsizing ok based on an implementation of the `Unsize` trait / lang item.
struct CoerceVisitor<'a, 'tcx> {
    fcx: &'a FnCtxt<'a, 'tcx>,
    span: Span,
    /// Whether the coercion is impossible. If so we sometimes still try to
    /// coerce in these cases to emit better errors. This changes the behavior
    /// when hitting the recursion limit.
    errored: bool,
}

impl<'tcx> ProofTreeVisitor<'tcx> for CoerceVisitor<'_, 'tcx> {
    type Result = ControlFlow<()>;

    fn span(&self) -> Span {
        self.span
    }

    fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
        let Some(pred) = goal.goal().predicate.as_trait_clause() else {
            return ControlFlow::Continue(());
        };

        // Make sure this predicate is referring to either an `Unsize` or `CoerceUnsized` trait,
        // Otherwise there's nothing to do.
        if !self.fcx.tcx.is_lang_item(pred.def_id(), LangItem::Unsize)
            && !self.fcx.tcx.is_lang_item(pred.def_id(), LangItem::CoerceUnsized)
        {
            return ControlFlow::Continue(());
        }