@@ -271,205 +271,187 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
271271 ( None , true ) => "variant" ,
272272 }
273273 } ;
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, \
340335 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,
345354 ) ;
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- ) ;
360355
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) ;
386377 }
387378 }
388379 }
389- _ => { }
390380 }
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 ( ) ;
424409 }
425410 }
411+ }
412+ }
426413
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 {
438429 self . suggest_await_before_method (
439430 & mut err, item_name, actual, cal, span,
440431 ) ;
441432 }
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`, \
449438 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 \
458447 type behind the pointer: https://doc.rust-lang.org/std/\
459448 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 \
463452 which is unaligned or points to invalid \
464453 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+ ) ;
473455 }
474456
475457 if let Some ( def) = actual. ty_adt_def ( ) {
0 commit comments