@@ -444,6 +444,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
444444 }
445445
446446 self . suggest_bare_struct_literal ( & mut err) ;
447+ self . suggest_changing_type_to_const_param ( & mut err, res, source, span) ;
447448
448449 if self . suggest_pattern_match_with_let ( & mut err, source, span) {
449450 // Fallback label.
@@ -452,7 +453,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
452453 }
453454
454455 self . suggest_self_or_self_ref ( & mut err, path, span) ;
455- self . detect_assoct_type_constraint_meant_as_path ( & mut err, & base_error) ;
456+ self . detect_assoc_type_constraint_meant_as_path ( & mut err, & base_error) ;
456457 if self . suggest_self_ty ( & mut err, source, path, span)
457458 || self . suggest_self_value ( & mut err, source, path, span)
458459 {
@@ -491,7 +492,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
491492 ( err, candidates)
492493 }
493494
494- fn detect_assoct_type_constraint_meant_as_path (
495+ fn detect_assoc_type_constraint_meant_as_path (
495496 & self ,
496497 err : & mut Diagnostic ,
497498 base_error : & BaseError ,
@@ -799,17 +800,19 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
799800 false ,
800801 ) = ( source, res, is_macro)
801802 {
802- if let Some ( bounds @ [ _, .., _] ) = self . diagnostic_metadata . current_trait_object {
803+ if let Some ( bounds @ [ first_bound, .., last_bound] ) =
804+ self . diagnostic_metadata . current_trait_object
805+ {
803806 fallback = true ;
804807 let spans: Vec < Span > = bounds
805808 . iter ( )
806809 . map ( |bound| bound. span ( ) )
807810 . filter ( |& sp| sp != base_error. span )
808811 . collect ( ) ;
809812
810- let start_span = bounds [ 0 ] . span ( ) ;
813+ let start_span = first_bound . span ( ) ;
811814 // `end_span` is the end of the poly trait ref (Foo + 'baz + Bar><)
812- let end_span = bounds . last ( ) . unwrap ( ) . span ( ) ;
815+ let end_span = last_bound . span ( ) ;
813816 // `last_bound_span` is the last bound of the poly trait ref (Foo + >'baz< + Bar)
814817 let last_bound_span = spans. last ( ) . cloned ( ) . unwrap ( ) ;
815818 let mut multi_span: MultiSpan = spans. clone ( ) . into ( ) ;
@@ -1136,6 +1139,55 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
11361139 }
11371140 }
11381141
1142+ fn suggest_changing_type_to_const_param (
1143+ & mut self ,
1144+ err : & mut Diagnostic ,
1145+ res : Option < Res > ,
1146+ source : PathSource < ' _ > ,
1147+ span : Span ,
1148+ ) {
1149+ let PathSource :: Trait ( _) = source else { return } ;
1150+
1151+ // We don't include `DefKind::Str` and `DefKind::AssocTy` as they can't be reached here anyway.
1152+ let applicability = match res {
1153+ Some ( Res :: PrimTy ( PrimTy :: Int ( _) | PrimTy :: Uint ( _) | PrimTy :: Bool | PrimTy :: Char ) ) => {
1154+ Applicability :: MachineApplicable
1155+ }
1156+ // FIXME(const_generics): Add `DefKind::TyParam` and `SelfTyParam` once we support generic
1157+ // const generics. Of course, `Struct` and `Enum` may contain ty params, too, but the
1158+ // benefits of including them here outweighs the small number of false positives.
1159+ Some ( Res :: Def ( DefKind :: Struct | DefKind :: Enum , _) )
1160+ if self . r . tcx . features ( ) . adt_const_params =>
1161+ {
1162+ Applicability :: MaybeIncorrect
1163+ }
1164+ _ => return ,
1165+ } ;
1166+
1167+ let Some ( item) = self . diagnostic_metadata . current_item else { return } ;
1168+ let Some ( generics) = item. kind . generics ( ) else { return } ;
1169+
1170+ let param = generics. params . iter ( ) . find_map ( |param| {
1171+ // Only consider type params with exactly one trait bound.
1172+ if let [ bound] = & * param. bounds
1173+ && let ast:: GenericBound :: Trait ( tref, ast:: TraitBoundModifiers :: NONE ) = bound
1174+ && tref. span == span
1175+ && param. ident . span . eq_ctxt ( span)
1176+ {
1177+ Some ( param. ident . span )
1178+ } else {
1179+ None
1180+ }
1181+ } ) ;
1182+
1183+ if let Some ( param) = param {
1184+ err. subdiagnostic ( errors:: UnexpectedResChangeTyToConstParamSugg {
1185+ span : param. shrink_to_lo ( ) ,
1186+ applicability,
1187+ } ) ;
1188+ }
1189+ }
1190+
11391191 fn suggest_pattern_match_with_let (
11401192 & mut self ,
11411193 err : & mut Diagnostic ,
@@ -2419,10 +2471,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
24192471 let mut iter = ident. chars ( ) . map ( |c| c. is_uppercase ( ) ) ;
24202472 let single_uppercase_char =
24212473 matches ! ( iter. next( ) , Some ( true ) ) && matches ! ( iter. next( ) , None ) ;
2422- if !self . diagnostic_metadata . currently_processing_generics && !single_uppercase_char {
2474+ if !self . diagnostic_metadata . currently_processing_generic_args && !single_uppercase_char {
24232475 return None ;
24242476 }
2425- match ( self . diagnostic_metadata . current_item , single_uppercase_char, self . diagnostic_metadata . currently_processing_generics ) {
2477+ match ( self . diagnostic_metadata . current_item , single_uppercase_char, self . diagnostic_metadata . currently_processing_generic_args ) {
24262478 ( Some ( Item { kind : ItemKind :: Fn ( ..) , ident, .. } ) , _, _) if ident. name == sym:: main => {
24272479 // Ignore `fn main()` as we don't want to suggest `fn main<T>()`
24282480 }
0 commit comments