@@ -7,6 +7,7 @@ use rustc_ast::util::parser::ExprPrecedence;
77use rustc_data_structures:: packed:: Pu128 ;
88use rustc_errors:: { Applicability , Diag , MultiSpan , listify, msg} ;
99use rustc_hir:: def:: { CtorKind , CtorOf , DefKind , Res } ;
10+ use rustc_hir:: intravisit:: Visitor ;
1011use rustc_hir:: lang_items:: LangItem ;
1112use rustc_hir:: {
1213 self as hir, Arm , CoroutineDesugaring , CoroutineKind , CoroutineSource , Expr , ExprKind ,
@@ -26,13 +27,14 @@ use rustc_session::errors::ExprParenthesesNeeded;
2627use rustc_span:: { ExpnKind , Ident , MacroKind , Span , Spanned , Symbol , sym} ;
2728use rustc_trait_selection:: error_reporting:: InferCtxtErrorExt ;
2829use rustc_trait_selection:: error_reporting:: traits:: DefIdOrName ;
30+ use rustc_trait_selection:: error_reporting:: traits:: suggestions:: ReturnsVisitor ;
2931use rustc_trait_selection:: infer:: InferCtxtExt ;
3032use rustc_trait_selection:: traits;
3133use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
3234use tracing:: { debug, instrument} ;
3335
3436use super :: FnCtxt ;
35- use crate :: errors;
37+ use crate :: errors:: { self , SuggestBoxingForReturnImplTrait } ;
3638use crate :: fn_ctxt:: rustc_span:: BytePos ;
3739use crate :: method:: probe;
3840use crate :: method:: probe:: { IsSuggestion , Mode , ProbeScope } ;
@@ -963,6 +965,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
963965 ) ;
964966 }
965967
968+ let trait_def_id = trait_ref. trait_ref . path . res . def_id ( ) ;
969+ if self . tcx . is_dyn_compatible ( trait_def_id) {
970+ err. subdiagnostic ( SuggestBoxingForReturnImplTrait :: ChangeReturnType {
971+ start_sp : hir_ty. span . with_hi ( hir_ty. span . lo ( ) + BytePos ( 4 ) ) ,
972+ end_sp : hir_ty. span . shrink_to_hi ( ) ,
973+ } ) ;
974+
975+ let body = self . tcx . hir_body_owned_by ( fn_id) ;
976+ let mut visitor = ReturnsVisitor :: default ( ) ;
977+ visitor. visit_body ( & body) ;
978+
979+ if !visitor. returns . is_empty ( ) {
980+ let starts: Vec < Span > = visitor
981+ . returns
982+ . iter ( )
983+ . filter ( |expr| expr. span . can_be_used_for_suggestions ( ) )
984+ . map ( |expr| expr. span . shrink_to_lo ( ) )
985+ . collect ( ) ;
986+ let ends: Vec < Span > = visitor
987+ . returns
988+ . iter ( )
989+ . filter ( |expr| expr. span . can_be_used_for_suggestions ( ) )
990+ . map ( |expr| expr. span . shrink_to_hi ( ) )
991+ . collect ( ) ;
992+
993+ if !starts. is_empty ( ) {
994+ err. subdiagnostic ( SuggestBoxingForReturnImplTrait :: BoxReturnExpr {
995+ starts,
996+ ends,
997+ } ) ;
998+ }
999+ }
1000+ }
1001+
9661002 self . try_suggest_return_impl_trait ( err, expected, found, fn_id) ;
9671003 self . try_note_caller_chooses_ty_for_ty_param ( err, expected, found) ;
9681004 return true ;
0 commit comments