@@ -71,7 +71,7 @@ pub trait InferCtxtExt<'tcx> {
71
71
/// returns a span and `ArgKind` information that describes the
72
72
/// arguments it expects. This can be supplied to
73
73
/// `report_arg_count_mismatch`.
74
- fn get_fn_like_arguments ( & self , node : Node < ' _ > ) -> Option < ( Span , Vec < ArgKind > ) > ;
74
+ fn get_fn_like_arguments ( & self , node : Node < ' _ > ) -> Option < ( Span , Option < Span > , Vec < ArgKind > ) > ;
75
75
76
76
/// Reports an error when the number of arguments needed by a
77
77
/// trait match doesn't match the number that the expression
@@ -83,6 +83,7 @@ pub trait InferCtxtExt<'tcx> {
83
83
expected_args : Vec < ArgKind > ,
84
84
found_args : Vec < ArgKind > ,
85
85
is_closure : bool ,
86
+ closure_pipe_span : Option < Span > ,
86
87
) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > ;
87
88
88
89
/// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce`
@@ -135,15 +136,16 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
135
136
/// returns a span and `ArgKind` information that describes the
136
137
/// arguments it expects. This can be supplied to
137
138
/// `report_arg_count_mismatch`.
138
- fn get_fn_like_arguments ( & self , node : Node < ' _ > ) -> Option < ( Span , Vec < ArgKind > ) > {
139
+ fn get_fn_like_arguments ( & self , node : Node < ' _ > ) -> Option < ( Span , Option < Span > , Vec < ArgKind > ) > {
139
140
let sm = self . tcx . sess . source_map ( ) ;
140
141
let hir = self . tcx . hir ( ) ;
141
142
Some ( match node {
142
143
Node :: Expr ( & hir:: Expr {
143
- kind : hir:: ExprKind :: Closure ( & hir:: Closure { body, fn_decl_span, .. } ) ,
144
+ kind : hir:: ExprKind :: Closure ( & hir:: Closure { body, fn_decl_span, fn_arg_span , .. } ) ,
144
145
..
145
146
} ) => (
146
147
fn_decl_span,
148
+ fn_arg_span,
147
149
hir. body ( body)
148
150
. params
149
151
. iter ( )
@@ -174,6 +176,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
174
176
kind : hir:: TraitItemKind :: Fn ( ref sig, _) , ..
175
177
} ) => (
176
178
sig. span ,
179
+ None ,
177
180
sig. decl
178
181
. inputs
179
182
. iter ( )
@@ -188,7 +191,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
188
191
) ,
189
192
Node :: Ctor ( ref variant_data) => {
190
193
let span = variant_data. ctor_hir_id ( ) . map_or ( DUMMY_SP , |id| hir. span ( id) ) ;
191
- ( span, vec ! [ ArgKind :: empty( ) ; variant_data. fields( ) . len( ) ] )
194
+ ( span, None , vec ! [ ArgKind :: empty( ) ; variant_data. fields( ) . len( ) ] )
192
195
}
193
196
_ => panic ! ( "non-FnLike node found: {:?}" , node) ,
194
197
} )
@@ -204,6 +207,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
204
207
expected_args : Vec < ArgKind > ,
205
208
found_args : Vec < ArgKind > ,
206
209
is_closure : bool ,
210
+ closure_arg_span : Option < Span > ,
207
211
) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
208
212
let kind = if is_closure { "closure" } else { "function" } ;
209
213
@@ -241,24 +245,13 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
241
245
if let Some ( found_span) = found_span {
242
246
err. span_label ( found_span, format ! ( "takes {}" , found_str) ) ;
243
247
244
- // move |_| { ... }
245
- // ^^^^^^^^-- def_span
246
- //
247
- // move |_| { ... }
248
- // ^^^^^-- prefix
249
- let prefix_span = self . tcx . sess . source_map ( ) . span_until_non_whitespace ( found_span) ;
250
- // move |_| { ... }
251
- // ^^^-- pipe_span
252
- let pipe_span =
253
- if let Some ( span) = found_span. trim_start ( prefix_span) { span } else { found_span } ;
254
-
255
248
// Suggest to take and ignore the arguments with expected_args_length `_`s if
256
249
// found arguments is empty (assume the user just wants to ignore args in this case).
257
250
// For example, if `expected_args_length` is 2, suggest `|_, _|`.
258
251
if found_args. is_empty ( ) && is_closure {
259
252
let underscores = vec ! [ "_" ; expected_args. len( ) ] . join ( ", " ) ;
260
253
err. span_suggestion_verbose (
261
- pipe_span ,
254
+ closure_arg_span . unwrap_or ( found_span ) ,
262
255
& format ! (
263
256
"consider changing the closure to take and ignore the expected argument{}" ,
264
257
pluralize!( expected_args. len( ) )
@@ -1252,20 +1245,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1252
1245
obligation. cause . code ( ) ,
1253
1246
)
1254
1247
} else {
1255
- let ( closure_span, found) = found_did
1248
+ let ( closure_span, closure_arg_span , found) = found_did
1256
1249
. and_then ( |did| {
1257
1250
let node = self . tcx . hir ( ) . get_if_local ( did) ?;
1258
- let ( found_span, found) = self . get_fn_like_arguments ( node) ?;
1259
- Some ( ( Some ( found_span) , found) )
1251
+ let ( found_span, closure_arg_span, found) =
1252
+ self . get_fn_like_arguments ( node) ?;
1253
+ Some ( ( Some ( found_span) , closure_arg_span, found) )
1260
1254
} )
1261
- . unwrap_or ( ( found_span, found) ) ;
1255
+ . unwrap_or ( ( found_span, None , found) ) ;
1262
1256
1263
1257
self . report_arg_count_mismatch (
1264
1258
span,
1265
1259
closure_span,
1266
1260
expected,
1267
1261
found,
1268
1262
found_trait_ty. is_closure ( ) ,
1263
+ closure_arg_span,
1269
1264
)
1270
1265
}
1271
1266
}
0 commit comments