@@ -5,6 +5,7 @@ use crate::session_diagnostics::{
55 CaptureVarKind , CaptureVarPathUseCause , OnClosureNote ,
66} ;
77use rustc_errors:: { Applicability , Diag } ;
8+ use rustc_errors:: { DiagCtxt , MultiSpan } ;
89use rustc_hir as hir;
910use rustc_hir:: def:: { CtorKind , Namespace } ;
1011use rustc_hir:: CoroutineKind ;
@@ -29,6 +30,8 @@ use rustc_trait_selection::infer::InferCtxtExt;
2930use rustc_trait_selection:: traits:: error_reporting:: suggestions:: TypeErrCtxtExt as _;
3031use rustc_trait_selection:: traits:: type_known_to_meet_bound_modulo_regions;
3132
33+ use crate :: fluent_generated as fluent;
34+
3235use super :: borrow_set:: BorrowData ;
3336use super :: MirBorrowckCtxt ;
3437
@@ -587,7 +590,7 @@ impl UseSpans<'_> {
587590 #[ allow( rustc:: diagnostic_outside_of_impl) ]
588591 pub ( super ) fn args_subdiag (
589592 self ,
590- dcx : & rustc_errors :: DiagCtxt ,
593+ dcx : & DiagCtxt ,
591594 err : & mut Diag < ' _ > ,
592595 f : impl FnOnce ( Span ) -> CaptureArgLabel ,
593596 ) {
@@ -601,7 +604,7 @@ impl UseSpans<'_> {
601604 #[ allow( rustc:: diagnostic_outside_of_impl) ]
602605 pub ( super ) fn var_path_only_subdiag (
603606 self ,
604- dcx : & rustc_errors :: DiagCtxt ,
607+ dcx : & DiagCtxt ,
605608 err : & mut Diag < ' _ > ,
606609 action : crate :: InitializationRequiringAction ,
607610 ) {
@@ -639,7 +642,7 @@ impl UseSpans<'_> {
639642 #[ allow( rustc:: diagnostic_outside_of_impl) ]
640643 pub ( super ) fn var_subdiag (
641644 self ,
642- dcx : & rustc_errors :: DiagCtxt ,
645+ dcx : & DiagCtxt ,
643646 err : & mut Diag < ' _ > ,
644647 kind : Option < rustc_middle:: mir:: BorrowKind > ,
645648 f : impl FnOnce ( hir:: ClosureKind , Span ) -> CaptureVarCause ,
@@ -1034,7 +1037,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
10341037 . map ( |n| format ! ( "`{n}`" ) )
10351038 . unwrap_or_else ( || "value" . to_owned ( ) ) ;
10361039 match kind {
1037- CallKind :: FnCall { fn_trait_id, .. }
1040+ CallKind :: FnCall { fn_trait_id, self_ty }
10381041 if Some ( fn_trait_id) == self . infcx . tcx . lang_items ( ) . fn_once_trait ( ) =>
10391042 {
10401043 err. subdiagnostic (
@@ -1046,7 +1049,58 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
10461049 is_loop_message,
10471050 } ,
10481051 ) ;
1049- err. subdiagnostic ( self . dcx ( ) , CaptureReasonNote :: FnOnceMoveInCall { var_span } ) ;
1052+ if let ty:: Param ( param_ty) = self_ty. kind ( )
1053+ && let generics = self . infcx . tcx . generics_of ( self . mir_def_id ( ) )
1054+ && let param = generics. type_param ( param_ty, self . infcx . tcx )
1055+ && let Some ( hir_generics) = self
1056+ . infcx
1057+ . tcx
1058+ . typeck_root_def_id ( self . mir_def_id ( ) . to_def_id ( ) )
1059+ . as_local ( )
1060+ . and_then ( |def_id| self . infcx . tcx . hir ( ) . get_generics ( def_id) )
1061+ && let spans = hir_generics
1062+ . predicates
1063+ . iter ( )
1064+ . filter_map ( |pred| match pred {
1065+ hir:: WherePredicate :: BoundPredicate ( pred) => Some ( pred) ,
1066+ _ => None ,
1067+ } )
1068+ . filter ( |pred| {
1069+ if let Some ( ( id, _) ) = pred. bounded_ty . as_generic_param ( ) {
1070+ id == param. def_id
1071+ } else {
1072+ false
1073+ }
1074+ } )
1075+ . flat_map ( |pred| pred. bounds )
1076+ . filter_map ( |bound| {
1077+ if let Some ( trait_ref) = bound. trait_ref ( )
1078+ && let Some ( trait_def_id) = trait_ref. trait_def_id ( )
1079+ && trait_def_id == fn_trait_id
1080+ {
1081+ Some ( bound. span ( ) )
1082+ } else {
1083+ None
1084+ }
1085+ } )
1086+ . collect :: < Vec < Span > > ( )
1087+ && !spans. is_empty ( )
1088+ {
1089+ let mut span: MultiSpan = spans. clone ( ) . into ( ) ;
1090+ for sp in spans {
1091+ span. push_span_label ( sp, fluent:: borrowck_moved_a_fn_once_in_call_def) ;
1092+ }
1093+ span. push_span_label (
1094+ fn_call_span,
1095+ fluent:: borrowck_moved_a_fn_once_in_call,
1096+ ) ;
1097+ err. span_note ( span, fluent:: borrowck_moved_a_fn_once_in_call_call) ;
1098+ } else {
1099+ err. subdiagnostic (
1100+ self . dcx ( ) ,
1101+ CaptureReasonNote :: FnOnceMoveInCall { var_span } ,
1102+ ) ;
1103+ }
10501104 }
10511105 CallKind :: Operator { self_arg, trait_id, .. } => {
10521106 let self_arg = self_arg. unwrap ( ) ;
0 commit comments