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