@@ -22,7 +22,7 @@ use rustc_span::symbol::{sym, Ident};
2222use rustc_span:: { Span , Symbol , DUMMY_SP } ;
2323use rustc_trait_selection:: traits:: object_safety_violations_for_assoc_item;
2424
25- impl < ' o , ' tcx > dyn AstConv < ' tcx > + ' o {
25+ impl < ' tcx > dyn AstConv < ' tcx > + ' _ {
2626 /// On missing type parameters, emit an E0393 error and provide a structured suggestion using
2727 /// the type parameter's name as a placeholder.
2828 pub ( crate ) fn complain_about_missing_type_params (
@@ -349,6 +349,118 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
349349 } )
350350 }
351351
352+ pub ( super ) fn report_ambiguous_associated_type (
353+ & self ,
354+ span : Span ,
355+ types : & [ String ] ,
356+ traits : & [ String ] ,
357+ name : Symbol ,
358+ ) -> ErrorGuaranteed {
359+ let mut err =
360+ struct_span_code_err ! ( self . tcx( ) . dcx( ) , span, E0223 , "ambiguous associated type" ) ;
361+ if self
362+ . tcx ( )
363+ . resolutions ( ( ) )
364+ . confused_type_with_std_module
365+ . keys ( )
366+ . any ( |full_span| full_span. contains ( span) )
367+ {
368+ err. span_suggestion_verbose (
369+ span. shrink_to_lo ( ) ,
370+ "you are looking for the module in `std`, not the primitive type" ,
371+ "std::" ,
372+ Applicability :: MachineApplicable ,
373+ ) ;
374+ } else {
375+ let mut types = types. to_vec ( ) ;
376+ types. sort ( ) ;
377+ let mut traits = traits. to_vec ( ) ;
378+ traits. sort ( ) ;
379+ match ( & types[ ..] , & traits[ ..] ) {
380+ ( [ ] , [ ] ) => {
381+ err. span_suggestion_verbose (
382+ span,
383+ format ! (
384+ "if there were a type named `Type` that implements a trait named \
385+ `Trait` with associated type `{name}`, you could use the \
386+ fully-qualified path",
387+ ) ,
388+ format ! ( "<Type as Trait>::{name}" ) ,
389+ Applicability :: HasPlaceholders ,
390+ ) ;
391+ }
392+ ( [ ] , [ trait_str] ) => {
393+ err. span_suggestion_verbose (
394+ span,
395+ format ! (
396+ "if there were a type named `Example` that implemented `{trait_str}`, \
397+ you could use the fully-qualified path",
398+ ) ,
399+ format ! ( "<Example as {trait_str}>::{name}" ) ,
400+ Applicability :: HasPlaceholders ,
401+ ) ;
402+ }
403+ ( [ ] , traits) => {
404+ err. span_suggestions (
405+ span,
406+ format ! (
407+ "if there were a type named `Example` that implemented one of the \
408+ traits with associated type `{name}`, you could use the \
409+ fully-qualified path",
410+ ) ,
411+ traits
412+ . iter ( )
413+ . map ( |trait_str| format ! ( "<Example as {trait_str}>::{name}" ) )
414+ . collect :: < Vec < _ > > ( ) ,
415+ Applicability :: HasPlaceholders ,
416+ ) ;
417+ }
418+ ( [ type_str] , [ ] ) => {
419+ err. span_suggestion_verbose (
420+ span,
421+ format ! (
422+ "if there were a trait named `Example` with associated type `{name}` \
423+ implemented for `{type_str}`, you could use the fully-qualified path",
424+ ) ,
425+ format ! ( "<{type_str} as Example>::{name}" ) ,
426+ Applicability :: HasPlaceholders ,
427+ ) ;
428+ }
429+ ( types, [ ] ) => {
430+ err. span_suggestions (
431+ span,
432+ format ! (
433+ "if there were a trait named `Example` with associated type `{name}` \
434+ implemented for one of the types, you could use the fully-qualified \
435+ path",
436+ ) ,
437+ types
438+ . into_iter ( )
439+ . map ( |type_str| format ! ( "<{type_str} as Example>::{name}" ) ) ,
440+ Applicability :: HasPlaceholders ,
441+ ) ;
442+ }
443+ ( types, traits) => {
444+ let mut suggestions = vec ! [ ] ;
445+ for type_str in types {
446+ for trait_str in traits {
447+ suggestions. push ( format ! ( "<{type_str} as {trait_str}>::{name}" ) ) ;
448+ }
449+ }
450+ err. span_suggestions (
451+ span,
452+ "use fully-qualified syntax" ,
453+ suggestions,
454+ Applicability :: MachineApplicable ,
455+ ) ;
456+ }
457+ }
458+ }
459+ let reported = err. emit ( ) ;
460+ self . set_tainted_by_errors ( reported) ;
461+ reported
462+ }
463+
352464 pub ( crate ) fn complain_about_ambiguous_inherent_assoc_type (
353465 & self ,
354466 name : Ident ,
0 commit comments