2
2
#![ allow( rustc:: untranslatable_diagnostic) ]
3
3
use std:: num:: NonZero ;
4
4
5
- use crate :: errors:: RequestedLevel ;
5
+ use crate :: builtin:: { InitError , ShorthandAssocTyCollector , TypeAliasBounds } ;
6
+ use crate :: errors:: { OverruledAttributeSub , RequestedLevel } ;
6
7
use crate :: fluent_generated as fluent;
8
+ use crate :: LateContext ;
7
9
use rustc_errors:: {
8
10
codes:: * , Applicability , Diag , DiagArgValue , DiagMessage , DiagStyledString ,
9
11
ElidedLifetimeInPathSubdiag , EmissionGuarantee , LintDiagnostic , MultiSpan , SubdiagMessageOp ,
@@ -22,8 +24,6 @@ use rustc_span::{
22
24
Span , Symbol ,
23
25
} ;
24
26
25
- use crate :: { builtin:: InitError , errors:: OverruledAttributeSub , LateContext } ;
26
-
27
27
// array_into_iter.rs
28
28
#[ derive( LintDiagnostic ) ]
29
29
#[ diag( lint_shadowed_into_iter) ]
@@ -268,97 +268,72 @@ pub struct MacroExprFragment2024 {
268
268
pub suggestion : Span ,
269
269
}
270
270
271
- #[ derive( LintDiagnostic ) ]
272
- pub enum BuiltinTypeAliasBounds < ' a , ' hir > {
273
- #[ diag( lint_builtin_type_alias_bounds_where_clause) ]
274
- #[ note( lint_builtin_type_alias_bounds_limitation_note) ]
275
- WhereClause {
276
- #[ label( lint_builtin_type_alias_bounds_label) ]
277
- label : Span ,
278
- #[ help( lint_builtin_type_alias_bounds_enable_feat_help) ]
279
- enable_feat_help : Option < ( ) > ,
280
- #[ suggestion( code = "" ) ]
281
- suggestion : ( Span , Applicability ) ,
282
- #[ subdiagnostic]
283
- qualify_assoc_tys_sugg : Option < TypeAliasBoundsQualifyAssocTysSugg < ' a , ' hir > > ,
284
- } ,
285
- #[ diag( lint_builtin_type_alias_bounds_param_bounds) ]
286
- #[ note( lint_builtin_type_alias_bounds_limitation_note) ]
287
- ParamBounds {
288
- #[ label( lint_builtin_type_alias_bounds_label) ]
289
- label : Span ,
290
- #[ help( lint_builtin_type_alias_bounds_enable_feat_help) ]
291
- enable_feat_help : Option < ( ) > ,
292
- #[ subdiagnostic]
293
- suggestion : BuiltinTypeAliasParamBoundsSuggestion ,
294
- #[ subdiagnostic]
295
- qualify_assoc_tys_sugg : Option < TypeAliasBoundsQualifyAssocTysSugg < ' a , ' hir > > ,
296
- } ,
297
- }
298
-
299
- pub struct BuiltinTypeAliasParamBoundsSuggestion {
271
+ pub struct BuiltinTypeAliasBounds < ' a , ' hir > {
272
+ pub in_where_clause : bool ,
273
+ pub label : Span ,
274
+ pub enable_feat_help : bool ,
300
275
pub suggestions : Vec < ( Span , String ) > ,
301
- pub applicability : Applicability ,
276
+ pub preds : & ' hir [ hir:: WherePredicate < ' hir > ] ,
277
+ pub ty : Option < & ' a hir:: Ty < ' hir > > ,
302
278
}
303
279
304
- impl Subdiagnostic for BuiltinTypeAliasParamBoundsSuggestion {
305
- fn add_to_diag_with < G : EmissionGuarantee , F : SubdiagMessageOp < G > > (
306
- self ,
307
- diag : & mut Diag < ' _ , G > ,
308
- _f : & F ,
309
- ) {
310
- diag. arg ( "count" , self . suggestions . len ( ) ) ;
311
- diag. multipart_suggestion ( fluent:: lint_suggestion, self . suggestions , self . applicability ) ;
312
- }
313
- }
314
-
315
- pub struct TypeAliasBoundsQualifyAssocTysSugg < ' a , ' hir > {
316
- pub ty : & ' a hir:: Ty < ' hir > ,
317
- }
280
+ impl < ' a > LintDiagnostic < ' a , ( ) > for BuiltinTypeAliasBounds < ' _ , ' _ > {
281
+ fn decorate_lint < ' b > ( self , diag : & ' b mut Diag < ' a , ( ) > ) {
282
+ diag. primary_message ( if self . in_where_clause {
283
+ fluent:: lint_builtin_type_alias_bounds_where_clause
284
+ } else {
285
+ fluent:: lint_builtin_type_alias_bounds_param_bounds
286
+ } ) ;
287
+ diag. span_label ( self . label , fluent:: lint_builtin_type_alias_bounds_label) ;
288
+ diag. note ( fluent:: lint_builtin_type_alias_bounds_limitation_note) ;
289
+ if self . enable_feat_help {
290
+ diag. help ( fluent:: lint_builtin_type_alias_bounds_enable_feat_help) ;
291
+ }
318
292
319
- impl < ' a , ' hir > Subdiagnostic for TypeAliasBoundsQualifyAssocTysSugg < ' a , ' hir > {
320
- fn add_to_diag_with < G : EmissionGuarantee , F : SubdiagMessageOp < G > > (
321
- self ,
322
- diag : & mut Diag < ' _ , G > ,
323
- _f : & F ,
324
- ) {
325
293
// We perform the walk in here instead of in `<TypeAliasBounds as LateLintPass>` to
326
294
// avoid doing throwaway work in case the lint ends up getting suppressed.
327
-
328
- use hir:: intravisit:: Visitor ;
329
- struct ProbeShorthandAssocTys < ' a , ' b , G : EmissionGuarantee > {
330
- diag : & ' a mut Diag < ' b , G > ,
295
+ let mut collector = ShorthandAssocTyCollector { qselves : Vec :: new ( ) } ;
296
+ if let Some ( ty) = self . ty {
297
+ hir:: intravisit:: Visitor :: visit_ty ( & mut collector, ty) ;
331
298
}
332
- impl < ' a , ' b , G : EmissionGuarantee > Visitor < ' _ > for ProbeShorthandAssocTys < ' a , ' b , G > {
333
- fn visit_qpath ( & mut self , qpath : & hir:: QPath < ' _ > , id : hir:: HirId , _: Span ) {
334
- // Look for "type-parameter shorthand-associated-types". I.e., paths of the
335
- // form `T::Assoc` with `T` type param. These are reliant on trait bounds.
336
- // Suggest fully qualifying them via `<T as /* Trait */>::Assoc`.
337
- //
338
- // Instead of attempting to figure out the necessary trait ref, just use a
339
- // placeholder. Since we don't record type-dependent resolutions for non-body
340
- // items like type aliases, we can't simply deduce the corresp. trait from
341
- // the HIR path alone without rerunning parts of HIR ty lowering here
342
- // (namely `probe_single_ty_param_bound_for_assoc_ty`) which is infeasible.
343
- //
344
- // (We could employ some simple heuristics but that's likely not worth it).
345
- if let hir:: QPath :: TypeRelative ( qself, _) = qpath
346
- && let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , path) ) = qself. kind
347
- && let hir:: def:: Res :: Def ( hir:: def:: DefKind :: TyParam , _) = path. res
348
- {
349
- self . diag . multipart_suggestion (
350
- fluent:: lint_builtin_type_alias_bounds_qualify_assoc_tys_sugg,
351
- vec ! [
352
- ( qself. span. shrink_to_lo( ) , "<" . into( ) ) ,
353
- ( qself. span. shrink_to_hi( ) , " as /* Trait */>" . into( ) ) ,
354
- ] ,
355
- Applicability :: HasPlaceholders ,
356
- ) ;
357
- }
358
- hir:: intravisit:: walk_qpath ( self , qpath, id)
359
- }
299
+
300
+ let affect_object_lifetime_defaults = self
301
+ . preds
302
+ . iter ( )
303
+ . filter ( |pred| pred. in_where_clause ( ) == self . in_where_clause )
304
+ . any ( |pred| TypeAliasBounds :: affects_object_lifetime_defaults ( pred) ) ;
305
+
306
+ // If there are any shorthand assoc tys, then the bounds can't be removed automatically.
307
+ // The user first needs to fully qualify the assoc tys.
308
+ let applicability = if !collector. qselves . is_empty ( ) || affect_object_lifetime_defaults {
309
+ Applicability :: MaybeIncorrect
310
+ } else {
311
+ Applicability :: MachineApplicable
312
+ } ;
313
+
314
+ diag. arg ( "count" , self . suggestions . len ( ) ) ;
315
+ diag. multipart_suggestion ( fluent:: lint_suggestion, self . suggestions , applicability) ;
316
+
317
+ // Suggest fully qualifying paths of the form `T::Assoc` with `T` type param via
318
+ // `<T as /* Trait */>::Assoc` to remove their reliance on any type param bounds.
319
+ //
320
+ // Instead of attempting to figure out the necessary trait ref, just use a
321
+ // placeholder. Since we don't record type-dependent resolutions for non-body
322
+ // items like type aliases, we can't simply deduce the corresp. trait from
323
+ // the HIR path alone without rerunning parts of HIR ty lowering here
324
+ // (namely `probe_single_ty_param_bound_for_assoc_ty`) which is infeasible.
325
+ //
326
+ // (We could employ some simple heuristics but that's likely not worth it).
327
+ for qself in collector. qselves {
328
+ diag. multipart_suggestion (
329
+ fluent:: lint_builtin_type_alias_bounds_qualify_assoc_tys_sugg,
330
+ vec ! [
331
+ ( qself. shrink_to_lo( ) , "<" . into( ) ) ,
332
+ ( qself. shrink_to_hi( ) , " as /* Trait */>" . into( ) ) ,
333
+ ] ,
334
+ Applicability :: HasPlaceholders ,
335
+ ) ;
360
336
}
361
- ProbeShorthandAssocTys { diag } . visit_ty ( self . ty ) ;
362
337
}
363
338
}
364
339
0 commit comments