@@ -6,6 +6,7 @@ use crate::session_diagnostics::{
6
6
} ;
7
7
use itertools:: Itertools ;
8
8
use rustc_errors:: { Applicability , Diag } ;
9
+ use rustc_errors:: { DiagCtxt , MultiSpan } ;
9
10
use rustc_hir as hir;
10
11
use rustc_hir:: def:: { CtorKind , Namespace } ;
11
12
use rustc_hir:: CoroutineKind ;
@@ -30,6 +31,8 @@ use rustc_trait_selection::infer::InferCtxtExt;
30
31
use rustc_trait_selection:: traits:: error_reporting:: suggestions:: TypeErrCtxtExt as _;
31
32
use rustc_trait_selection:: traits:: type_known_to_meet_bound_modulo_regions;
32
33
34
+ use crate :: fluent_generated as fluent;
35
+
33
36
use super :: borrow_set:: BorrowData ;
34
37
use super :: MirBorrowckCtxt ;
35
38
@@ -589,7 +592,7 @@ impl UseSpans<'_> {
589
592
#[ allow( rustc:: diagnostic_outside_of_impl) ]
590
593
pub ( super ) fn args_subdiag (
591
594
self ,
592
- dcx : & rustc_errors :: DiagCtxt ,
595
+ dcx : & DiagCtxt ,
593
596
err : & mut Diag < ' _ > ,
594
597
f : impl FnOnce ( Span ) -> CaptureArgLabel ,
595
598
) {
@@ -603,7 +606,7 @@ impl UseSpans<'_> {
603
606
#[ allow( rustc:: diagnostic_outside_of_impl) ]
604
607
pub ( super ) fn var_path_only_subdiag (
605
608
self ,
606
- dcx : & rustc_errors :: DiagCtxt ,
609
+ dcx : & DiagCtxt ,
607
610
err : & mut Diag < ' _ > ,
608
611
action : crate :: InitializationRequiringAction ,
609
612
) {
@@ -641,7 +644,7 @@ impl UseSpans<'_> {
641
644
#[ allow( rustc:: diagnostic_outside_of_impl) ]
642
645
pub ( super ) fn var_subdiag (
643
646
self ,
644
- dcx : & rustc_errors :: DiagCtxt ,
647
+ dcx : & DiagCtxt ,
645
648
err : & mut Diag < ' _ > ,
646
649
kind : Option < rustc_middle:: mir:: BorrowKind > ,
647
650
f : impl FnOnce ( hir:: ClosureKind , Span ) -> CaptureVarCause ,
@@ -1036,7 +1039,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1036
1039
. map ( |n| format ! ( "`{n}`" ) )
1037
1040
. unwrap_or_else ( || "value" . to_owned ( ) ) ;
1038
1041
match kind {
1039
- CallKind :: FnCall { fn_trait_id, .. }
1042
+ CallKind :: FnCall { fn_trait_id, self_ty }
1040
1043
if Some ( fn_trait_id) == self . infcx . tcx . lang_items ( ) . fn_once_trait ( ) =>
1041
1044
{
1042
1045
err. subdiagnostic (
@@ -1048,7 +1051,58 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1048
1051
is_loop_message,
1049
1052
} ,
1050
1053
) ;
1051
- err. subdiagnostic ( self . dcx ( ) , CaptureReasonNote :: FnOnceMoveInCall { var_span } ) ;
1054
+ if let ty:: Param ( param_ty) = self_ty. kind ( )
1055
+ && let generics = self . infcx . tcx . generics_of ( self . mir_def_id ( ) )
1056
+ && let param = generics. type_param ( param_ty, self . infcx . tcx )
1057
+ && let Some ( hir_generics) = self
1058
+ . infcx
1059
+ . tcx
1060
+ . typeck_root_def_id ( self . mir_def_id ( ) . to_def_id ( ) )
1061
+ . as_local ( )
1062
+ . and_then ( |def_id| self . infcx . tcx . hir ( ) . get_generics ( def_id) )
1063
+ && let spans = hir_generics
1064
+ . predicates
1065
+ . iter ( )
1066
+ . filter_map ( |pred| match pred {
1067
+ hir:: WherePredicate :: BoundPredicate ( pred) => Some ( pred) ,
1068
+ _ => None ,
1069
+ } )
1070
+ . filter ( |pred| {
1071
+ if let Some ( ( id, _) ) = pred. bounded_ty . as_generic_param ( ) {
1072
+ id == param. def_id
1073
+ } else {
1074
+ false
1075
+ }
1076
+ } )
1077
+ . flat_map ( |pred| pred. bounds )
1078
+ . filter_map ( |bound| {
1079
+ if let Some ( trait_ref) = bound. trait_ref ( )
1080
+ && let Some ( trait_def_id) = trait_ref. trait_def_id ( )
1081
+ && trait_def_id == fn_trait_id
1082
+ {
1083
+ Some ( bound. span ( ) )
1084
+ } else {
1085
+ None
1086
+ }
1087
+ } )
1088
+ . collect :: < Vec < Span > > ( )
1089
+ && !spans. is_empty ( )
1090
+ {
1091
+ let mut span: MultiSpan = spans. clone ( ) . into ( ) ;
1092
+ for sp in spans {
1093
+ span. push_span_label ( sp, fluent:: borrowck_moved_a_fn_once_in_call_def) ;
1094
+ }
1095
+ span. push_span_label (
1096
+ fn_call_span,
1097
+ fluent:: borrowck_moved_a_fn_once_in_call,
1098
+ ) ;
1099
+ err. span_note ( span, fluent:: borrowck_moved_a_fn_once_in_call_call) ;
1100
+ } else {
1101
+ err. subdiagnostic (
1102
+ self . dcx ( ) ,
1103
+ CaptureReasonNote :: FnOnceMoveInCall { var_span } ,
1104
+ ) ;
1105
+ }
1052
1106
}
1053
1107
CallKind :: Operator { self_arg, trait_id, .. } => {
1054
1108
let self_arg = self_arg. unwrap ( ) ;
0 commit comments