diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 893d1e88bf8a..d5f37abb8b45 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -45,7 +45,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Expr; use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{Coercion, InferOk, InferResult, TyCtxtInferExt}; +use rustc_infer::infer::{Coercion, InferOk, InferResult}; use rustc_infer::traits::Obligation; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::{ @@ -1565,9 +1565,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { && let hir::ExprKind::Loop(loop_blk, ..) = expression.kind { intravisit::walk_block(& mut visitor, loop_blk); } - if let Some(expr) = expression { - self.note_result_coercion(fcx, &mut err, expr, expected, found); - } } ObligationCauseCode::ReturnValue(id) => { err = self.report_return_mismatched_types( @@ -1584,9 +1581,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { let id = fcx.tcx.hir().parent_id(id); unsized_return = self.is_return_ty_unsized(fcx, id); } - if let Some(expr) = expression { - self.note_result_coercion(fcx, &mut err, expr, expected, found); - } } _ => { err = fcx.err_ctxt().report_mismatched_types( @@ -1626,44 +1620,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } } - fn note_result_coercion( - &self, - fcx: &FnCtxt<'_, 'tcx>, - err: &mut Diagnostic, - expr: &hir::Expr<'tcx>, - expected: Ty<'tcx>, - found: Ty<'tcx>, - ) { - let ty::Adt(e, substs_e) = expected.kind() else { return; }; - let ty::Adt(f, substs_f) = found.kind() else { return; }; - if e.did() != f.did() { - return; - } - if Some(e.did()) != fcx.tcx.get_diagnostic_item(sym::Result) { - return; - } - let e = substs_e.type_at(1); - let f = substs_f.type_at(1); - if fcx - .infcx - .type_implements_trait( - fcx.tcx.get_diagnostic_item(sym::Into).unwrap(), - [fcx.tcx.erase_regions(f), fcx.tcx.erase_regions(e)], - fcx.param_env, - ) - .must_apply_modulo_regions() - { - err.multipart_suggestion( - "you can rely on the implicit conversion that `?` does to transform the error type", - vec![ - (expr.span.shrink_to_lo(), "Ok(".to_string()), - (expr.span.shrink_to_hi(), "?)".to_string()), - ], - Applicability::MaybeIncorrect, - ); - } - } - fn note_unreachable_loop_return( &self, err: &mut Diagnostic, diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 665dc8b6a2f2..b10bb593ead4 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -59,7 +59,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_copied_or_cloned(err, expr, expr_ty, expected) || self.suggest_clone_for_ref(err, expr, expr_ty, expected) || self.suggest_into(err, expr, expr_ty, expected) - || self.suggest_floating_point_literal(err, expr, expected); + || self.suggest_floating_point_literal(err, expr, expected) + || self.note_result_coercion(err, expr, expected, expr_ty); if !suggested { self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected); } @@ -697,6 +698,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } + pub(crate) fn note_result_coercion( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'tcx>, + expected: Ty<'tcx>, + found: Ty<'tcx>, + ) -> bool { + let ty::Adt(e, substs_e) = expected.kind() else { return false; }; + let ty::Adt(f, substs_f) = found.kind() else { return false; }; + if e.did() != f.did() { + return false; + } + if Some(e.did()) != self.tcx.get_diagnostic_item(sym::Result) { + return false; + } + let e = substs_e.type_at(1); + let f = substs_f.type_at(1); + if self + .infcx + .type_implements_trait( + self.tcx.get_diagnostic_item(sym::Into).unwrap(), + [self.tcx.erase_regions(f), self.tcx.erase_regions(e)], + self.param_env, + ) + .must_apply_modulo_regions() + { + err.multipart_suggestion( + "you can rely on the implicit conversion that `?` does to transform the error type", + vec![ + (expr.span.shrink_to_lo(), "Ok(".to_string()), + (expr.span.shrink_to_hi(), "?)".to_string()), + ], + Applicability::MaybeIncorrect, + ); + return true; + } + false + } + /// If the expected type is an enum (Issue #55250) with any variants whose /// sole field is of the found type, suggest such variants. (Issue #42764) fn suggest_compatible_variants(