@@ -26,6 +26,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
2626use rustc_span:: { BytePos , MultiSpan , Span , DUMMY_SP } ;
2727
2828use std:: iter;
29+ use std:: ops:: Deref ;
2930
3031use tracing:: debug;
3132
@@ -265,6 +266,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
265266 }
266267 }
267268
269+ self . detect_assoct_type_constraint_meant_as_path ( base_span, & mut err) ;
270+
268271 // Emit special messages for unresolved `Self` and `self`.
269272 if is_self_type ( path, ns) {
270273 err. code ( rustc_errors:: error_code!( E0411 ) ) ;
@@ -603,6 +606,40 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
603606 ( err, candidates)
604607 }
605608
609+ fn detect_assoct_type_constraint_meant_as_path (
610+ & self ,
611+ base_span : Span ,
612+ err : & mut DiagnosticBuilder < ' _ > ,
613+ ) {
614+ let Some ( ty) = self . diagnostic_metadata . current_type_path else { return ; } ;
615+ let TyKind :: Path ( _, path) = & ty. kind else { return ; } ;
616+ for segment in & path. segments {
617+ let Some ( params) = & segment. args else { continue ; } ;
618+ let ast:: GenericArgs :: AngleBracketed ( ref params) = params. deref ( ) else { continue ; } ;
619+ for param in & params. args {
620+ let ast:: AngleBracketedArg :: Constraint ( constraint) = param else { continue ; } ;
621+ let ast:: AssocConstraintKind :: Bound { bounds } = & constraint. kind else {
622+ continue ;
623+ } ;
624+ for bound in bounds {
625+ let ast:: GenericBound :: Trait ( trait_ref, ast:: TraitBoundModifier :: None )
626+ = bound else
627+ {
628+ continue ;
629+ } ;
630+ if base_span == trait_ref. span {
631+ err. span_suggestion_verbose (
632+ constraint. ident . span . between ( trait_ref. span ) ,
633+ "you might have meant to write a path instead of an associated type bound" ,
634+ "::" . to_string ( ) ,
635+ Applicability :: MachineApplicable ,
636+ ) ;
637+ }
638+ }
639+ }
640+ }
641+ }
642+
606643 fn get_single_associated_item (
607644 & mut self ,
608645 path : & [ Segment ] ,
0 commit comments