@@ -102,7 +102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
102
102
103
103
pub fn report_method_error (
104
104
& self ,
105
- mut span : Span ,
105
+ span : Span ,
106
106
rcvr_ty : Ty < ' tcx > ,
107
107
item_name : Ident ,
108
108
source : SelfSource < ' tcx > ,
@@ -114,144 +114,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
114
114
return None ;
115
115
}
116
116
117
- let report_candidates = |span : Span ,
118
- err : & mut Diagnostic ,
119
- sources : & mut Vec < CandidateSource > ,
120
- sugg_span : Option < Span > | {
121
- sources. sort ( ) ;
122
- sources. dedup ( ) ;
123
- // Dynamic limit to avoid hiding just one candidate, which is silly.
124
- let limit = if sources. len ( ) == 5 { 5 } else { 4 } ;
125
-
126
- for ( idx, source) in sources. iter ( ) . take ( limit) . enumerate ( ) {
127
- match * source {
128
- CandidateSource :: Impl ( impl_did) => {
129
- // Provide the best span we can. Use the item, if local to crate, else
130
- // the impl, if local to crate (item may be defaulted), else nothing.
131
- let Some ( item) = self . associated_value ( impl_did, item_name) . or_else ( || {
132
- let impl_trait_ref = self . tcx . impl_trait_ref ( impl_did) ?;
133
- self . associated_value ( impl_trait_ref. def_id , item_name)
134
- } ) else {
135
- continue ;
136
- } ;
137
-
138
- let note_span = if item. def_id . is_local ( ) {
139
- Some ( self . tcx . def_span ( item. def_id ) )
140
- } else if impl_did. is_local ( ) {
141
- Some ( self . tcx . def_span ( impl_did) )
142
- } else {
143
- None
144
- } ;
145
-
146
- let impl_ty = self . tcx . at ( span) . type_of ( impl_did) ;
147
-
148
- let insertion = match self . tcx . impl_trait_ref ( impl_did) {
149
- None => String :: new ( ) ,
150
- Some ( trait_ref) => format ! (
151
- " of the trait `{}`" ,
152
- self . tcx. def_path_str( trait_ref. def_id)
153
- ) ,
154
- } ;
155
-
156
- let ( note_str, idx) = if sources. len ( ) > 1 {
157
- (
158
- format ! (
159
- "candidate #{} is defined in an impl{} for the type `{}`" ,
160
- idx + 1 ,
161
- insertion,
162
- impl_ty,
163
- ) ,
164
- Some ( idx + 1 ) ,
165
- )
166
- } else {
167
- (
168
- format ! (
169
- "the candidate is defined in an impl{} for the type `{}`" ,
170
- insertion, impl_ty,
171
- ) ,
172
- None ,
173
- )
174
- } ;
175
- if let Some ( note_span) = note_span {
176
- // We have a span pointing to the method. Show note with snippet.
177
- err. span_note ( note_span, & note_str) ;
178
- } else {
179
- err. note ( & note_str) ;
180
- }
181
- if let Some ( sugg_span) = sugg_span
182
- && let Some ( trait_ref) = self . tcx . impl_trait_ref ( impl_did) {
183
- let path = self . tcx . def_path_str ( trait_ref. def_id ) ;
184
-
185
- let ty = match item. kind {
186
- ty:: AssocKind :: Const | ty:: AssocKind :: Type => rcvr_ty,
187
- ty:: AssocKind :: Fn => self
188
- . tcx
189
- . fn_sig ( item. def_id )
190
- . inputs ( )
191
- . skip_binder ( )
192
- . get ( 0 )
193
- . filter ( |ty| ty. is_region_ptr ( ) && !rcvr_ty. is_region_ptr ( ) )
194
- . copied ( )
195
- . unwrap_or ( rcvr_ty) ,
196
- } ;
197
- print_disambiguation_help (
198
- item_name,
199
- args,
200
- err,
201
- path,
202
- ty,
203
- item. kind ,
204
- item. def_id ,
205
- sugg_span,
206
- idx,
207
- self . tcx . sess . source_map ( ) ,
208
- item. fn_has_self_parameter ,
209
- ) ;
210
- }
211
- }
212
- CandidateSource :: Trait ( trait_did) => {
213
- let Some ( item) = self . associated_value ( trait_did, item_name) else { continue } ;
214
- let item_span = self . tcx . def_span ( item. def_id ) ;
215
- let idx = if sources. len ( ) > 1 {
216
- let msg = & format ! (
217
- "candidate #{} is defined in the trait `{}`" ,
218
- idx + 1 ,
219
- self . tcx. def_path_str( trait_did)
220
- ) ;
221
- err. span_note ( item_span, msg) ;
222
- Some ( idx + 1 )
223
- } else {
224
- let msg = & format ! (
225
- "the candidate is defined in the trait `{}`" ,
226
- self . tcx. def_path_str( trait_did)
227
- ) ;
228
- err. span_note ( item_span, msg) ;
229
- None
230
- } ;
231
- if let Some ( sugg_span) = sugg_span {
232
- let path = self . tcx . def_path_str ( trait_did) ;
233
- print_disambiguation_help (
234
- item_name,
235
- args,
236
- err,
237
- path,
238
- rcvr_ty,
239
- item. kind ,
240
- item. def_id ,
241
- sugg_span,
242
- idx,
243
- self . tcx . sess . source_map ( ) ,
244
- item. fn_has_self_parameter ,
245
- ) ;
246
- }
247
- }
248
- }
249
- }
250
- if sources. len ( ) > limit {
251
- err. note ( & format ! ( "and {} others" , sources. len( ) - limit) ) ;
252
- }
253
- } ;
254
-
255
117
let sugg_span = if let SelfSource :: MethodCall ( expr) = source {
256
118
// Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
257
119
self . tcx . hir ( ) . expect_expr ( self . tcx . hir ( ) . get_parent_node ( expr. hir_id ) ) . span
@@ -260,777 +122,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
260
122
} ;
261
123
262
124
match error {
263
- MethodError :: NoMatch ( NoMatchData {
264
- mut static_candidates,
265
- unsatisfied_predicates,
266
- out_of_scope_traits,
267
- lev_candidate,
268
- mode,
269
- } ) => {
270
- let tcx = self . tcx ;
271
-
272
- let rcvr_ty = self . resolve_vars_if_possible ( rcvr_ty) ;
273
- let ty_str = with_forced_trimmed_paths ! ( self . ty_to_string( rcvr_ty) ) ;
274
- let is_method = mode == Mode :: MethodCall ;
275
- let item_kind = if is_method {
276
- "method"
277
- } else if rcvr_ty. is_enum ( ) {
278
- "variant or associated item"
279
- } else {
280
- match ( item_name. as_str ( ) . chars ( ) . next ( ) , rcvr_ty. is_fresh_ty ( ) ) {
281
- ( Some ( name) , false ) if name. is_lowercase ( ) => "function or associated item" ,
282
- ( Some ( _) , false ) => "associated item" ,
283
- ( Some ( _) , true ) | ( None , false ) => "variant or associated item" ,
284
- ( None , true ) => "variant" ,
285
- }
286
- } ;
287
-
288
- if self . suggest_wrapping_range_with_parens (
289
- tcx, rcvr_ty, source, span, item_name, & ty_str,
290
- ) || self . suggest_constraining_numerical_ty (
291
- tcx, rcvr_ty, source, span, item_kind, item_name, & ty_str,
292
- ) {
293
- return None ;
294
- }
295
- span = item_name. span ;
296
-
297
- // Don't show generic arguments when the method can't be found in any implementation (#81576).
298
- let mut ty_str_reported = ty_str. clone ( ) ;
299
- if let ty:: Adt ( _, generics) = rcvr_ty. kind ( ) {
300
- if generics. len ( ) > 0 {
301
- let mut autoderef = self . autoderef ( span, rcvr_ty) ;
302
- let candidate_found = autoderef. any ( |( ty, _) | {
303
- if let ty:: Adt ( adt_def, _) = ty. kind ( ) {
304
- self . tcx
305
- . inherent_impls ( adt_def. did ( ) )
306
- . iter ( )
307
- . filter_map ( |def_id| self . associated_value ( * def_id, item_name) )
308
- . count ( )
309
- >= 1
310
- } else {
311
- false
312
- }
313
- } ) ;
314
- let has_deref = autoderef. step_count ( ) > 0 ;
315
- if !candidate_found && !has_deref && unsatisfied_predicates. is_empty ( ) {
316
- if let Some ( ( path_string, _) ) = ty_str. split_once ( '<' ) {
317
- ty_str_reported = path_string. to_string ( ) ;
318
- }
319
- }
320
- }
321
- }
322
-
323
- let mut err = struct_span_err ! (
324
- tcx. sess,
125
+ MethodError :: NoMatch ( mut no_match_data) => {
126
+ return self . report_no_match_method_error (
325
127
span,
326
- E0599 ,
327
- "no {} named `{}` found for {} `{}` in the current scope" ,
328
- item_kind,
128
+ rcvr_ty,
329
129
item_name,
330
- rcvr_ty. prefix_string( self . tcx) ,
331
- ty_str_reported,
130
+ source,
131
+ args,
132
+ sugg_span,
133
+ & mut no_match_data,
332
134
) ;
333
- if rcvr_ty. references_error ( ) {
334
- err. downgrade_to_delayed_bug ( ) ;
335
- }
336
-
337
- if let Mode :: MethodCall = mode && let SelfSource :: MethodCall ( cal) = source {
338
- self . suggest_await_before_method (
339
- & mut err, item_name, rcvr_ty, cal, span,
340
- ) ;
341
- }
342
- if let Some ( span) =
343
- tcx. resolutions ( ( ) ) . confused_type_with_std_module . get ( & span. with_parent ( None ) )
344
- {
345
- err. span_suggestion (
346
- span. shrink_to_lo ( ) ,
347
- "you are looking for the module in `std`, not the primitive type" ,
348
- "std::" ,
349
- Applicability :: MachineApplicable ,
350
- ) ;
351
- }
352
- if let ty:: RawPtr ( _) = & rcvr_ty. kind ( ) {
353
- err. note (
354
- "try using `<*const T>::as_ref()` to get a reference to the \
355
- type behind the pointer: https://doc.rust-lang.org/std/\
356
- primitive.pointer.html#method.as_ref",
357
- ) ;
358
- err. note (
359
- "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
360
- to invalid or uninitialized memory is undefined behavior",
361
- ) ;
362
- }
363
-
364
- let ty_span = match rcvr_ty. kind ( ) {
365
- ty:: Param ( param_type) => Some (
366
- param_type. span_from_generics ( self . tcx , self . body_id . owner . to_def_id ( ) ) ,
367
- ) ,
368
- ty:: Adt ( def, _) if def. did ( ) . is_local ( ) => Some ( tcx. def_span ( def. did ( ) ) ) ,
369
- _ => None ,
370
- } ;
371
- if let Some ( span) = ty_span {
372
- err. span_label (
373
- span,
374
- format ! (
375
- "{item_kind} `{item_name}` not found for this {}" ,
376
- rcvr_ty. prefix_string( self . tcx)
377
- ) ,
378
- ) ;
379
- }
380
-
381
- if let SelfSource :: MethodCall ( rcvr_expr) = source {
382
- self . suggest_fn_call ( & mut err, rcvr_expr, rcvr_ty, |output_ty| {
383
- let call_expr = self
384
- . tcx
385
- . hir ( )
386
- . expect_expr ( self . tcx . hir ( ) . get_parent_node ( rcvr_expr. hir_id ) ) ;
387
- let probe = self . lookup_probe (
388
- item_name,
389
- output_ty,
390
- call_expr,
391
- ProbeScope :: AllTraits ,
392
- ) ;
393
- probe. is_ok ( )
394
- } ) ;
395
- }
396
-
397
- let mut custom_span_label = false ;
398
-
399
- if !static_candidates. is_empty ( ) {
400
- err. note (
401
- "found the following associated functions; to be used as methods, \
402
- functions must have a `self` parameter",
403
- ) ;
404
- err. span_label ( span, "this is an associated function, not a method" ) ;
405
- custom_span_label = true ;
406
- }
407
- if static_candidates. len ( ) == 1 {
408
- self . suggest_associated_call_syntax (
409
- & mut err,
410
- & static_candidates,
411
- rcvr_ty,
412
- source,
413
- item_name,
414
- args,
415
- sugg_span,
416
- ) ;
417
-
418
- report_candidates ( span, & mut err, & mut static_candidates, None ) ;
419
- } else if static_candidates. len ( ) > 1 {
420
- report_candidates ( span, & mut err, & mut static_candidates, Some ( sugg_span) ) ;
421
- }
422
-
423
- let mut bound_spans = vec ! [ ] ;
424
- let mut restrict_type_params = false ;
425
- let mut unsatisfied_bounds = false ;
426
- if item_name. name == sym:: count && self . is_slice_ty ( rcvr_ty, span) {
427
- let msg = "consider using `len` instead" ;
428
- if let SelfSource :: MethodCall ( _expr) = source {
429
- err. span_suggestion_short (
430
- span,
431
- msg,
432
- "len" ,
433
- Applicability :: MachineApplicable ,
434
- ) ;
435
- } else {
436
- err. span_label ( span, msg) ;
437
- }
438
- if let Some ( iterator_trait) = self . tcx . get_diagnostic_item ( sym:: Iterator ) {
439
- let iterator_trait = self . tcx . def_path_str ( iterator_trait) ;
440
- err. note ( & format ! ( "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement" ) ) ;
441
- }
442
- } else if !unsatisfied_predicates. is_empty ( ) {
443
- let mut type_params = FxHashMap :: default ( ) ;
444
-
445
- // Pick out the list of unimplemented traits on the receiver.
446
- // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
447
- let mut unimplemented_traits = FxHashMap :: default ( ) ;
448
- let mut unimplemented_traits_only = true ;
449
- for ( predicate, _parent_pred, cause) in & unsatisfied_predicates {
450
- if let ( ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( p) ) , Some ( cause) ) =
451
- ( predicate. kind ( ) . skip_binder ( ) , cause. as_ref ( ) )
452
- {
453
- if p. trait_ref . self_ty ( ) != rcvr_ty {
454
- // This is necessary, not just to keep the errors clean, but also
455
- // because our derived obligations can wind up with a trait ref that
456
- // requires a different param_env to be correctly compared.
457
- continue ;
458
- }
459
- unimplemented_traits. entry ( p. trait_ref . def_id ) . or_insert ( (
460
- predicate. kind ( ) . rebind ( p. trait_ref ) ,
461
- Obligation {
462
- cause : cause. clone ( ) ,
463
- param_env : self . param_env ,
464
- predicate : * predicate,
465
- recursion_depth : 0 ,
466
- } ,
467
- ) ) ;
468
- }
469
- }
470
-
471
- // Make sure that, if any traits other than the found ones were involved,
472
- // we don't don't report an unimplemented trait.
473
- // We don't want to say that `iter::Cloned` is not an iterator, just
474
- // because of some non-Clone item being iterated over.
475
- for ( predicate, _parent_pred, _cause) in & unsatisfied_predicates {
476
- match predicate. kind ( ) . skip_binder ( ) {
477
- ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( p) )
478
- if unimplemented_traits. contains_key ( & p. trait_ref . def_id ) => { }
479
- _ => {
480
- unimplemented_traits_only = false ;
481
- break ;
482
- }
483
- }
484
- }
485
-
486
- let mut collect_type_param_suggestions =
487
- |self_ty : Ty < ' tcx > , parent_pred : ty:: Predicate < ' tcx > , obligation : & str | {
488
- // We don't care about regions here, so it's fine to skip the binder here.
489
- if let ( ty:: Param ( _) , ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( p) ) ) =
490
- ( self_ty. kind ( ) , parent_pred. kind ( ) . skip_binder ( ) )
491
- {
492
- let hir = self . tcx . hir ( ) ;
493
- let node = match p. trait_ref . self_ty ( ) . kind ( ) {
494
- ty:: Param ( _) => {
495
- // Account for `fn` items like in `issue-35677.rs` to
496
- // suggest restricting its type params.
497
- let parent_body =
498
- hir. body_owner ( hir:: BodyId { hir_id : self . body_id } ) ;
499
- Some ( hir. get ( parent_body) )
500
- }
501
- ty:: Adt ( def, _) => {
502
- def. did ( ) . as_local ( ) . map ( |def_id| hir. get_by_def_id ( def_id) )
503
- }
504
- _ => None ,
505
- } ;
506
- if let Some ( hir:: Node :: Item ( hir:: Item { kind, .. } ) ) = node {
507
- if let Some ( g) = kind. generics ( ) {
508
- let key = (
509
- g. tail_span_for_predicate_suggestion ( ) ,
510
- g. add_where_or_trailing_comma ( ) ,
511
- ) ;
512
- type_params
513
- . entry ( key)
514
- . or_insert_with ( FxHashSet :: default)
515
- . insert ( obligation. to_owned ( ) ) ;
516
- }
517
- }
518
- }
519
- } ;
520
- let mut bound_span_label = |self_ty : Ty < ' _ > , obligation : & str , quiet : & str | {
521
- let msg = format ! (
522
- "doesn't satisfy `{}`" ,
523
- if obligation. len( ) > 50 { quiet } else { obligation }
524
- ) ;
525
- match & self_ty. kind ( ) {
526
- // Point at the type that couldn't satisfy the bound.
527
- ty:: Adt ( def, _) => {
528
- bound_spans. push ( ( self . tcx . def_span ( def. did ( ) ) , msg) )
529
- }
530
- // Point at the trait object that couldn't satisfy the bound.
531
- ty:: Dynamic ( preds, _, _) => {
532
- for pred in preds. iter ( ) {
533
- match pred. skip_binder ( ) {
534
- ty:: ExistentialPredicate :: Trait ( tr) => bound_spans
535
- . push ( ( self . tcx . def_span ( tr. def_id ) , msg. clone ( ) ) ) ,
536
- ty:: ExistentialPredicate :: Projection ( _)
537
- | ty:: ExistentialPredicate :: AutoTrait ( _) => { }
538
- }
539
- }
540
- }
541
- // Point at the closure that couldn't satisfy the bound.
542
- ty:: Closure ( def_id, _) => bound_spans. push ( (
543
- tcx. def_span ( * def_id) ,
544
- format ! ( "doesn't satisfy `{}`" , quiet) ,
545
- ) ) ,
546
- _ => { }
547
- }
548
- } ;
549
- let mut format_pred = |pred : ty:: Predicate < ' tcx > | {
550
- let bound_predicate = pred. kind ( ) ;
551
- match bound_predicate. skip_binder ( ) {
552
- ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( pred) ) => {
553
- let pred = bound_predicate. rebind ( pred) ;
554
- // `<Foo as Iterator>::Item = String`.
555
- let projection_ty = pred. skip_binder ( ) . projection_ty ;
556
-
557
- let substs_with_infer_self = tcx. mk_substs (
558
- iter:: once ( tcx. mk_ty_var ( ty:: TyVid :: from_u32 ( 0 ) ) . into ( ) )
559
- . chain ( projection_ty. substs . iter ( ) . skip ( 1 ) ) ,
560
- ) ;
561
-
562
- let quiet_projection_ty =
563
- tcx. mk_alias_ty ( projection_ty. def_id , substs_with_infer_self) ;
564
-
565
- let term = pred. skip_binder ( ) . term ;
566
-
567
- let obligation = format ! ( "{} = {}" , projection_ty, term) ;
568
- let quiet = with_forced_trimmed_paths ! ( format!(
569
- "{} = {}" ,
570
- quiet_projection_ty, term
571
- ) ) ;
572
-
573
- bound_span_label ( projection_ty. self_ty ( ) , & obligation, & quiet) ;
574
- Some ( ( obligation, projection_ty. self_ty ( ) ) )
575
- }
576
- ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( poly_trait_ref) ) => {
577
- let p = poly_trait_ref. trait_ref ;
578
- let self_ty = p. self_ty ( ) ;
579
- let path = p. print_only_trait_path ( ) ;
580
- let obligation = format ! ( "{}: {}" , self_ty, path) ;
581
- let quiet = with_forced_trimmed_paths ! ( format!( "_: {}" , path) ) ;
582
- bound_span_label ( self_ty, & obligation, & quiet) ;
583
- Some ( ( obligation, self_ty) )
584
- }
585
- _ => None ,
586
- }
587
- } ;
588
-
589
- // Find all the requirements that come from a local `impl` block.
590
- let mut skip_list: FxHashSet < _ > = Default :: default ( ) ;
591
- let mut spanned_predicates: FxHashMap < MultiSpan , _ > = Default :: default ( ) ;
592
- for ( data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
593
- . iter ( )
594
- . filter_map ( |( p, parent, c) | c. as_ref ( ) . map ( |c| ( p, parent, c) ) )
595
- . filter_map ( |( p, parent, c) | match c. code ( ) {
596
- ObligationCauseCode :: ImplDerivedObligation ( data) => {
597
- Some ( ( & data. derived , p, parent, data. impl_def_id , data) )
598
- }
599
- _ => None ,
600
- } )
601
- {
602
- let parent_trait_ref = data. parent_trait_pred ;
603
- let path = parent_trait_ref. print_modifiers_and_trait_path ( ) ;
604
- let tr_self_ty = parent_trait_ref. skip_binder ( ) . self_ty ( ) ;
605
- let unsatisfied_msg = "unsatisfied trait bound introduced here" ;
606
- let derive_msg =
607
- "unsatisfied trait bound introduced in this `derive` macro" ;
608
- match self . tcx . hir ( ) . get_if_local ( impl_def_id) {
609
- // Unmet obligation comes from a `derive` macro, point at it once to
610
- // avoid multiple span labels pointing at the same place.
611
- Some ( Node :: Item ( hir:: Item {
612
- kind : hir:: ItemKind :: Impl ( hir:: Impl { of_trait, self_ty, .. } ) ,
613
- ..
614
- } ) ) if matches ! (
615
- self_ty. span. ctxt( ) . outer_expn_data( ) . kind,
616
- ExpnKind :: Macro ( MacroKind :: Derive , _)
617
- ) || matches ! (
618
- of_trait. as_ref( ) . map( |t| t
619
- . path
620
- . span
621
- . ctxt( )
622
- . outer_expn_data( )
623
- . kind) ,
624
- Some ( ExpnKind :: Macro ( MacroKind :: Derive , _) )
625
- ) =>
626
- {
627
- let span = self_ty. span . ctxt ( ) . outer_expn_data ( ) . call_site ;
628
- let mut spans: MultiSpan = span. into ( ) ;
629
- spans. push_span_label ( span, derive_msg) ;
630
- let entry = spanned_predicates. entry ( spans) ;
631
- entry. or_insert_with ( || ( path, tr_self_ty, Vec :: new ( ) ) ) . 2 . push ( p) ;
632
- }
633
-
634
- // Unmet obligation coming from an `impl`.
635
- Some ( Node :: Item ( hir:: Item {
636
- kind :
637
- hir:: ItemKind :: Impl ( hir:: Impl {
638
- of_trait, self_ty, generics, ..
639
- } ) ,
640
- span : item_span,
641
- ..
642
- } ) ) => {
643
- let sized_pred =
644
- unsatisfied_predicates. iter ( ) . any ( |( pred, _, _) | {
645
- match pred. kind ( ) . skip_binder ( ) {
646
- ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( pred) ) => {
647
- Some ( pred. def_id ( ) )
648
- == self . tcx . lang_items ( ) . sized_trait ( )
649
- && pred. polarity == ty:: ImplPolarity :: Positive
650
- }
651
- _ => false ,
652
- }
653
- } ) ;
654
- for param in generics. params {
655
- if param. span == cause. span && sized_pred {
656
- let ( sp, sugg) = match param. colon_span {
657
- Some ( sp) => ( sp. shrink_to_hi ( ) , " ?Sized +" ) ,
658
- None => ( param. span . shrink_to_hi ( ) , ": ?Sized" ) ,
659
- } ;
660
- err. span_suggestion_verbose (
661
- sp,
662
- "consider relaxing the type parameter's implicit \
663
- `Sized` bound",
664
- sugg,
665
- Applicability :: MachineApplicable ,
666
- ) ;
667
- }
668
- }
669
- if let Some ( pred) = parent_p {
670
- // Done to add the "doesn't satisfy" `span_label`.
671
- let _ = format_pred ( * pred) ;
672
- }
673
- skip_list. insert ( p) ;
674
- let mut spans = if cause. span != * item_span {
675
- let mut spans: MultiSpan = cause. span . into ( ) ;
676
- spans. push_span_label ( cause. span , unsatisfied_msg) ;
677
- spans
678
- } else {
679
- let mut spans = Vec :: with_capacity ( 2 ) ;
680
- if let Some ( trait_ref) = of_trait {
681
- spans. push ( trait_ref. path . span ) ;
682
- }
683
- spans. push ( self_ty. span ) ;
684
- spans. into ( )
685
- } ;
686
- if let Some ( trait_ref) = of_trait {
687
- spans. push_span_label ( trait_ref. path . span , "" ) ;
688
- }
689
- spans. push_span_label ( self_ty. span , "" ) ;
690
-
691
- let entry = spanned_predicates. entry ( spans) ;
692
- entry. or_insert_with ( || ( path, tr_self_ty, Vec :: new ( ) ) ) . 2 . push ( p) ;
693
- }
694
- Some ( Node :: Item ( hir:: Item {
695
- kind : hir:: ItemKind :: Trait ( rustc_ast:: ast:: IsAuto :: Yes , ..) ,
696
- span : item_span,
697
- ..
698
- } ) ) => {
699
- tcx. sess . delay_span_bug (
700
- * item_span,
701
- "auto trait is invoked with no method error, but no error reported?" ,
702
- ) ;
703
- }
704
- Some ( _) => unreachable ! ( ) ,
705
- None => ( ) ,
706
- }
707
- }
708
- let mut spanned_predicates: Vec < _ > = spanned_predicates. into_iter ( ) . collect ( ) ;
709
- spanned_predicates. sort_by_key ( |( span, ( _, _, _) ) | span. primary_span ( ) ) ;
710
- for ( span, ( _path, _self_ty, preds) ) in spanned_predicates {
711
- let mut preds: Vec < _ > = preds
712
- . into_iter ( )
713
- . filter_map ( |pred| format_pred ( * pred) )
714
- . map ( |( p, _) | format ! ( "`{}`" , p) )
715
- . collect ( ) ;
716
- preds. sort ( ) ;
717
- preds. dedup ( ) ;
718
- let msg = if let [ pred] = & preds[ ..] {
719
- format ! ( "trait bound {} was not satisfied" , pred)
720
- } else {
721
- format ! (
722
- "the following trait bounds were not satisfied:\n {}" ,
723
- preds. join( "\n " ) ,
724
- )
725
- } ;
726
- err. span_note ( span, & msg) ;
727
- unsatisfied_bounds = true ;
728
- }
729
-
730
- // The requirements that didn't have an `impl` span to show.
731
- let mut bound_list = unsatisfied_predicates
732
- . iter ( )
733
- . filter_map ( |( pred, parent_pred, _cause) | {
734
- format_pred ( * pred) . map ( |( p, self_ty) | {
735
- collect_type_param_suggestions ( self_ty, * pred, & p) ;
736
- (
737
- match parent_pred {
738
- None => format ! ( "`{}`" , & p) ,
739
- Some ( parent_pred) => match format_pred ( * parent_pred) {
740
- None => format ! ( "`{}`" , & p) ,
741
- Some ( ( parent_p, _) ) => {
742
- collect_type_param_suggestions (
743
- self_ty,
744
- * parent_pred,
745
- & p,
746
- ) ;
747
- format ! (
748
- "`{}`\n which is required by `{}`" ,
749
- p, parent_p
750
- )
751
- }
752
- } ,
753
- } ,
754
- * pred,
755
- )
756
- } )
757
- } )
758
- . filter ( |( _, pred) | !skip_list. contains ( & pred) )
759
- . map ( |( t, _) | t)
760
- . enumerate ( )
761
- . collect :: < Vec < ( usize , String ) > > ( ) ;
762
-
763
- for ( ( span, add_where_or_comma) , obligations) in type_params. into_iter ( ) {
764
- restrict_type_params = true ;
765
- // #74886: Sort here so that the output is always the same.
766
- let mut obligations = obligations. into_iter ( ) . collect :: < Vec < _ > > ( ) ;
767
- obligations. sort ( ) ;
768
- err. span_suggestion_verbose (
769
- span,
770
- & format ! (
771
- "consider restricting the type parameter{s} to satisfy the \
772
- trait bound{s}",
773
- s = pluralize!( obligations. len( ) )
774
- ) ,
775
- format ! ( "{} {}" , add_where_or_comma, obligations. join( ", " ) ) ,
776
- Applicability :: MaybeIncorrect ,
777
- ) ;
778
- }
779
-
780
- bound_list. sort_by ( |( _, a) , ( _, b) | a. cmp ( b) ) ; // Sort alphabetically.
781
- bound_list. dedup_by ( |( _, a) , ( _, b) | a == b) ; // #35677
782
- bound_list. sort_by_key ( |( pos, _) | * pos) ; // Keep the original predicate order.
783
-
784
- if !bound_list. is_empty ( ) || !skip_list. is_empty ( ) {
785
- let bound_list = bound_list
786
- . into_iter ( )
787
- . map ( |( _, path) | path)
788
- . collect :: < Vec < _ > > ( )
789
- . join ( "\n " ) ;
790
- let actual_prefix = rcvr_ty. prefix_string ( self . tcx ) ;
791
- info ! ( "unimplemented_traits.len() == {}" , unimplemented_traits. len( ) ) ;
792
- let ( primary_message, label) =
793
- if unimplemented_traits. len ( ) == 1 && unimplemented_traits_only {
794
- unimplemented_traits
795
- . into_iter ( )
796
- . next ( )
797
- . map ( |( _, ( trait_ref, obligation) ) | {
798
- if trait_ref. self_ty ( ) . references_error ( )
799
- || rcvr_ty. references_error ( )
800
- {
801
- // Avoid crashing.
802
- return ( None , None ) ;
803
- }
804
- let OnUnimplementedNote { message, label, .. } = self
805
- . err_ctxt ( )
806
- . on_unimplemented_note ( trait_ref, & obligation) ;
807
- ( message, label)
808
- } )
809
- . unwrap ( )
810
- } else {
811
- ( None , None )
812
- } ;
813
- let primary_message = primary_message. unwrap_or_else ( || format ! (
814
- "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
815
- but its trait bounds were not satisfied"
816
- ) ) ;
817
- err. set_primary_message ( & primary_message) ;
818
- if let Some ( label) = label {
819
- custom_span_label = true ;
820
- err. span_label ( span, label) ;
821
- }
822
- if !bound_list. is_empty ( ) {
823
- err. note ( & format ! (
824
- "the following trait bounds were not satisfied:\n {bound_list}"
825
- ) ) ;
826
- }
827
- self . suggest_derive ( & mut err, & unsatisfied_predicates) ;
828
-
829
- unsatisfied_bounds = true ;
830
- }
831
- }
832
-
833
- let label_span_not_found = |err : & mut Diagnostic | {
834
- if unsatisfied_predicates. is_empty ( ) {
835
- err. span_label ( span, format ! ( "{item_kind} not found in `{ty_str}`" ) ) ;
836
- let is_string_or_ref_str = match rcvr_ty. kind ( ) {
837
- ty:: Ref ( _, ty, _) => {
838
- ty. is_str ( )
839
- || matches ! (
840
- ty. kind( ) ,
841
- ty:: Adt ( adt, _) if Some ( adt. did( ) ) == self . tcx. lang_items( ) . string( )
842
- )
843
- }
844
- ty:: Adt ( adt, _) => Some ( adt. did ( ) ) == self . tcx . lang_items ( ) . string ( ) ,
845
- _ => false ,
846
- } ;
847
- if is_string_or_ref_str && item_name. name == sym:: iter {
848
- err. span_suggestion_verbose (
849
- item_name. span ,
850
- "because of the in-memory representation of `&str`, to obtain \
851
- an `Iterator` over each of its codepoint use method `chars`",
852
- "chars" ,
853
- Applicability :: MachineApplicable ,
854
- ) ;
855
- }
856
- if let ty:: Adt ( adt, _) = rcvr_ty. kind ( ) {
857
- let mut inherent_impls_candidate = self
858
- . tcx
859
- . inherent_impls ( adt. did ( ) )
860
- . iter ( )
861
- . copied ( )
862
- . filter ( |def_id| {
863
- if let Some ( assoc) = self . associated_value ( * def_id, item_name) {
864
- // Check for both mode is the same so we avoid suggesting
865
- // incorrect associated item.
866
- match ( mode, assoc. fn_has_self_parameter , source) {
867
- ( Mode :: MethodCall , true , SelfSource :: MethodCall ( _) ) => {
868
- // We check that the suggest type is actually
869
- // different from the received one
870
- // So we avoid suggestion method with Box<Self>
871
- // for instance
872
- self . tcx . at ( span) . type_of ( * def_id) != rcvr_ty
873
- && self . tcx . at ( span) . type_of ( * def_id) != rcvr_ty
874
- }
875
- ( Mode :: Path , false , _) => true ,
876
- _ => false ,
877
- }
878
- } else {
879
- false
880
- }
881
- } )
882
- . collect :: < Vec < _ > > ( ) ;
883
- if !inherent_impls_candidate. is_empty ( ) {
884
- inherent_impls_candidate. sort ( ) ;
885
- inherent_impls_candidate. dedup ( ) ;
886
-
887
- // number of type to shows at most.
888
- let limit = if inherent_impls_candidate. len ( ) == 5 { 5 } else { 4 } ;
889
- let type_candidates = inherent_impls_candidate
890
- . iter ( )
891
- . take ( limit)
892
- . map ( |impl_item| {
893
- format ! ( "- `{}`" , self . tcx. at( span) . type_of( * impl_item) )
894
- } )
895
- . collect :: < Vec < _ > > ( )
896
- . join ( "\n " ) ;
897
- let additional_types = if inherent_impls_candidate. len ( ) > limit {
898
- format ! (
899
- "\n and {} more types" ,
900
- inherent_impls_candidate. len( ) - limit
901
- )
902
- } else {
903
- "" . to_string ( )
904
- } ;
905
- err. note ( & format ! (
906
- "the {item_kind} was found for\n {}{}" ,
907
- type_candidates, additional_types
908
- ) ) ;
909
- }
910
- }
911
- } else {
912
- let ty_str = if ty_str. len ( ) > 50 {
913
- String :: new ( )
914
- } else {
915
- format ! ( "on `{ty_str}` " )
916
- } ;
917
- err. span_label ( span, format ! (
918
- "{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"
919
- ) ) ;
920
- }
921
- } ;
922
-
923
- // If the method name is the name of a field with a function or closure type,
924
- // give a helping note that it has to be called as `(x.f)(...)`.
925
- if let SelfSource :: MethodCall ( expr) = source {
926
- if !self . suggest_calling_field_as_fn ( span, rcvr_ty, expr, item_name, & mut err)
927
- && lev_candidate. is_none ( )
928
- && !custom_span_label
929
- {
930
- label_span_not_found ( & mut err) ;
931
- }
932
- } else if !custom_span_label {
933
- label_span_not_found ( & mut err) ;
934
- }
935
-
936
- // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
937
- // can't be called due to `typeof(expr): Clone` not holding.
938
- if unsatisfied_predicates. is_empty ( ) {
939
- self . suggest_calling_method_on_field (
940
- & mut err, source, span, rcvr_ty, item_name,
941
- ) ;
942
- }
943
-
944
- self . check_for_inner_self ( & mut err, source, rcvr_ty, item_name) ;
945
-
946
- bound_spans. sort ( ) ;
947
- bound_spans. dedup ( ) ;
948
- for ( span, msg) in bound_spans. into_iter ( ) {
949
- err. span_label ( span, & msg) ;
950
- }
951
-
952
- if rcvr_ty. is_numeric ( ) && rcvr_ty. is_fresh ( ) || restrict_type_params {
953
- } else {
954
- self . suggest_traits_to_import (
955
- & mut err,
956
- span,
957
- rcvr_ty,
958
- item_name,
959
- args. map ( |( _, args) | args. len ( ) + 1 ) ,
960
- source,
961
- out_of_scope_traits,
962
- & unsatisfied_predicates,
963
- & static_candidates,
964
- unsatisfied_bounds,
965
- ) ;
966
- }
967
-
968
- // Don't emit a suggestion if we found an actual method
969
- // that had unsatisfied trait bounds
970
- if unsatisfied_predicates. is_empty ( ) && rcvr_ty. is_enum ( ) {
971
- let adt_def = rcvr_ty. ty_adt_def ( ) . expect ( "enum is not an ADT" ) ;
972
- if let Some ( suggestion) = lev_distance:: find_best_match_for_name (
973
- & adt_def. variants ( ) . iter ( ) . map ( |s| s. name ) . collect :: < Vec < _ > > ( ) ,
974
- item_name. name ,
975
- None ,
976
- ) {
977
- err. span_suggestion (
978
- span,
979
- "there is a variant with a similar name" ,
980
- suggestion,
981
- Applicability :: MaybeIncorrect ,
982
- ) ;
983
- }
984
- }
985
-
986
- if item_name. name == sym:: as_str && rcvr_ty. peel_refs ( ) . is_str ( ) {
987
- let msg = "remove this method call" ;
988
- let mut fallback_span = true ;
989
- if let SelfSource :: MethodCall ( expr) = source {
990
- let call_expr =
991
- self . tcx . hir ( ) . expect_expr ( self . tcx . hir ( ) . get_parent_node ( expr. hir_id ) ) ;
992
- if let Some ( span) = call_expr. span . trim_start ( expr. span ) {
993
- err. span_suggestion ( span, msg, "" , Applicability :: MachineApplicable ) ;
994
- fallback_span = false ;
995
- }
996
- }
997
- if fallback_span {
998
- err. span_label ( span, msg) ;
999
- }
1000
- } else if let Some ( lev_candidate) = lev_candidate {
1001
- // Don't emit a suggestion if we found an actual method
1002
- // that had unsatisfied trait bounds
1003
- if unsatisfied_predicates. is_empty ( ) {
1004
- let def_kind = lev_candidate. kind . as_def_kind ( ) ;
1005
- // Methods are defined within the context of a struct and their first parameter is always self,
1006
- // which represents the instance of the struct the method is being called on
1007
- // Associated functions don’t take self as a parameter and
1008
- // they are not methods because they don’t have an instance of the struct to work with.
1009
- if def_kind == DefKind :: AssocFn && lev_candidate. fn_has_self_parameter {
1010
- err. span_suggestion (
1011
- span,
1012
- "there is a method with a similar name" ,
1013
- lev_candidate. name ,
1014
- Applicability :: MaybeIncorrect ,
1015
- ) ;
1016
- } else {
1017
- err. span_suggestion (
1018
- span,
1019
- & format ! (
1020
- "there is {} {} with a similar name" ,
1021
- def_kind. article( ) ,
1022
- def_kind. descr( lev_candidate. def_id) ,
1023
- ) ,
1024
- lev_candidate. name ,
1025
- Applicability :: MaybeIncorrect ,
1026
- ) ;
1027
- }
1028
- }
1029
- }
1030
-
1031
- self . check_for_deref_method ( & mut err, source, rcvr_ty, item_name) ;
1032
-
1033
- return Some ( err) ;
1034
135
}
1035
136
1036
137
MethodError :: Ambiguity ( mut sources) => {
@@ -1042,7 +143,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1042
143
) ;
1043
144
err. span_label ( item_name. span , format ! ( "multiple `{}` found" , item_name) ) ;
1044
145
1045
- report_candidates ( span, & mut err, & mut sources, Some ( sugg_span) ) ;
146
+ self . note_candidates_on_method_error (
147
+ rcvr_ty,
148
+ item_name,
149
+ args,
150
+ span,
151
+ & mut err,
152
+ & mut sources,
153
+ Some ( sugg_span) ,
154
+ ) ;
1046
155
err. emit ( ) ;
1047
156
}
1048
157
@@ -1099,6 +208,902 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1099
208
None
1100
209
}
1101
210
211
+ pub fn report_no_match_method_error (
212
+ & self ,
213
+ mut span : Span ,
214
+ rcvr_ty : Ty < ' tcx > ,
215
+ item_name : Ident ,
216
+ source : SelfSource < ' tcx > ,
217
+ args : Option < ( & ' tcx hir:: Expr < ' tcx > , & ' tcx [ hir:: Expr < ' tcx > ] ) > ,
218
+ sugg_span : Span ,
219
+ no_match_data : & mut NoMatchData < ' tcx > ,
220
+ ) -> Option < DiagnosticBuilder < ' _ , ErrorGuaranteed > > {
221
+ let mode = no_match_data. mode ;
222
+ let tcx = self . tcx ;
223
+ let rcvr_ty = self . resolve_vars_if_possible ( rcvr_ty) ;
224
+ let ty_str = with_forced_trimmed_paths ! ( self . ty_to_string( rcvr_ty) ) ;
225
+ let is_method = mode == Mode :: MethodCall ;
226
+ let unsatisfied_predicates = & no_match_data. unsatisfied_predicates ;
227
+ let lev_candidate = no_match_data. lev_candidate ;
228
+ let item_kind = if is_method {
229
+ "method"
230
+ } else if rcvr_ty. is_enum ( ) {
231
+ "variant or associated item"
232
+ } else {
233
+ match ( item_name. as_str ( ) . chars ( ) . next ( ) , rcvr_ty. is_fresh_ty ( ) ) {
234
+ ( Some ( name) , false ) if name. is_lowercase ( ) => "function or associated item" ,
235
+ ( Some ( _) , false ) => "associated item" ,
236
+ ( Some ( _) , true ) | ( None , false ) => "variant or associated item" ,
237
+ ( None , true ) => "variant" ,
238
+ }
239
+ } ;
240
+
241
+ if self . suggest_wrapping_range_with_parens ( tcx, rcvr_ty, source, span, item_name, & ty_str)
242
+ || self . suggest_constraining_numerical_ty (
243
+ tcx, rcvr_ty, source, span, item_kind, item_name, & ty_str,
244
+ )
245
+ {
246
+ return None ;
247
+ }
248
+ span = item_name. span ;
249
+
250
+ // Don't show generic arguments when the method can't be found in any implementation (#81576).
251
+ let mut ty_str_reported = ty_str. clone ( ) ;
252
+ if let ty:: Adt ( _, generics) = rcvr_ty. kind ( ) {
253
+ if generics. len ( ) > 0 {
254
+ let mut autoderef = self . autoderef ( span, rcvr_ty) ;
255
+ let candidate_found = autoderef. any ( |( ty, _) | {
256
+ if let ty:: Adt ( adt_def, _) = ty. kind ( ) {
257
+ self . tcx
258
+ . inherent_impls ( adt_def. did ( ) )
259
+ . iter ( )
260
+ . filter_map ( |def_id| self . associated_value ( * def_id, item_name) )
261
+ . count ( )
262
+ >= 1
263
+ } else {
264
+ false
265
+ }
266
+ } ) ;
267
+ let has_deref = autoderef. step_count ( ) > 0 ;
268
+ if !candidate_found && !has_deref && unsatisfied_predicates. is_empty ( ) {
269
+ if let Some ( ( path_string, _) ) = ty_str. split_once ( '<' ) {
270
+ ty_str_reported = path_string. to_string ( ) ;
271
+ }
272
+ }
273
+ }
274
+ }
275
+
276
+ let mut err = struct_span_err ! (
277
+ tcx. sess,
278
+ span,
279
+ E0599 ,
280
+ "no {} named `{}` found for {} `{}` in the current scope" ,
281
+ item_kind,
282
+ item_name,
283
+ rcvr_ty. prefix_string( self . tcx) ,
284
+ ty_str_reported,
285
+ ) ;
286
+ if rcvr_ty. references_error ( ) {
287
+ err. downgrade_to_delayed_bug ( ) ;
288
+ }
289
+
290
+ if let Mode :: MethodCall = mode && let SelfSource :: MethodCall ( cal) = source {
291
+ self . suggest_await_before_method (
292
+ & mut err, item_name, rcvr_ty, cal, span,
293
+ ) ;
294
+ }
295
+ if let Some ( span) =
296
+ tcx. resolutions ( ( ) ) . confused_type_with_std_module . get ( & span. with_parent ( None ) )
297
+ {
298
+ err. span_suggestion (
299
+ span. shrink_to_lo ( ) ,
300
+ "you are looking for the module in `std`, not the primitive type" ,
301
+ "std::" ,
302
+ Applicability :: MachineApplicable ,
303
+ ) ;
304
+ }
305
+ if let ty:: RawPtr ( _) = & rcvr_ty. kind ( ) {
306
+ err. note (
307
+ "try using `<*const T>::as_ref()` to get a reference to the \
308
+ type behind the pointer: https://doc.rust-lang.org/std/\
309
+ primitive.pointer.html#method.as_ref",
310
+ ) ;
311
+ err. note (
312
+ "using `<*const T>::as_ref()` on a pointer which is unaligned or points \
313
+ to invalid or uninitialized memory is undefined behavior",
314
+ ) ;
315
+ }
316
+
317
+ let ty_span = match rcvr_ty. kind ( ) {
318
+ ty:: Param ( param_type) => {
319
+ Some ( param_type. span_from_generics ( self . tcx , self . body_id . owner . to_def_id ( ) ) )
320
+ }
321
+ ty:: Adt ( def, _) if def. did ( ) . is_local ( ) => Some ( tcx. def_span ( def. did ( ) ) ) ,
322
+ _ => None ,
323
+ } ;
324
+ if let Some ( span) = ty_span {
325
+ err. span_label (
326
+ span,
327
+ format ! (
328
+ "{item_kind} `{item_name}` not found for this {}" ,
329
+ rcvr_ty. prefix_string( self . tcx)
330
+ ) ,
331
+ ) ;
332
+ }
333
+
334
+ if let SelfSource :: MethodCall ( rcvr_expr) = source {
335
+ self . suggest_fn_call ( & mut err, rcvr_expr, rcvr_ty, |output_ty| {
336
+ let call_expr =
337
+ self . tcx . hir ( ) . expect_expr ( self . tcx . hir ( ) . get_parent_node ( rcvr_expr. hir_id ) ) ;
338
+ let probe =
339
+ self . lookup_probe ( item_name, output_ty, call_expr, ProbeScope :: AllTraits ) ;
340
+ probe. is_ok ( )
341
+ } ) ;
342
+ }
343
+
344
+ let mut custom_span_label = false ;
345
+
346
+ let static_candidates = & mut no_match_data. static_candidates ;
347
+ if !static_candidates. is_empty ( ) {
348
+ err. note (
349
+ "found the following associated functions; to be used as methods, \
350
+ functions must have a `self` parameter",
351
+ ) ;
352
+ err. span_label ( span, "this is an associated function, not a method" ) ;
353
+ custom_span_label = true ;
354
+ }
355
+ if static_candidates. len ( ) == 1 {
356
+ self . suggest_associated_call_syntax (
357
+ & mut err,
358
+ & static_candidates,
359
+ rcvr_ty,
360
+ source,
361
+ item_name,
362
+ args,
363
+ sugg_span,
364
+ ) ;
365
+
366
+ self . note_candidates_on_method_error (
367
+ rcvr_ty,
368
+ item_name,
369
+ args,
370
+ span,
371
+ & mut err,
372
+ static_candidates,
373
+ None ,
374
+ ) ;
375
+ } else if static_candidates. len ( ) > 1 {
376
+ self . note_candidates_on_method_error (
377
+ rcvr_ty,
378
+ item_name,
379
+ args,
380
+ span,
381
+ & mut err,
382
+ static_candidates,
383
+ Some ( sugg_span) ,
384
+ ) ;
385
+ }
386
+
387
+ let mut bound_spans = vec ! [ ] ;
388
+ let mut restrict_type_params = false ;
389
+ let mut unsatisfied_bounds = false ;
390
+ if item_name. name == sym:: count && self . is_slice_ty ( rcvr_ty, span) {
391
+ let msg = "consider using `len` instead" ;
392
+ if let SelfSource :: MethodCall ( _expr) = source {
393
+ err. span_suggestion_short ( span, msg, "len" , Applicability :: MachineApplicable ) ;
394
+ } else {
395
+ err. span_label ( span, msg) ;
396
+ }
397
+ if let Some ( iterator_trait) = self . tcx . get_diagnostic_item ( sym:: Iterator ) {
398
+ let iterator_trait = self . tcx . def_path_str ( iterator_trait) ;
399
+ err. note ( & format ! (
400
+ "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"
401
+ ) ) ;
402
+ }
403
+ } else if !unsatisfied_predicates. is_empty ( ) {
404
+ let mut type_params = FxHashMap :: default ( ) ;
405
+
406
+ // Pick out the list of unimplemented traits on the receiver.
407
+ // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
408
+ let mut unimplemented_traits = FxHashMap :: default ( ) ;
409
+ let mut unimplemented_traits_only = true ;
410
+ for ( predicate, _parent_pred, cause) in unsatisfied_predicates {
411
+ if let ( ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( p) ) , Some ( cause) ) =
412
+ ( predicate. kind ( ) . skip_binder ( ) , cause. as_ref ( ) )
413
+ {
414
+ if p. trait_ref . self_ty ( ) != rcvr_ty {
415
+ // This is necessary, not just to keep the errors clean, but also
416
+ // because our derived obligations can wind up with a trait ref that
417
+ // requires a different param_env to be correctly compared.
418
+ continue ;
419
+ }
420
+ unimplemented_traits. entry ( p. trait_ref . def_id ) . or_insert ( (
421
+ predicate. kind ( ) . rebind ( p. trait_ref ) ,
422
+ Obligation {
423
+ cause : cause. clone ( ) ,
424
+ param_env : self . param_env ,
425
+ predicate : * predicate,
426
+ recursion_depth : 0 ,
427
+ } ,
428
+ ) ) ;
429
+ }
430
+ }
431
+
432
+ // Make sure that, if any traits other than the found ones were involved,
433
+ // we don't don't report an unimplemented trait.
434
+ // We don't want to say that `iter::Cloned` is not an iterator, just
435
+ // because of some non-Clone item being iterated over.
436
+ for ( predicate, _parent_pred, _cause) in unsatisfied_predicates {
437
+ match predicate. kind ( ) . skip_binder ( ) {
438
+ ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( p) )
439
+ if unimplemented_traits. contains_key ( & p. trait_ref . def_id ) => { }
440
+ _ => {
441
+ unimplemented_traits_only = false ;
442
+ break ;
443
+ }
444
+ }
445
+ }
446
+
447
+ let mut collect_type_param_suggestions =
448
+ |self_ty : Ty < ' tcx > , parent_pred : ty:: Predicate < ' tcx > , obligation : & str | {
449
+ // We don't care about regions here, so it's fine to skip the binder here.
450
+ if let ( ty:: Param ( _) , ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( p) ) ) =
451
+ ( self_ty. kind ( ) , parent_pred. kind ( ) . skip_binder ( ) )
452
+ {
453
+ let hir = self . tcx . hir ( ) ;
454
+ let node = match p. trait_ref . self_ty ( ) . kind ( ) {
455
+ ty:: Param ( _) => {
456
+ // Account for `fn` items like in `issue-35677.rs` to
457
+ // suggest restricting its type params.
458
+ let parent_body =
459
+ hir. body_owner ( hir:: BodyId { hir_id : self . body_id } ) ;
460
+ Some ( hir. get ( parent_body) )
461
+ }
462
+ ty:: Adt ( def, _) => {
463
+ def. did ( ) . as_local ( ) . map ( |def_id| hir. get_by_def_id ( def_id) )
464
+ }
465
+ _ => None ,
466
+ } ;
467
+ if let Some ( hir:: Node :: Item ( hir:: Item { kind, .. } ) ) = node {
468
+ if let Some ( g) = kind. generics ( ) {
469
+ let key = (
470
+ g. tail_span_for_predicate_suggestion ( ) ,
471
+ g. add_where_or_trailing_comma ( ) ,
472
+ ) ;
473
+ type_params
474
+ . entry ( key)
475
+ . or_insert_with ( FxHashSet :: default)
476
+ . insert ( obligation. to_owned ( ) ) ;
477
+ }
478
+ }
479
+ }
480
+ } ;
481
+ let mut bound_span_label = |self_ty : Ty < ' _ > , obligation : & str , quiet : & str | {
482
+ let msg = format ! (
483
+ "doesn't satisfy `{}`" ,
484
+ if obligation. len( ) > 50 { quiet } else { obligation }
485
+ ) ;
486
+ match & self_ty. kind ( ) {
487
+ // Point at the type that couldn't satisfy the bound.
488
+ ty:: Adt ( def, _) => bound_spans. push ( ( self . tcx . def_span ( def. did ( ) ) , msg) ) ,
489
+ // Point at the trait object that couldn't satisfy the bound.
490
+ ty:: Dynamic ( preds, _, _) => {
491
+ for pred in preds. iter ( ) {
492
+ match pred. skip_binder ( ) {
493
+ ty:: ExistentialPredicate :: Trait ( tr) => {
494
+ bound_spans. push ( ( self . tcx . def_span ( tr. def_id ) , msg. clone ( ) ) )
495
+ }
496
+ ty:: ExistentialPredicate :: Projection ( _)
497
+ | ty:: ExistentialPredicate :: AutoTrait ( _) => { }
498
+ }
499
+ }
500
+ }
501
+ // Point at the closure that couldn't satisfy the bound.
502
+ ty:: Closure ( def_id, _) => bound_spans
503
+ . push ( ( tcx. def_span ( * def_id) , format ! ( "doesn't satisfy `{}`" , quiet) ) ) ,
504
+ _ => { }
505
+ }
506
+ } ;
507
+ let mut format_pred = |pred : ty:: Predicate < ' tcx > | {
508
+ let bound_predicate = pred. kind ( ) ;
509
+ match bound_predicate. skip_binder ( ) {
510
+ ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( pred) ) => {
511
+ let pred = bound_predicate. rebind ( pred) ;
512
+ // `<Foo as Iterator>::Item = String`.
513
+ let projection_ty = pred. skip_binder ( ) . projection_ty ;
514
+
515
+ let substs_with_infer_self = tcx. mk_substs (
516
+ iter:: once ( tcx. mk_ty_var ( ty:: TyVid :: from_u32 ( 0 ) ) . into ( ) )
517
+ . chain ( projection_ty. substs . iter ( ) . skip ( 1 ) ) ,
518
+ ) ;
519
+
520
+ let quiet_projection_ty =
521
+ tcx. mk_alias_ty ( projection_ty. def_id , substs_with_infer_self) ;
522
+
523
+ let term = pred. skip_binder ( ) . term ;
524
+
525
+ let obligation = format ! ( "{} = {}" , projection_ty, term) ;
526
+ let quiet = with_forced_trimmed_paths ! ( format!(
527
+ "{} = {}" ,
528
+ quiet_projection_ty, term
529
+ ) ) ;
530
+
531
+ bound_span_label ( projection_ty. self_ty ( ) , & obligation, & quiet) ;
532
+ Some ( ( obligation, projection_ty. self_ty ( ) ) )
533
+ }
534
+ ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( poly_trait_ref) ) => {
535
+ let p = poly_trait_ref. trait_ref ;
536
+ let self_ty = p. self_ty ( ) ;
537
+ let path = p. print_only_trait_path ( ) ;
538
+ let obligation = format ! ( "{}: {}" , self_ty, path) ;
539
+ let quiet = with_forced_trimmed_paths ! ( format!( "_: {}" , path) ) ;
540
+ bound_span_label ( self_ty, & obligation, & quiet) ;
541
+ Some ( ( obligation, self_ty) )
542
+ }
543
+ _ => None ,
544
+ }
545
+ } ;
546
+
547
+ // Find all the requirements that come from a local `impl` block.
548
+ let mut skip_list: FxHashSet < _ > = Default :: default ( ) ;
549
+ let mut spanned_predicates: FxHashMap < MultiSpan , _ > = Default :: default ( ) ;
550
+ for ( data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates
551
+ . iter ( )
552
+ . filter_map ( |( p, parent, c) | c. as_ref ( ) . map ( |c| ( p, parent, c) ) )
553
+ . filter_map ( |( p, parent, c) | match c. code ( ) {
554
+ ObligationCauseCode :: ImplDerivedObligation ( data) => {
555
+ Some ( ( & data. derived , p, parent, data. impl_def_id , data) )
556
+ }
557
+ _ => None ,
558
+ } )
559
+ {
560
+ let parent_trait_ref = data. parent_trait_pred ;
561
+ let path = parent_trait_ref. print_modifiers_and_trait_path ( ) ;
562
+ let tr_self_ty = parent_trait_ref. skip_binder ( ) . self_ty ( ) ;
563
+ let unsatisfied_msg = "unsatisfied trait bound introduced here" ;
564
+ let derive_msg = "unsatisfied trait bound introduced in this `derive` macro" ;
565
+ match self . tcx . hir ( ) . get_if_local ( impl_def_id) {
566
+ // Unmet obligation comes from a `derive` macro, point at it once to
567
+ // avoid multiple span labels pointing at the same place.
568
+ Some ( Node :: Item ( hir:: Item {
569
+ kind : hir:: ItemKind :: Impl ( hir:: Impl { of_trait, self_ty, .. } ) ,
570
+ ..
571
+ } ) ) if matches ! (
572
+ self_ty. span. ctxt( ) . outer_expn_data( ) . kind,
573
+ ExpnKind :: Macro ( MacroKind :: Derive , _)
574
+ ) || matches ! (
575
+ of_trait. as_ref( ) . map( |t| t. path. span. ctxt( ) . outer_expn_data( ) . kind) ,
576
+ Some ( ExpnKind :: Macro ( MacroKind :: Derive , _) )
577
+ ) =>
578
+ {
579
+ let span = self_ty. span . ctxt ( ) . outer_expn_data ( ) . call_site ;
580
+ let mut spans: MultiSpan = span. into ( ) ;
581
+ spans. push_span_label ( span, derive_msg) ;
582
+ let entry = spanned_predicates. entry ( spans) ;
583
+ entry. or_insert_with ( || ( path, tr_self_ty, Vec :: new ( ) ) ) . 2 . push ( p) ;
584
+ }
585
+
586
+ // Unmet obligation coming from an `impl`.
587
+ Some ( Node :: Item ( hir:: Item {
588
+ kind : hir:: ItemKind :: Impl ( hir:: Impl { of_trait, self_ty, generics, .. } ) ,
589
+ span : item_span,
590
+ ..
591
+ } ) ) => {
592
+ let sized_pred =
593
+ unsatisfied_predicates. iter ( ) . any ( |( pred, _, _) | {
594
+ match pred. kind ( ) . skip_binder ( ) {
595
+ ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( pred) ) => {
596
+ Some ( pred. def_id ( ) ) == self . tcx . lang_items ( ) . sized_trait ( )
597
+ && pred. polarity == ty:: ImplPolarity :: Positive
598
+ }
599
+ _ => false ,
600
+ }
601
+ } ) ;
602
+ for param in generics. params {
603
+ if param. span == cause. span && sized_pred {
604
+ let ( sp, sugg) = match param. colon_span {
605
+ Some ( sp) => ( sp. shrink_to_hi ( ) , " ?Sized +" ) ,
606
+ None => ( param. span . shrink_to_hi ( ) , ": ?Sized" ) ,
607
+ } ;
608
+ err. span_suggestion_verbose (
609
+ sp,
610
+ "consider relaxing the type parameter's implicit \
611
+ `Sized` bound",
612
+ sugg,
613
+ Applicability :: MachineApplicable ,
614
+ ) ;
615
+ }
616
+ }
617
+ if let Some ( pred) = parent_p {
618
+ // Done to add the "doesn't satisfy" `span_label`.
619
+ let _ = format_pred ( * pred) ;
620
+ }
621
+ skip_list. insert ( p) ;
622
+ let mut spans = if cause. span != * item_span {
623
+ let mut spans: MultiSpan = cause. span . into ( ) ;
624
+ spans. push_span_label ( cause. span , unsatisfied_msg) ;
625
+ spans
626
+ } else {
627
+ let mut spans = Vec :: with_capacity ( 2 ) ;
628
+ if let Some ( trait_ref) = of_trait {
629
+ spans. push ( trait_ref. path . span ) ;
630
+ }
631
+ spans. push ( self_ty. span ) ;
632
+ spans. into ( )
633
+ } ;
634
+ if let Some ( trait_ref) = of_trait {
635
+ spans. push_span_label ( trait_ref. path . span , "" ) ;
636
+ }
637
+ spans. push_span_label ( self_ty. span , "" ) ;
638
+
639
+ let entry = spanned_predicates. entry ( spans) ;
640
+ entry. or_insert_with ( || ( path, tr_self_ty, Vec :: new ( ) ) ) . 2 . push ( p) ;
641
+ }
642
+ Some ( Node :: Item ( hir:: Item {
643
+ kind : hir:: ItemKind :: Trait ( rustc_ast:: ast:: IsAuto :: Yes , ..) ,
644
+ span : item_span,
645
+ ..
646
+ } ) ) => {
647
+ tcx. sess . delay_span_bug (
648
+ * item_span,
649
+ "auto trait is invoked with no method error, but no error reported?" ,
650
+ ) ;
651
+ }
652
+ Some ( _) => unreachable ! ( ) ,
653
+ None => ( ) ,
654
+ }
655
+ }
656
+ let mut spanned_predicates: Vec < _ > = spanned_predicates. into_iter ( ) . collect ( ) ;
657
+ spanned_predicates. sort_by_key ( |( span, ( _, _, _) ) | span. primary_span ( ) ) ;
658
+ for ( span, ( _path, _self_ty, preds) ) in spanned_predicates {
659
+ let mut preds: Vec < _ > = preds
660
+ . into_iter ( )
661
+ . filter_map ( |pred| format_pred ( * pred) )
662
+ . map ( |( p, _) | format ! ( "`{}`" , p) )
663
+ . collect ( ) ;
664
+ preds. sort ( ) ;
665
+ preds. dedup ( ) ;
666
+ let msg = if let [ pred] = & preds[ ..] {
667
+ format ! ( "trait bound {} was not satisfied" , pred)
668
+ } else {
669
+ format ! ( "the following trait bounds were not satisfied:\n {}" , preds. join( "\n " ) , )
670
+ } ;
671
+ err. span_note ( span, & msg) ;
672
+ unsatisfied_bounds = true ;
673
+ }
674
+
675
+ // The requirements that didn't have an `impl` span to show.
676
+ let mut bound_list = unsatisfied_predicates
677
+ . iter ( )
678
+ . filter_map ( |( pred, parent_pred, _cause) | {
679
+ format_pred ( * pred) . map ( |( p, self_ty) | {
680
+ collect_type_param_suggestions ( self_ty, * pred, & p) ;
681
+ (
682
+ match parent_pred {
683
+ None => format ! ( "`{}`" , & p) ,
684
+ Some ( parent_pred) => match format_pred ( * parent_pred) {
685
+ None => format ! ( "`{}`" , & p) ,
686
+ Some ( ( parent_p, _) ) => {
687
+ collect_type_param_suggestions ( self_ty, * parent_pred, & p) ;
688
+ format ! ( "`{}`\n which is required by `{}`" , p, parent_p)
689
+ }
690
+ } ,
691
+ } ,
692
+ * pred,
693
+ )
694
+ } )
695
+ } )
696
+ . filter ( |( _, pred) | !skip_list. contains ( & pred) )
697
+ . map ( |( t, _) | t)
698
+ . enumerate ( )
699
+ . collect :: < Vec < ( usize , String ) > > ( ) ;
700
+
701
+ for ( ( span, add_where_or_comma) , obligations) in type_params. into_iter ( ) {
702
+ restrict_type_params = true ;
703
+ // #74886: Sort here so that the output is always the same.
704
+ let mut obligations = obligations. into_iter ( ) . collect :: < Vec < _ > > ( ) ;
705
+ obligations. sort ( ) ;
706
+ err. span_suggestion_verbose (
707
+ span,
708
+ & format ! (
709
+ "consider restricting the type parameter{s} to satisfy the \
710
+ trait bound{s}",
711
+ s = pluralize!( obligations. len( ) )
712
+ ) ,
713
+ format ! ( "{} {}" , add_where_or_comma, obligations. join( ", " ) ) ,
714
+ Applicability :: MaybeIncorrect ,
715
+ ) ;
716
+ }
717
+
718
+ bound_list. sort_by ( |( _, a) , ( _, b) | a. cmp ( b) ) ; // Sort alphabetically.
719
+ bound_list. dedup_by ( |( _, a) , ( _, b) | a == b) ; // #35677
720
+ bound_list. sort_by_key ( |( pos, _) | * pos) ; // Keep the original predicate order.
721
+
722
+ if !bound_list. is_empty ( ) || !skip_list. is_empty ( ) {
723
+ let bound_list =
724
+ bound_list. into_iter ( ) . map ( |( _, path) | path) . collect :: < Vec < _ > > ( ) . join ( "\n " ) ;
725
+ let actual_prefix = rcvr_ty. prefix_string ( self . tcx ) ;
726
+ info ! ( "unimplemented_traits.len() == {}" , unimplemented_traits. len( ) ) ;
727
+ let ( primary_message, label) = if unimplemented_traits. len ( ) == 1
728
+ && unimplemented_traits_only
729
+ {
730
+ unimplemented_traits
731
+ . into_iter ( )
732
+ . next ( )
733
+ . map ( |( _, ( trait_ref, obligation) ) | {
734
+ if trait_ref. self_ty ( ) . references_error ( ) || rcvr_ty. references_error ( )
735
+ {
736
+ // Avoid crashing.
737
+ return ( None , None ) ;
738
+ }
739
+ let OnUnimplementedNote { message, label, .. } =
740
+ self . err_ctxt ( ) . on_unimplemented_note ( trait_ref, & obligation) ;
741
+ ( message, label)
742
+ } )
743
+ . unwrap ( )
744
+ } else {
745
+ ( None , None )
746
+ } ;
747
+ let primary_message = primary_message. unwrap_or_else ( || {
748
+ format ! (
749
+ "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
750
+ but its trait bounds were not satisfied"
751
+ )
752
+ } ) ;
753
+ err. set_primary_message ( & primary_message) ;
754
+ if let Some ( label) = label {
755
+ custom_span_label = true ;
756
+ err. span_label ( span, label) ;
757
+ }
758
+ if !bound_list. is_empty ( ) {
759
+ err. note ( & format ! (
760
+ "the following trait bounds were not satisfied:\n {bound_list}"
761
+ ) ) ;
762
+ }
763
+ self . suggest_derive ( & mut err, & unsatisfied_predicates) ;
764
+
765
+ unsatisfied_bounds = true ;
766
+ }
767
+ }
768
+
769
+ let label_span_not_found = |err : & mut Diagnostic | {
770
+ if unsatisfied_predicates. is_empty ( ) {
771
+ err. span_label ( span, format ! ( "{item_kind} not found in `{ty_str}`" ) ) ;
772
+ let is_string_or_ref_str = match rcvr_ty. kind ( ) {
773
+ ty:: Ref ( _, ty, _) => {
774
+ ty. is_str ( )
775
+ || matches ! (
776
+ ty. kind( ) ,
777
+ ty:: Adt ( adt, _) if Some ( adt. did( ) ) == self . tcx. lang_items( ) . string( )
778
+ )
779
+ }
780
+ ty:: Adt ( adt, _) => Some ( adt. did ( ) ) == self . tcx . lang_items ( ) . string ( ) ,
781
+ _ => false ,
782
+ } ;
783
+ if is_string_or_ref_str && item_name. name == sym:: iter {
784
+ err. span_suggestion_verbose (
785
+ item_name. span ,
786
+ "because of the in-memory representation of `&str`, to obtain \
787
+ an `Iterator` over each of its codepoint use method `chars`",
788
+ "chars" ,
789
+ Applicability :: MachineApplicable ,
790
+ ) ;
791
+ }
792
+ if let ty:: Adt ( adt, _) = rcvr_ty. kind ( ) {
793
+ let mut inherent_impls_candidate = self
794
+ . tcx
795
+ . inherent_impls ( adt. did ( ) )
796
+ . iter ( )
797
+ . copied ( )
798
+ . filter ( |def_id| {
799
+ if let Some ( assoc) = self . associated_value ( * def_id, item_name) {
800
+ // Check for both mode is the same so we avoid suggesting
801
+ // incorrect associated item.
802
+ match ( mode, assoc. fn_has_self_parameter , source) {
803
+ ( Mode :: MethodCall , true , SelfSource :: MethodCall ( _) ) => {
804
+ // We check that the suggest type is actually
805
+ // different from the received one
806
+ // So we avoid suggestion method with Box<Self>
807
+ // for instance
808
+ self . tcx . at ( span) . type_of ( * def_id) != rcvr_ty
809
+ && self . tcx . at ( span) . type_of ( * def_id) != rcvr_ty
810
+ }
811
+ ( Mode :: Path , false , _) => true ,
812
+ _ => false ,
813
+ }
814
+ } else {
815
+ false
816
+ }
817
+ } )
818
+ . collect :: < Vec < _ > > ( ) ;
819
+ if !inherent_impls_candidate. is_empty ( ) {
820
+ inherent_impls_candidate. sort ( ) ;
821
+ inherent_impls_candidate. dedup ( ) ;
822
+
823
+ // number of type to shows at most.
824
+ let limit = if inherent_impls_candidate. len ( ) == 5 { 5 } else { 4 } ;
825
+ let type_candidates = inherent_impls_candidate
826
+ . iter ( )
827
+ . take ( limit)
828
+ . map ( |impl_item| {
829
+ format ! ( "- `{}`" , self . tcx. at( span) . type_of( * impl_item) )
830
+ } )
831
+ . collect :: < Vec < _ > > ( )
832
+ . join ( "\n " ) ;
833
+ let additional_types = if inherent_impls_candidate. len ( ) > limit {
834
+ format ! ( "\n and {} more types" , inherent_impls_candidate. len( ) - limit)
835
+ } else {
836
+ "" . to_string ( )
837
+ } ;
838
+ err. note ( & format ! (
839
+ "the {item_kind} was found for\n {}{}" ,
840
+ type_candidates, additional_types
841
+ ) ) ;
842
+ }
843
+ }
844
+ } else {
845
+ let ty_str =
846
+ if ty_str. len ( ) > 50 { String :: new ( ) } else { format ! ( "on `{ty_str}` " ) } ;
847
+ err. span_label (
848
+ span,
849
+ format ! ( "{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds" ) ,
850
+ ) ;
851
+ }
852
+ } ;
853
+
854
+ // If the method name is the name of a field with a function or closure type,
855
+ // give a helping note that it has to be called as `(x.f)(...)`.
856
+ if let SelfSource :: MethodCall ( expr) = source {
857
+ if !self . suggest_calling_field_as_fn ( span, rcvr_ty, expr, item_name, & mut err)
858
+ && lev_candidate. is_none ( )
859
+ && !custom_span_label
860
+ {
861
+ label_span_not_found ( & mut err) ;
862
+ }
863
+ } else if !custom_span_label {
864
+ label_span_not_found ( & mut err) ;
865
+ }
866
+
867
+ // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
868
+ // can't be called due to `typeof(expr): Clone` not holding.
869
+ if unsatisfied_predicates. is_empty ( ) {
870
+ self . suggest_calling_method_on_field ( & mut err, source, span, rcvr_ty, item_name) ;
871
+ }
872
+
873
+ self . check_for_inner_self ( & mut err, source, rcvr_ty, item_name) ;
874
+
875
+ bound_spans. sort ( ) ;
876
+ bound_spans. dedup ( ) ;
877
+ for ( span, msg) in bound_spans. into_iter ( ) {
878
+ err. span_label ( span, & msg) ;
879
+ }
880
+
881
+ if rcvr_ty. is_numeric ( ) && rcvr_ty. is_fresh ( ) || restrict_type_params {
882
+ } else {
883
+ self . suggest_traits_to_import (
884
+ & mut err,
885
+ span,
886
+ rcvr_ty,
887
+ item_name,
888
+ args. map ( |( _, args) | args. len ( ) + 1 ) ,
889
+ source,
890
+ no_match_data. out_of_scope_traits . clone ( ) ,
891
+ & unsatisfied_predicates,
892
+ & static_candidates,
893
+ unsatisfied_bounds,
894
+ ) ;
895
+ }
896
+
897
+ // Don't emit a suggestion if we found an actual method
898
+ // that had unsatisfied trait bounds
899
+ if unsatisfied_predicates. is_empty ( ) && rcvr_ty. is_enum ( ) {
900
+ let adt_def = rcvr_ty. ty_adt_def ( ) . expect ( "enum is not an ADT" ) ;
901
+ if let Some ( suggestion) = lev_distance:: find_best_match_for_name (
902
+ & adt_def. variants ( ) . iter ( ) . map ( |s| s. name ) . collect :: < Vec < _ > > ( ) ,
903
+ item_name. name ,
904
+ None ,
905
+ ) {
906
+ err. span_suggestion (
907
+ span,
908
+ "there is a variant with a similar name" ,
909
+ suggestion,
910
+ Applicability :: MaybeIncorrect ,
911
+ ) ;
912
+ }
913
+ }
914
+
915
+ if item_name. name == sym:: as_str && rcvr_ty. peel_refs ( ) . is_str ( ) {
916
+ let msg = "remove this method call" ;
917
+ let mut fallback_span = true ;
918
+ if let SelfSource :: MethodCall ( expr) = source {
919
+ let call_expr =
920
+ self . tcx . hir ( ) . expect_expr ( self . tcx . hir ( ) . get_parent_node ( expr. hir_id ) ) ;
921
+ if let Some ( span) = call_expr. span . trim_start ( expr. span ) {
922
+ err. span_suggestion ( span, msg, "" , Applicability :: MachineApplicable ) ;
923
+ fallback_span = false ;
924
+ }
925
+ }
926
+ if fallback_span {
927
+ err. span_label ( span, msg) ;
928
+ }
929
+ } else if let Some ( lev_candidate) = lev_candidate {
930
+ // Don't emit a suggestion if we found an actual method
931
+ // that had unsatisfied trait bounds
932
+ if unsatisfied_predicates. is_empty ( ) {
933
+ let def_kind = lev_candidate. kind . as_def_kind ( ) ;
934
+ // Methods are defined within the context of a struct and their first parameter is always self,
935
+ // which represents the instance of the struct the method is being called on
936
+ // Associated functions don’t take self as a parameter and
937
+ // they are not methods because they don’t have an instance of the struct to work with.
938
+ if def_kind == DefKind :: AssocFn && lev_candidate. fn_has_self_parameter {
939
+ err. span_suggestion (
940
+ span,
941
+ "there is a method with a similar name" ,
942
+ lev_candidate. name ,
943
+ Applicability :: MaybeIncorrect ,
944
+ ) ;
945
+ } else {
946
+ err. span_suggestion (
947
+ span,
948
+ & format ! (
949
+ "there is {} {} with a similar name" ,
950
+ def_kind. article( ) ,
951
+ def_kind. descr( lev_candidate. def_id) ,
952
+ ) ,
953
+ lev_candidate. name ,
954
+ Applicability :: MaybeIncorrect ,
955
+ ) ;
956
+ }
957
+ }
958
+ }
959
+
960
+ self . check_for_deref_method ( & mut err, source, rcvr_ty, item_name) ;
961
+ return Some ( err) ;
962
+ }
963
+
964
+ fn note_candidates_on_method_error (
965
+ & self ,
966
+ rcvr_ty : Ty < ' tcx > ,
967
+ item_name : Ident ,
968
+ args : Option < ( & ' tcx hir:: Expr < ' tcx > , & ' tcx [ hir:: Expr < ' tcx > ] ) > ,
969
+ span : Span ,
970
+ err : & mut Diagnostic ,
971
+ sources : & mut Vec < CandidateSource > ,
972
+ sugg_span : Option < Span > ,
973
+ ) {
974
+ sources. sort ( ) ;
975
+ sources. dedup ( ) ;
976
+ // Dynamic limit to avoid hiding just one candidate, which is silly.
977
+ let limit = if sources. len ( ) == 5 { 5 } else { 4 } ;
978
+
979
+ for ( idx, source) in sources. iter ( ) . take ( limit) . enumerate ( ) {
980
+ match * source {
981
+ CandidateSource :: Impl ( impl_did) => {
982
+ // Provide the best span we can. Use the item, if local to crate, else
983
+ // the impl, if local to crate (item may be defaulted), else nothing.
984
+ let Some ( item) = self . associated_value ( impl_did, item_name) . or_else ( || {
985
+ let impl_trait_ref = self . tcx . impl_trait_ref ( impl_did) ?;
986
+ self . associated_value ( impl_trait_ref. def_id , item_name)
987
+ } ) else {
988
+ continue ;
989
+ } ;
990
+
991
+ let note_span = if item. def_id . is_local ( ) {
992
+ Some ( self . tcx . def_span ( item. def_id ) )
993
+ } else if impl_did. is_local ( ) {
994
+ Some ( self . tcx . def_span ( impl_did) )
995
+ } else {
996
+ None
997
+ } ;
998
+
999
+ let impl_ty = self . tcx . at ( span) . type_of ( impl_did) ;
1000
+
1001
+ let insertion = match self . tcx . impl_trait_ref ( impl_did) {
1002
+ None => String :: new ( ) ,
1003
+ Some ( trait_ref) => {
1004
+ format ! ( " of the trait `{}`" , self . tcx. def_path_str( trait_ref. def_id) )
1005
+ }
1006
+ } ;
1007
+
1008
+ let ( note_str, idx) = if sources. len ( ) > 1 {
1009
+ (
1010
+ format ! (
1011
+ "candidate #{} is defined in an impl{} for the type `{}`" ,
1012
+ idx + 1 ,
1013
+ insertion,
1014
+ impl_ty,
1015
+ ) ,
1016
+ Some ( idx + 1 ) ,
1017
+ )
1018
+ } else {
1019
+ (
1020
+ format ! (
1021
+ "the candidate is defined in an impl{} for the type `{}`" ,
1022
+ insertion, impl_ty,
1023
+ ) ,
1024
+ None ,
1025
+ )
1026
+ } ;
1027
+ if let Some ( note_span) = note_span {
1028
+ // We have a span pointing to the method. Show note with snippet.
1029
+ err. span_note ( note_span, & note_str) ;
1030
+ } else {
1031
+ err. note ( & note_str) ;
1032
+ }
1033
+ if let Some ( sugg_span) = sugg_span
1034
+ && let Some ( trait_ref) = self . tcx . impl_trait_ref ( impl_did) {
1035
+ let path = self . tcx . def_path_str ( trait_ref. def_id ) ;
1036
+
1037
+ let ty = match item. kind {
1038
+ ty:: AssocKind :: Const | ty:: AssocKind :: Type => rcvr_ty,
1039
+ ty:: AssocKind :: Fn => self
1040
+ . tcx
1041
+ . fn_sig ( item. def_id )
1042
+ . inputs ( )
1043
+ . skip_binder ( )
1044
+ . get ( 0 )
1045
+ . filter ( |ty| ty. is_region_ptr ( ) && !rcvr_ty. is_region_ptr ( ) )
1046
+ . copied ( )
1047
+ . unwrap_or ( rcvr_ty) ,
1048
+ } ;
1049
+ print_disambiguation_help (
1050
+ item_name,
1051
+ args,
1052
+ err,
1053
+ path,
1054
+ ty,
1055
+ item. kind ,
1056
+ item. def_id ,
1057
+ sugg_span,
1058
+ idx,
1059
+ self . tcx . sess . source_map ( ) ,
1060
+ item. fn_has_self_parameter ,
1061
+ ) ;
1062
+ }
1063
+ }
1064
+ CandidateSource :: Trait ( trait_did) => {
1065
+ let Some ( item) = self . associated_value ( trait_did, item_name) else { continue } ;
1066
+ let item_span = self . tcx . def_span ( item. def_id ) ;
1067
+ let idx = if sources. len ( ) > 1 {
1068
+ let msg = & format ! (
1069
+ "candidate #{} is defined in the trait `{}`" ,
1070
+ idx + 1 ,
1071
+ self . tcx. def_path_str( trait_did)
1072
+ ) ;
1073
+ err. span_note ( item_span, msg) ;
1074
+ Some ( idx + 1 )
1075
+ } else {
1076
+ let msg = & format ! (
1077
+ "the candidate is defined in the trait `{}`" ,
1078
+ self . tcx. def_path_str( trait_did)
1079
+ ) ;
1080
+ err. span_note ( item_span, msg) ;
1081
+ None
1082
+ } ;
1083
+ if let Some ( sugg_span) = sugg_span {
1084
+ let path = self . tcx . def_path_str ( trait_did) ;
1085
+ print_disambiguation_help (
1086
+ item_name,
1087
+ args,
1088
+ err,
1089
+ path,
1090
+ rcvr_ty,
1091
+ item. kind ,
1092
+ item. def_id ,
1093
+ sugg_span,
1094
+ idx,
1095
+ self . tcx . sess . source_map ( ) ,
1096
+ item. fn_has_self_parameter ,
1097
+ ) ;
1098
+ }
1099
+ }
1100
+ }
1101
+ }
1102
+ if sources. len ( ) > limit {
1103
+ err. note ( & format ! ( "and {} others" , sources. len( ) - limit) ) ;
1104
+ }
1105
+ }
1106
+
1102
1107
/// Suggest calling `Ty::method` if `.method()` isn't found because the method
1103
1108
/// doesn't take a `self` receiver.
1104
1109
fn suggest_associated_call_syntax (
0 commit comments