@@ -59,7 +59,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5959 || self . suggest_copied_or_cloned ( err, expr, expr_ty, expected)
6060 || self . suggest_clone_for_ref ( err, expr, expr_ty, expected)
6161 || self . suggest_into ( err, expr, expr_ty, expected)
62- || self . suggest_floating_point_literal ( err, expr, expected) ;
62+ || self . suggest_floating_point_literal ( err, expr, expected)
63+ || self . note_result_coercion ( err, expr, expected, expr_ty) ;
6364 if !suggested {
6465 self . point_at_expr_source_of_inferred_type ( err, expr, expr_ty, expected) ;
6566 }
@@ -81,7 +82,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8182 self . annotate_expected_due_to_let_ty ( err, expr, error) ;
8283 self . emit_type_mismatch_suggestions ( err, expr, expr_ty, expected, expected_ty_expr, error) ;
8384 self . note_type_is_not_clone ( err, expected, expr_ty, expr) ;
84- self . note_need_for_fn_pointer ( err, expected, expr_ty) ;
8585 self . note_internal_mutation_in_method ( err, expr, expected, expr_ty) ;
8686 self . check_for_range_as_method_call ( err, expr, expr_ty, expected) ;
8787 self . check_for_binding_assigned_block_without_tail_expression ( err, expr, expr_ty, expected) ;
@@ -697,6 +697,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
697697 ) ;
698698 }
699699
700+ pub ( crate ) fn note_result_coercion (
701+ & self ,
702+ err : & mut Diagnostic ,
703+ expr : & hir:: Expr < ' tcx > ,
704+ expected : Ty < ' tcx > ,
705+ found : Ty < ' tcx > ,
706+ ) -> bool {
707+ let ty:: Adt ( e, substs_e) = expected. kind ( ) else { return false ; } ;
708+ let ty:: Adt ( f, substs_f) = found. kind ( ) else { return false ; } ;
709+ if e. did ( ) != f. did ( ) {
710+ return false ;
711+ }
712+ if Some ( e. did ( ) ) != self . tcx . get_diagnostic_item ( sym:: Result ) {
713+ return false ;
714+ }
715+ let map = self . tcx . hir ( ) ;
716+ if let Some ( hir:: Node :: Expr ( expr) ) = map. find_parent ( expr. hir_id )
717+ && let hir:: ExprKind :: Ret ( _) = expr. kind
718+ {
719+ // `return foo;`
720+ } else if map. get_return_block ( expr. hir_id ) . is_some ( ) {
721+ // Function's tail expression.
722+ } else {
723+ return false ;
724+ }
725+ let e = substs_e. type_at ( 1 ) ;
726+ let f = substs_f. type_at ( 1 ) ;
727+ if self
728+ . infcx
729+ . type_implements_trait (
730+ self . tcx . get_diagnostic_item ( sym:: Into ) . unwrap ( ) ,
731+ [ f, e] ,
732+ self . param_env ,
733+ )
734+ . must_apply_modulo_regions ( )
735+ {
736+ err. multipart_suggestion (
737+ "use `?` to coerce and return an appropriate `Err`, and wrap the resulting value \
738+ in `Ok` so the expression remains of type `Result`",
739+ vec ! [
740+ ( expr. span. shrink_to_lo( ) , "Ok(" . to_string( ) ) ,
741+ ( expr. span. shrink_to_hi( ) , "?)" . to_string( ) ) ,
742+ ] ,
743+ Applicability :: MaybeIncorrect ,
744+ ) ;
745+ return true ;
746+ }
747+ false
748+ }
749+
700750 /// If the expected type is an enum (Issue #55250) with any variants whose
701751 /// sole field is of the found type, suggest such variants. (Issue #42764)
702752 fn suggest_compatible_variants (
0 commit comments