@@ -444,6 +444,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
444
444
}
445
445
446
446
self . suggest_bare_struct_literal ( & mut err) ;
447
+ self . suggest_changing_type_to_const_param ( & mut err, res, source, span) ;
447
448
448
449
if self . suggest_pattern_match_with_let ( & mut err, source, span) {
449
450
// Fallback label.
@@ -452,7 +453,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
452
453
}
453
454
454
455
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) ;
456
457
if self . suggest_self_ty ( & mut err, source, path, span)
457
458
|| self . suggest_self_value ( & mut err, source, path, span)
458
459
{
@@ -491,7 +492,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
491
492
( err, candidates)
492
493
}
493
494
494
- fn detect_assoct_type_constraint_meant_as_path (
495
+ fn detect_assoc_type_constraint_meant_as_path (
495
496
& self ,
496
497
err : & mut Diagnostic ,
497
498
base_error : & BaseError ,
@@ -799,17 +800,19 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
799
800
false ,
800
801
) = ( source, res, is_macro)
801
802
{
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
+ {
803
806
fallback = true ;
804
807
let spans: Vec < Span > = bounds
805
808
. iter ( )
806
809
. map ( |bound| bound. span ( ) )
807
810
. filter ( |& sp| sp != base_error. span )
808
811
. collect ( ) ;
809
812
810
- let start_span = bounds [ 0 ] . span ( ) ;
813
+ let start_span = first_bound . span ( ) ;
811
814
// `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 ( ) ;
813
816
// `last_bound_span` is the last bound of the poly trait ref (Foo + >'baz< + Bar)
814
817
let last_bound_span = spans. last ( ) . cloned ( ) . unwrap ( ) ;
815
818
let mut multi_span: MultiSpan = spans. clone ( ) . into ( ) ;
@@ -1136,6 +1139,55 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
1136
1139
}
1137
1140
}
1138
1141
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
+
1139
1191
fn suggest_pattern_match_with_let (
1140
1192
& mut self ,
1141
1193
err : & mut Diagnostic ,
@@ -2419,10 +2471,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
2419
2471
let mut iter = ident. chars ( ) . map ( |c| c. is_uppercase ( ) ) ;
2420
2472
let single_uppercase_char =
2421
2473
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 {
2423
2475
return None ;
2424
2476
}
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 ) {
2426
2478
( Some ( Item { kind : ItemKind :: Fn ( ..) , ident, .. } ) , _, _) if ident. name == sym:: main => {
2427
2479
// Ignore `fn main()` as we don't want to suggest `fn main<T>()`
2428
2480
}
0 commit comments