@@ -5,9 +5,9 @@ use rustc_errors::codes::*;
5
5
use rustc_errors:: {
6
6
Applicability , Diag , ErrorGuaranteed , MultiSpan , listify, pluralize, struct_span_code_err,
7
7
} ;
8
- use rustc_hir as hir;
9
8
use rustc_hir:: def:: { CtorOf , DefKind , Res } ;
10
9
use rustc_hir:: def_id:: DefId ;
10
+ use rustc_hir:: { self as hir, HirId } ;
11
11
use rustc_middle:: bug;
12
12
use rustc_middle:: ty:: fast_reject:: { TreatParams , simplify_type} ;
13
13
use rustc_middle:: ty:: print:: { PrintPolyTraitRefExt as _, PrintTraitRefExt as _} ;
@@ -23,6 +23,7 @@ use rustc_trait_selection::traits::{
23
23
FulfillmentError , dyn_compatibility_violations_for_assoc_item,
24
24
} ;
25
25
use smallvec:: SmallVec ;
26
+ use tracing:: debug;
26
27
27
28
use crate :: errors:: {
28
29
self , AssocItemConstraintsNotAllowedHere , ManualImplementation , MissingTypeParams ,
@@ -34,7 +35,7 @@ use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
34
35
impl < ' tcx > dyn HirTyLowerer < ' tcx > + ' _ {
35
36
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
36
37
/// the type parameter's name as a placeholder.
37
- pub ( crate ) fn complain_about_missing_type_params (
38
+ pub ( crate ) fn report_missing_type_params (
38
39
& self ,
39
40
missing_type_params : Vec < Symbol > ,
40
41
def_id : DefId ,
@@ -56,7 +57,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
56
57
57
58
/// When the code is using the `Fn` traits directly, instead of the `Fn(A) -> B` syntax, emit
58
59
/// an error and attempt to build a reasonable structured suggestion.
59
- pub ( crate ) fn complain_about_internal_fn_trait (
60
+ pub ( crate ) fn report_internal_fn_trait (
60
61
& self ,
61
62
span : Span ,
62
63
trait_def_id : DefId ,
@@ -112,7 +113,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
112
113
}
113
114
}
114
115
115
- pub ( super ) fn complain_about_assoc_item_not_found < I > (
116
+ pub ( super ) fn report_unresolved_assoc_item < I > (
116
117
& self ,
117
118
all_candidates : impl Fn ( ) -> I ,
118
119
qself : AssocItemQSelf ,
@@ -132,7 +133,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
132
133
. filter_by_name_unhygienic ( assoc_ident. name )
133
134
. find ( |item| tcx. hygienic_eq ( assoc_ident, item. ident ( tcx) , r. def_id ( ) ) )
134
135
} ) {
135
- return self . complain_about_assoc_kind_mismatch (
136
+ return self . report_assoc_kind_mismatch (
136
137
assoc_item,
137
138
assoc_tag,
138
139
assoc_ident,
@@ -331,7 +332,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
331
332
self . dcx ( ) . emit_err ( err)
332
333
}
333
334
334
- fn complain_about_assoc_kind_mismatch (
335
+ fn report_assoc_kind_mismatch (
335
336
& self ,
336
337
assoc_item : & ty:: AssocItem ,
337
338
assoc_tag : ty:: AssocTag ,
@@ -396,7 +397,173 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
396
397
} )
397
398
}
398
399
399
- pub ( super ) fn report_ambiguous_assoc (
400
+ pub ( crate ) fn report_missing_self_ty_for_resolved_path (
401
+ & self ,
402
+ trait_def_id : DefId ,
403
+ span : Span ,
404
+ item_segment : & hir:: PathSegment < ' tcx > ,
405
+ assoc_tag : ty:: AssocTag ,
406
+ ) -> ErrorGuaranteed {
407
+ let tcx = self . tcx ( ) ;
408
+ let path_str = tcx. def_path_str ( trait_def_id) ;
409
+
410
+ let def_id = self . item_def_id ( ) ;
411
+ debug ! ( item_def_id = ?def_id) ;
412
+
413
+ // FIXME: document why/how this is different from `tcx.local_parent(def_id)`
414
+ let parent_def_id = tcx. hir_get_parent_item ( tcx. local_def_id_to_hir_id ( def_id) ) . to_def_id ( ) ;
415
+ debug ! ( ?parent_def_id) ;
416
+
417
+ // If the trait in segment is the same as the trait defining the item,
418
+ // use the `<Self as ..>` syntax in the error.
419
+ let is_part_of_self_trait_constraints = def_id. to_def_id ( ) == trait_def_id;
420
+ let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id;
421
+
422
+ let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
423
+ vec ! [ "Self" . to_string( ) ]
424
+ } else {
425
+ // Find all the types that have an `impl` for the trait.
426
+ tcx. all_impls ( trait_def_id)
427
+ . filter_map ( |impl_def_id| tcx. impl_trait_header ( impl_def_id) )
428
+ . filter ( |header| {
429
+ // Consider only accessible traits
430
+ tcx. visibility ( trait_def_id) . is_accessible_from ( self . item_def_id ( ) , tcx)
431
+ && header. polarity != ty:: ImplPolarity :: Negative
432
+ } )
433
+ . map ( |header| header. trait_ref . instantiate_identity ( ) . self_ty ( ) )
434
+ // We don't care about blanket impls.
435
+ . filter ( |self_ty| !self_ty. has_non_region_param ( ) )
436
+ . map ( |self_ty| tcx. erase_regions ( self_ty) . to_string ( ) )
437
+ . collect ( )
438
+ } ;
439
+ // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
440
+ // references the trait. Relevant for the first case in
441
+ // `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
442
+ self . report_ambiguous_assoc_item_path (
443
+ span,
444
+ & type_names,
445
+ & [ path_str] ,
446
+ item_segment. ident . name ,
447
+ assoc_tag,
448
+ )
449
+ }
450
+
451
+ pub ( super ) fn report_unresolved_type_relative_path (
452
+ & self ,
453
+ self_ty : Ty < ' tcx > ,
454
+ hir_self_ty : & hir:: Ty < ' _ > ,
455
+ assoc_tag : ty:: AssocTag ,
456
+ ident : Ident ,
457
+ qpath_hir_id : HirId ,
458
+ span : Span ,
459
+ variant_def_id : Option < DefId > ,
460
+ ) -> ErrorGuaranteed {
461
+ let tcx = self . tcx ( ) ;
462
+ let kind_str = assoc_tag_str ( assoc_tag) ;
463
+ if variant_def_id. is_some ( ) {
464
+ // Variant in type position
465
+ let msg = format ! ( "expected {kind_str}, found variant `{ident}`" ) ;
466
+ self . dcx ( ) . span_err ( span, msg)
467
+ } else if self_ty. is_enum ( ) {
468
+ let mut err = self . dcx ( ) . create_err ( errors:: NoVariantNamed {
469
+ span : ident. span ,
470
+ ident,
471
+ ty : self_ty,
472
+ } ) ;
473
+
474
+ let adt_def = self_ty. ty_adt_def ( ) . expect ( "enum is not an ADT" ) ;
475
+ if let Some ( variant_name) = find_best_match_for_name (
476
+ & adt_def. variants ( ) . iter ( ) . map ( |variant| variant. name ) . collect :: < Vec < Symbol > > ( ) ,
477
+ ident. name ,
478
+ None ,
479
+ ) && let Some ( variant) = adt_def. variants ( ) . iter ( ) . find ( |s| s. name == variant_name)
480
+ {
481
+ let mut suggestion = vec ! [ ( ident. span, variant_name. to_string( ) ) ] ;
482
+ if let hir:: Node :: Stmt ( & hir:: Stmt { kind : hir:: StmtKind :: Semi ( expr) , .. } )
483
+ | hir:: Node :: Expr ( expr) = tcx. parent_hir_node ( qpath_hir_id)
484
+ && let hir:: ExprKind :: Struct ( ..) = expr. kind
485
+ {
486
+ match variant. ctor {
487
+ None => {
488
+ // struct
489
+ suggestion = vec ! [ (
490
+ ident. span. with_hi( expr. span. hi( ) ) ,
491
+ if variant. fields. is_empty( ) {
492
+ format!( "{variant_name} {{}}" )
493
+ } else {
494
+ format!(
495
+ "{variant_name} {{ {} }}" ,
496
+ variant
497
+ . fields
498
+ . iter( )
499
+ . map( |f| format!( "{}: /* value */" , f. name) )
500
+ . collect:: <Vec <_>>( )
501
+ . join( ", " )
502
+ )
503
+ } ,
504
+ ) ] ;
505
+ }
506
+ Some ( ( hir:: def:: CtorKind :: Fn , def_id) ) => {
507
+ // tuple
508
+ let fn_sig = tcx. fn_sig ( def_id) . instantiate_identity ( ) ;
509
+ let inputs = fn_sig. inputs ( ) . skip_binder ( ) ;
510
+ suggestion = vec ! [ (
511
+ ident. span. with_hi( expr. span. hi( ) ) ,
512
+ format!(
513
+ "{variant_name}({})" ,
514
+ inputs
515
+ . iter( )
516
+ . map( |i| format!( "/* {i} */" ) )
517
+ . collect:: <Vec <_>>( )
518
+ . join( ", " )
519
+ ) ,
520
+ ) ] ;
521
+ }
522
+ Some ( ( hir:: def:: CtorKind :: Const , _) ) => {
523
+ // unit
524
+ suggestion = vec ! [ (
525
+ ident. span. with_hi( expr. span. hi( ) ) ,
526
+ variant_name. to_string( ) ,
527
+ ) ] ;
528
+ }
529
+ }
530
+ }
531
+ err. multipart_suggestion_verbose (
532
+ "there is a variant with a similar name" ,
533
+ suggestion,
534
+ Applicability :: HasPlaceholders ,
535
+ ) ;
536
+ } else {
537
+ err. span_label ( ident. span , format ! ( "variant not found in `{self_ty}`" ) ) ;
538
+ }
539
+
540
+ if let Some ( sp) = tcx. hir_span_if_local ( adt_def. did ( ) ) {
541
+ err. span_label ( sp, format ! ( "variant `{ident}` not found here" ) ) ;
542
+ }
543
+
544
+ err. emit ( )
545
+ } else if let Err ( reported) = self_ty. error_reported ( ) {
546
+ reported
547
+ } else {
548
+ match self . maybe_report_similar_assoc_fn ( span, self_ty, hir_self_ty) {
549
+ Ok ( ( ) ) => { }
550
+ Err ( reported) => return reported,
551
+ }
552
+
553
+ let traits: Vec < _ > = self . probe_traits_that_match_assoc_ty ( self_ty, ident) ;
554
+
555
+ // Don't print `ty::Error` to the user.
556
+ self . report_ambiguous_assoc_item_path (
557
+ span,
558
+ & [ self_ty. to_string ( ) ] ,
559
+ & traits,
560
+ ident. name ,
561
+ assoc_tag,
562
+ )
563
+ }
564
+ }
565
+
566
+ pub ( super ) fn report_ambiguous_assoc_item_path (
400
567
& self ,
401
568
span : Span ,
402
569
types : & [ String ] ,
@@ -505,7 +672,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
505
672
err. emit ( )
506
673
}
507
674
508
- pub ( crate ) fn complain_about_ambiguous_inherent_assoc (
675
+ pub ( crate ) fn report_ambiguous_inherent_assoc_item (
509
676
& self ,
510
677
name : Ident ,
511
678
candidates : Vec < DefId > ,
@@ -518,12 +685,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
518
685
"multiple applicable items in scope"
519
686
) ;
520
687
err. span_label ( name. span , format ! ( "multiple `{name}` found" ) ) ;
521
- self . note_ambiguous_inherent_assoc_ty ( & mut err, candidates, span) ;
688
+ self . note_ambiguous_inherent_assoc_item ( & mut err, candidates, span) ;
522
689
err. emit ( )
523
690
}
524
691
525
692
// FIXME(fmease): Heavily adapted from `rustc_hir_typeck::method::suggest`. Deduplicate.
526
- fn note_ambiguous_inherent_assoc_ty (
693
+ fn note_ambiguous_inherent_assoc_item (
527
694
& self ,
528
695
err : & mut Diag < ' _ > ,
529
696
candidates : Vec < DefId > ,
@@ -566,7 +733,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
566
733
}
567
734
568
735
// FIXME(inherent_associated_types): Find similarly named associated types and suggest them.
569
- pub ( crate ) fn complain_about_inherent_assoc_not_found (
736
+ pub ( crate ) fn report_unresolved_inherent_assoc_item (
570
737
& self ,
571
738
name : Ident ,
572
739
self_ty : Ty < ' tcx > ,
@@ -1046,7 +1213,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1046
1213
}
1047
1214
}
1048
1215
1049
- pub fn report_prohibit_generics_error < ' a > (
1216
+ pub fn report_prohibited_generic_args < ' a > (
1050
1217
& self ,
1051
1218
segments : impl Iterator < Item = & ' a hir:: PathSegment < ' a > > + Clone ,
1052
1219
args_visitors : impl Iterator < Item = & ' a hir:: GenericArg < ' a > > + Clone ,
@@ -1128,7 +1295,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1128
1295
err. emit ( )
1129
1296
}
1130
1297
1131
- pub fn report_trait_object_addition_traits_error (
1298
+ pub fn report_trait_object_addition_traits (
1132
1299
& self ,
1133
1300
regular_traits : & Vec < ( ty:: PolyTraitPredicate < ' tcx > , SmallVec < [ Span ; 1 ] > ) > ,
1134
1301
) -> ErrorGuaranteed {
@@ -1171,7 +1338,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1171
1338
err. emit ( )
1172
1339
}
1173
1340
1174
- pub fn report_trait_object_with_no_traits_error (
1341
+ pub fn report_trait_object_with_no_traits (
1175
1342
& self ,
1176
1343
span : Span ,
1177
1344
user_written_clauses : impl IntoIterator < Item = ( ty:: Clause < ' tcx > , Span ) > ,
0 commit comments