@@ -5,6 +5,7 @@ use crate::session_diagnostics::{
5
5
CaptureVarKind , CaptureVarPathUseCause , OnClosureNote ,
6
6
} ;
7
7
use rustc_errors:: { Applicability , Diag } ;
8
+ use rustc_errors:: { DiagCtxt , MultiSpan } ;
8
9
use rustc_hir as hir;
9
10
use rustc_hir:: def:: { CtorKind , Namespace } ;
10
11
use rustc_hir:: CoroutineKind ;
@@ -29,6 +30,8 @@ use rustc_trait_selection::infer::InferCtxtExt;
29
30
use rustc_trait_selection:: traits:: error_reporting:: suggestions:: TypeErrCtxtExt as _;
30
31
use rustc_trait_selection:: traits:: type_known_to_meet_bound_modulo_regions;
31
32
33
+ use crate :: fluent_generated as fluent;
34
+
32
35
use super :: borrow_set:: BorrowData ;
33
36
use super :: MirBorrowckCtxt ;
34
37
@@ -587,7 +590,7 @@ impl UseSpans<'_> {
587
590
#[ allow( rustc:: diagnostic_outside_of_impl) ]
588
591
pub ( super ) fn args_subdiag (
589
592
self ,
590
- dcx : & rustc_errors :: DiagCtxt ,
593
+ dcx : & DiagCtxt ,
591
594
err : & mut Diag < ' _ > ,
592
595
f : impl FnOnce ( Span ) -> CaptureArgLabel ,
593
596
) {
@@ -601,7 +604,7 @@ impl UseSpans<'_> {
601
604
#[ allow( rustc:: diagnostic_outside_of_impl) ]
602
605
pub ( super ) fn var_path_only_subdiag (
603
606
self ,
604
- dcx : & rustc_errors :: DiagCtxt ,
607
+ dcx : & DiagCtxt ,
605
608
err : & mut Diag < ' _ > ,
606
609
action : crate :: InitializationRequiringAction ,
607
610
) {
@@ -639,7 +642,7 @@ impl UseSpans<'_> {
639
642
#[ allow( rustc:: diagnostic_outside_of_impl) ]
640
643
pub ( super ) fn var_subdiag (
641
644
self ,
642
- dcx : & rustc_errors :: DiagCtxt ,
645
+ dcx : & DiagCtxt ,
643
646
err : & mut Diag < ' _ > ,
644
647
kind : Option < rustc_middle:: mir:: BorrowKind > ,
645
648
f : impl FnOnce ( hir:: ClosureKind , Span ) -> CaptureVarCause ,
@@ -1034,7 +1037,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1034
1037
. map ( |n| format ! ( "`{n}`" ) )
1035
1038
. unwrap_or_else ( || "value" . to_owned ( ) ) ;
1036
1039
match kind {
1037
- CallKind :: FnCall { fn_trait_id, .. }
1040
+ CallKind :: FnCall { fn_trait_id, self_ty }
1038
1041
if Some ( fn_trait_id) == self . infcx . tcx . lang_items ( ) . fn_once_trait ( ) =>
1039
1042
{
1040
1043
err. subdiagnostic (
@@ -1046,7 +1049,58 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1046
1049
is_loop_message,
1047
1050
} ,
1048
1051
) ;
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
+ }
1050
1104
}
1051
1105
CallKind :: Operator { self_arg, trait_id, .. } => {
1052
1106
let self_arg = self_arg. unwrap ( ) ;
0 commit comments