11use clippy_utils:: def_path_def_ids;
2+ use rustc_errors:: { Applicability , Diag } ;
23use rustc_hir:: def_id:: DefIdMap ;
34use rustc_middle:: ty:: TyCtxt ;
5+ use rustc_span:: Span ;
46use serde:: de:: { self , Deserializer , Visitor } ;
57use serde:: { Deserialize , Serialize , ser} ;
68use std:: collections:: HashMap ;
@@ -12,37 +14,99 @@ pub struct Rename {
1214 pub rename : String ,
1315}
1416
15- #[ derive( Debug , Deserialize ) ]
17+ pub type DisallowedPathWithoutReplacement = DisallowedPath < false > ;
18+
19+ #[ derive( Debug , Serialize ) ]
20+ pub struct DisallowedPath < const REPLACEMENT_ALLOWED : bool = true> {
21+ path : String ,
22+ reason : Option < String > ,
23+ replacement : Option < String > ,
24+ }
25+
26+ impl < ' de , const REPLACEMENT_ALLOWED : bool > Deserialize < ' de > for DisallowedPath < REPLACEMENT_ALLOWED > {
27+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
28+ where
29+ D : Deserializer < ' de > ,
30+ {
31+ let enum_ = DisallowedPathEnum :: deserialize ( deserializer) ?;
32+ if !REPLACEMENT_ALLOWED && enum_. replacement ( ) . is_some ( ) {
33+ return Err ( de:: Error :: custom ( "replacement not allowed for this configuration" ) ) ;
34+ }
35+ Ok ( Self {
36+ path : enum_. path ( ) . to_owned ( ) ,
37+ reason : enum_. reason ( ) . map ( ToOwned :: to_owned) ,
38+ replacement : enum_. replacement ( ) . map ( ToOwned :: to_owned) ,
39+ } )
40+ }
41+ }
42+
43+ // `DisallowedPathEnum` is an implementation detail to enable the `Deserialize` implementation just
44+ // above. `DisallowedPathEnum` is not meant to be used outside of this file.
45+ #[ derive( Debug , Deserialize , Serialize ) ]
1646#[ serde( untagged) ]
17- pub enum DisallowedPath {
47+ enum DisallowedPathEnum {
1848 Simple ( String ) ,
19- WithReason { path : String , reason : Option < String > } ,
49+ WithReason {
50+ path : String ,
51+ reason : Option < String > ,
52+ replacement : Option < String > ,
53+ } ,
2054}
2155
22- impl DisallowedPath {
56+ impl < const REPLACEMENT_ALLOWED : bool > DisallowedPath < REPLACEMENT_ALLOWED > {
57+ pub fn path ( & self ) -> & str {
58+ & self . path
59+ }
60+
61+ pub fn diag_amendment ( & self , span : Span ) -> impl FnOnce ( & mut Diag < ' _ , ( ) > ) + use < ' _ , REPLACEMENT_ALLOWED > {
62+ move |diag| {
63+ if let Some ( replacement) = & self . replacement {
64+ diag. span_suggestion (
65+ span,
66+ self . reason . as_ref ( ) . map_or_else ( || String :: from ( "use" ) , Clone :: clone) ,
67+ replacement,
68+ Applicability :: MachineApplicable ,
69+ ) ;
70+ } else if let Some ( reason) = & self . reason {
71+ diag. note ( reason. clone ( ) ) ;
72+ }
73+ }
74+ }
75+ }
76+
77+ impl DisallowedPathEnum {
2378 pub fn path ( & self ) -> & str {
2479 let ( Self :: Simple ( path) | Self :: WithReason { path, .. } ) = self ;
2580
2681 path
2782 }
2883
29- pub fn reason ( & self ) -> Option < & str > {
84+ fn reason ( & self ) -> Option < & str > {
3085 match & self {
3186 Self :: WithReason { reason, .. } => reason. as_deref ( ) ,
3287 Self :: Simple ( _) => None ,
3388 }
3489 }
90+
91+ fn replacement ( & self ) -> Option < & str > {
92+ match & self {
93+ Self :: WithReason { replacement, .. } => replacement. as_deref ( ) ,
94+ Self :: Simple ( _) => None ,
95+ }
96+ }
3597}
3698
3799/// Creates a map of disallowed items to the reason they were disallowed.
38- pub fn create_disallowed_map (
100+ pub fn create_disallowed_map < const REPLACEMENT_ALLOWED : bool > (
39101 tcx : TyCtxt < ' _ > ,
40- disallowed : & ' static [ DisallowedPath ] ,
41- ) -> DefIdMap < ( & ' static str , Option < & ' static str > ) > {
102+ disallowed : & ' static [ DisallowedPath < REPLACEMENT_ALLOWED > ] ,
103+ ) -> DefIdMap < ( & ' static str , & ' static DisallowedPath < REPLACEMENT_ALLOWED > ) > {
42104 disallowed
43105 . iter ( )
44- . map ( |x| ( x. path ( ) , x. path ( ) . split ( "::" ) . collect :: < Vec < _ > > ( ) , x. reason ( ) ) )
45- . flat_map ( |( name, path, reason) | def_path_def_ids ( tcx, & path) . map ( move |id| ( id, ( name, reason) ) ) )
106+ . map ( |x| ( x. path ( ) , x. path ( ) . split ( "::" ) . collect :: < Vec < _ > > ( ) , x) )
107+ . flat_map ( |( name, path, disallowed_path) | {
108+ def_path_def_ids ( tcx, & path) . map ( move |id| ( id, ( name, disallowed_path) ) )
109+ } )
46110 . collect ( )
47111}
48112
@@ -436,7 +500,6 @@ macro_rules! unimplemented_serialize {
436500}
437501
438502unimplemented_serialize ! {
439- DisallowedPath ,
440503 Rename ,
441504 MacroMatcher ,
442505}
0 commit comments