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