22#![ allow( rustc:: untranslatable_diagnostic) ]
33use std:: num:: NonZero ;
44
5- use crate :: errors:: RequestedLevel ;
5+ use crate :: builtin:: { InitError , ShorthandAssocTyCollector , TypeAliasBounds } ;
6+ use crate :: errors:: { OverruledAttributeSub , RequestedLevel } ;
67use crate :: fluent_generated as fluent;
8+ use crate :: LateContext ;
79use rustc_errors:: {
810 codes:: * , Applicability , Diag , DiagArgValue , DiagMessage , DiagStyledString ,
911 ElidedLifetimeInPathSubdiag , EmissionGuarantee , LintDiagnostic , MultiSpan , SubdiagMessageOp ,
@@ -22,8 +24,6 @@ use rustc_span::{
2224 Span , Symbol ,
2325} ;
2426
25- use crate :: { builtin:: InitError , errors:: OverruledAttributeSub , LateContext } ;
26-
2727// array_into_iter.rs
2828#[ derive( LintDiagnostic ) ]
2929#[ diag( lint_shadowed_into_iter) ]
@@ -268,97 +268,72 @@ pub struct MacroExprFragment2024 {
268268 pub suggestion : Span ,
269269}
270270
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 ,
300275 pub suggestions : Vec < ( Span , String ) > ,
301- pub applicability : Applicability ,
276+ pub preds : & ' hir [ hir:: WherePredicate < ' hir > ] ,
277+ pub ty : Option < & ' a hir:: Ty < ' hir > > ,
302278}
303279
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+ }
318292
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- ) {
325293 // We perform the walk in here instead of in `<TypeAliasBounds as LateLintPass>` to
326294 // 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) ;
331298 }
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+ ) ;
360336 }
361- ProbeShorthandAssocTys { diag } . visit_ty ( self . ty ) ;
362337 }
363338}
364339
0 commit comments