@@ -271,205 +271,187 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
271
271
( None , true ) => "variant" ,
272
272
}
273
273
} ;
274
- // FIXME(eddyb) this indentation is probably unnecessary.
275
- let mut err = {
276
- // Suggest clamping down the type if the method that is being attempted to
277
- // be used exists at all, and the type is an ambiguous numeric type
278
- // ({integer}/{float}).
279
- let mut candidates = all_traits ( self . tcx )
280
- . into_iter ( )
281
- . filter_map ( |info| self . associated_value ( info. def_id , item_name) ) ;
282
- // There are methods that are defined on the primitive types and won't be
283
- // found when exploring `all_traits`, but we also need them to be accurate on
284
- // our suggestions (#47759).
285
- let found_assoc = |ty : Ty < ' tcx > | {
286
- simplify_type ( tcx, ty, TreatParams :: AsPlaceholders )
287
- . and_then ( |simp| {
288
- tcx. incoherent_impls ( simp)
289
- . iter ( )
290
- . find_map ( |& id| self . associated_value ( id, item_name) )
291
- } )
292
- . is_some ( )
293
- } ;
294
- let found_candidate = candidates. next ( ) . is_some ( )
295
- || found_assoc ( tcx. types . i8 )
296
- || found_assoc ( tcx. types . i16 )
297
- || found_assoc ( tcx. types . i32 )
298
- || found_assoc ( tcx. types . i64 )
299
- || found_assoc ( tcx. types . i128 )
300
- || found_assoc ( tcx. types . u8 )
301
- || found_assoc ( tcx. types . u16 )
302
- || found_assoc ( tcx. types . u32 )
303
- || found_assoc ( tcx. types . u64 )
304
- || found_assoc ( tcx. types . u128 )
305
- || found_assoc ( tcx. types . f32 )
306
- || found_assoc ( tcx. types . f32 ) ;
307
- if let ( true , false , SelfSource :: MethodCall ( expr) , true ) = (
308
- actual. is_numeric ( ) ,
309
- actual. has_concrete_skeleton ( ) ,
310
- source,
311
- found_candidate,
312
- ) {
313
- let mut err = struct_span_err ! (
314
- tcx. sess,
315
- span,
316
- E0689 ,
317
- "can't call {} `{}` on ambiguous numeric type `{}`" ,
318
- item_kind,
319
- item_name,
320
- ty_str
321
- ) ;
322
- let concrete_type = if actual. is_integral ( ) { "i32" } else { "f32" } ;
323
- match expr. kind {
324
- ExprKind :: Lit ( ref lit) => {
325
- // numeric literal
326
- let snippet = tcx
327
- . sess
328
- . source_map ( )
329
- . span_to_snippet ( lit. span )
330
- . unwrap_or_else ( |_| "<numeric literal>" . to_owned ( ) ) ;
331
-
332
- // If this is a floating point literal that ends with '.',
333
- // get rid of it to stop this from becoming a member access.
334
- let snippet = snippet. strip_suffix ( '.' ) . unwrap_or ( & snippet) ;
335
-
336
- err. span_suggestion (
337
- lit. span ,
338
- & format ! (
339
- "you must specify a concrete type for this numeric value, \
274
+ // Suggest clamping down the type if the method that is being attempted to
275
+ // be used exists at all, and the type is an ambiguous numeric type
276
+ // ({integer}/{float}).
277
+ let mut candidates = all_traits ( self . tcx )
278
+ . into_iter ( )
279
+ . filter_map ( |info| self . associated_value ( info. def_id , item_name) ) ;
280
+ // There are methods that are defined on the primitive types and won't be
281
+ // found when exploring `all_traits`, but we also need them to be accurate on
282
+ // our suggestions (#47759).
283
+ let found_assoc = |ty : Ty < ' tcx > | {
284
+ simplify_type ( tcx, ty, TreatParams :: AsPlaceholders )
285
+ . and_then ( |simp| {
286
+ tcx. incoherent_impls ( simp)
287
+ . iter ( )
288
+ . find_map ( |& id| self . associated_value ( id, item_name) )
289
+ } )
290
+ . is_some ( )
291
+ } ;
292
+ let found_candidate = candidates. next ( ) . is_some ( )
293
+ || found_assoc ( tcx. types . i8 )
294
+ || found_assoc ( tcx. types . i16 )
295
+ || found_assoc ( tcx. types . i32 )
296
+ || found_assoc ( tcx. types . i64 )
297
+ || found_assoc ( tcx. types . i128 )
298
+ || found_assoc ( tcx. types . u8 )
299
+ || found_assoc ( tcx. types . u16 )
300
+ || found_assoc ( tcx. types . u32 )
301
+ || found_assoc ( tcx. types . u64 )
302
+ || found_assoc ( tcx. types . u128 )
303
+ || found_assoc ( tcx. types . f32 )
304
+ || found_assoc ( tcx. types . f32 ) ;
305
+ if let ( true , false , SelfSource :: MethodCall ( expr) , true ) =
306
+ ( actual. is_numeric ( ) , actual. has_concrete_skeleton ( ) , source, found_candidate)
307
+ {
308
+ let mut err = struct_span_err ! (
309
+ tcx. sess,
310
+ span,
311
+ E0689 ,
312
+ "can't call {} `{}` on ambiguous numeric type `{}`" ,
313
+ item_kind,
314
+ item_name,
315
+ ty_str
316
+ ) ;
317
+ let concrete_type = if actual. is_integral ( ) { "i32" } else { "f32" } ;
318
+ match expr. kind {
319
+ ExprKind :: Lit ( ref lit) => {
320
+ // numeric literal
321
+ let snippet = tcx
322
+ . sess
323
+ . source_map ( )
324
+ . span_to_snippet ( lit. span )
325
+ . unwrap_or_else ( |_| "<numeric literal>" . to_owned ( ) ) ;
326
+
327
+ // If this is a floating point literal that ends with '.',
328
+ // get rid of it to stop this from becoming a member access.
329
+ let snippet = snippet. strip_suffix ( '.' ) . unwrap_or ( & snippet) ;
330
+
331
+ err. span_suggestion (
332
+ lit. span ,
333
+ & format ! (
334
+ "you must specify a concrete type for this numeric value, \
340
335
like `{}`",
341
- concrete_type
342
- ) ,
343
- format ! ( "{snippet}_{concrete_type}" ) ,
344
- Applicability :: MaybeIncorrect ,
336
+ concrete_type
337
+ ) ,
338
+ format ! ( "{snippet}_{concrete_type}" ) ,
339
+ Applicability :: MaybeIncorrect ,
340
+ ) ;
341
+ }
342
+ ExprKind :: Path ( QPath :: Resolved ( _, path) ) => {
343
+ // local binding
344
+ if let hir:: def:: Res :: Local ( hir_id) = path. res {
345
+ let span = tcx. hir ( ) . span ( hir_id) ;
346
+ let snippet = tcx. sess . source_map ( ) . span_to_snippet ( span) ;
347
+ let filename = tcx. sess . source_map ( ) . span_to_filename ( span) ;
348
+
349
+ let parent_node =
350
+ self . tcx . hir ( ) . get ( self . tcx . hir ( ) . get_parent_node ( hir_id) ) ;
351
+ let msg = format ! (
352
+ "you must specify a type for this binding, like `{}`" ,
353
+ concrete_type,
345
354
) ;
346
- }
347
- ExprKind :: Path ( QPath :: Resolved ( _, path) ) => {
348
- // local binding
349
- if let hir:: def:: Res :: Local ( hir_id) = path. res {
350
- let span = tcx. hir ( ) . span ( hir_id) ;
351
- let snippet = tcx. sess . source_map ( ) . span_to_snippet ( span) ;
352
- let filename = tcx. sess . source_map ( ) . span_to_filename ( span) ;
353
-
354
- let parent_node =
355
- self . tcx . hir ( ) . get ( self . tcx . hir ( ) . get_parent_node ( hir_id) ) ;
356
- let msg = format ! (
357
- "you must specify a type for this binding, like `{}`" ,
358
- concrete_type,
359
- ) ;
360
355
361
- match ( filename, parent_node, snippet) {
362
- (
363
- FileName :: Real ( _) ,
364
- Node :: Local ( hir:: Local {
365
- source : hir:: LocalSource :: Normal ,
366
- ty,
367
- ..
368
- } ) ,
369
- Ok ( ref snippet) ,
370
- ) => {
371
- err. span_suggestion (
372
- // account for `let x: _ = 42;`
373
- // ^^^^
374
- span. to ( ty
375
- . as_ref ( )
376
- . map ( |ty| ty. span )
377
- . unwrap_or ( span) ) ,
378
- & msg,
379
- format ! ( "{}: {}" , snippet, concrete_type) ,
380
- Applicability :: MaybeIncorrect ,
381
- ) ;
382
- }
383
- _ => {
384
- err. span_label ( span, msg) ;
385
- }
356
+ match ( filename, parent_node, snippet) {
357
+ (
358
+ FileName :: Real ( _) ,
359
+ Node :: Local ( hir:: Local {
360
+ source : hir:: LocalSource :: Normal ,
361
+ ty,
362
+ ..
363
+ } ) ,
364
+ Ok ( ref snippet) ,
365
+ ) => {
366
+ err. span_suggestion (
367
+ // account for `let x: _ = 42;`
368
+ // ^^^^
369
+ span. to ( ty. as_ref ( ) . map ( |ty| ty. span ) . unwrap_or ( span) ) ,
370
+ & msg,
371
+ format ! ( "{}: {}" , snippet, concrete_type) ,
372
+ Applicability :: MaybeIncorrect ,
373
+ ) ;
374
+ }
375
+ _ => {
376
+ err. span_label ( span, msg) ;
386
377
}
387
378
}
388
379
}
389
- _ => { }
390
380
}
391
- err. emit ( ) ;
392
- return None ;
393
- } else {
394
- span = item_name. span ;
395
-
396
- // Don't show generic arguments when the method can't be found in any implementation (#81576).
397
- let mut ty_str_reported = ty_str. clone ( ) ;
398
- if let ty:: Adt ( _, generics) = actual. kind ( ) {
399
- if generics. len ( ) > 0 {
400
- let mut autoderef = self . autoderef ( span, actual) ;
401
- let candidate_found = autoderef. any ( |( ty, _) | {
402
- if let ty:: Adt ( adt_deref, _) = ty. kind ( ) {
403
- self . tcx
404
- . inherent_impls ( adt_deref. did ( ) )
405
- . iter ( )
406
- . filter_map ( |def_id| {
407
- self . associated_value ( * def_id, item_name)
408
- } )
409
- . count ( )
410
- >= 1
411
- } else {
412
- false
413
- }
414
- } ) ;
415
- let has_deref = autoderef. step_count ( ) > 0 ;
416
- if !candidate_found
417
- && !has_deref
418
- && unsatisfied_predicates. is_empty ( )
419
- {
420
- if let Some ( ( path_string, _) ) = ty_str. split_once ( '<' ) {
421
- ty_str_reported = path_string. to_string ( ) ;
422
- }
423
- }
381
+ _ => { }
382
+ }
383
+ err. emit ( ) ;
384
+ return None ;
385
+ }
386
+ span = item_name. span ;
387
+
388
+ // Don't show generic arguments when the method can't be found in any implementation (#81576).
389
+ let mut ty_str_reported = ty_str. clone ( ) ;
390
+ if let ty:: Adt ( _, generics) = actual. kind ( ) {
391
+ if generics. len ( ) > 0 {
392
+ let mut autoderef = self . autoderef ( span, actual) ;
393
+ let candidate_found = autoderef. any ( |( ty, _) | {
394
+ if let ty:: Adt ( adt_deref, _) = ty. kind ( ) {
395
+ self . tcx
396
+ . inherent_impls ( adt_deref. did ( ) )
397
+ . iter ( )
398
+ . filter_map ( |def_id| self . associated_value ( * def_id, item_name) )
399
+ . count ( )
400
+ >= 1
401
+ } else {
402
+ false
403
+ }
404
+ } ) ;
405
+ let has_deref = autoderef. step_count ( ) > 0 ;
406
+ if !candidate_found && !has_deref && unsatisfied_predicates. is_empty ( ) {
407
+ if let Some ( ( path_string, _) ) = ty_str. split_once ( '<' ) {
408
+ ty_str_reported = path_string. to_string ( ) ;
424
409
}
425
410
}
411
+ }
412
+ }
426
413
427
- let mut err = struct_span_err ! (
428
- tcx. sess,
429
- span,
430
- E0599 ,
431
- "no {} named `{}` found for {} `{}` in the current scope" ,
432
- item_kind,
433
- item_name,
434
- actual. prefix_string( self . tcx) ,
435
- ty_str_reported,
436
- ) ;
437
- if let Mode :: MethodCall = mode && let SelfSource :: MethodCall ( cal) = source {
414
+ let mut err = struct_span_err ! (
415
+ tcx. sess,
416
+ span,
417
+ E0599 ,
418
+ "no {} named `{}` found for {} `{}` in the current scope" ,
419
+ item_kind,
420
+ item_name,
421
+ actual. prefix_string( self . tcx) ,
422
+ ty_str_reported,
423
+ ) ;
424
+ if actual. references_error ( ) {
425
+ err. downgrade_to_delayed_bug ( ) ;
426
+ }
427
+
428
+ if let Mode :: MethodCall = mode && let SelfSource :: MethodCall ( cal) = source {
438
429
self . suggest_await_before_method (
439
430
& mut err, item_name, actual, cal, span,
440
431
) ;
441
432
}
442
- if let Some ( span) =
443
- tcx. resolutions ( ( ) ) . confused_type_with_std_module . get ( & span)
444
- {
445
- if let Ok ( snippet) = tcx. sess . source_map ( ) . span_to_snippet ( * span) {
446
- err. span_suggestion (
447
- * span,
448
- "you are looking for the module in `std`, \
433
+ if let Some ( span) = tcx. resolutions ( ( ) ) . confused_type_with_std_module . get ( & span) {
434
+ if let Ok ( snippet) = tcx. sess . source_map ( ) . span_to_snippet ( * span) {
435
+ err. span_suggestion (
436
+ * span,
437
+ "you are looking for the module in `std`, \
449
438
not the primitive type",
450
- format ! ( "std::{}" , snippet) ,
451
- Applicability :: MachineApplicable ,
452
- ) ;
453
- }
454
- }
455
- if let ty:: RawPtr ( _) = & actual. kind ( ) {
456
- err. note (
457
- "try using `<*const T>::as_ref()` to get a reference to the \
439
+ format ! ( "std::{}" , snippet) ,
440
+ Applicability :: MachineApplicable ,
441
+ ) ;
442
+ }
443
+ }
444
+ if let ty:: RawPtr ( _) = & actual. kind ( ) {
445
+ err. note (
446
+ "try using `<*const T>::as_ref()` to get a reference to the \
458
447
type behind the pointer: https://doc.rust-lang.org/std/\
459
448
primitive.pointer.html#method.as_ref",
460
- ) ;
461
- err. note (
462
- "using `<*const T>::as_ref()` on a pointer \
449
+ ) ;
450
+ err. note (
451
+ "using `<*const T>::as_ref()` on a pointer \
463
452
which is unaligned or points to invalid \
464
453
or uninitialized memory is undefined behavior",
465
- ) ;
466
- }
467
- err
468
- }
469
- } ;
470
-
471
- if actual. references_error ( ) {
472
- err. downgrade_to_delayed_bug ( ) ;
454
+ ) ;
473
455
}
474
456
475
457
if let Some ( def) = actual. ty_adt_def ( ) {
0 commit comments