1
1
use clippy_utils:: def_path_def_ids;
2
+ use rustc_errors:: { Applicability , Diag } ;
2
3
use rustc_hir:: def_id:: DefIdMap ;
3
4
use rustc_middle:: ty:: TyCtxt ;
5
+ use rustc_span:: Span ;
4
6
use serde:: de:: { self , Deserializer , Visitor } ;
5
7
use serde:: { Deserialize , Serialize , ser} ;
6
8
use std:: collections:: HashMap ;
@@ -12,37 +14,99 @@ pub struct Rename {
12
14
pub rename : String ,
13
15
}
14
16
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 ) ]
16
46
#[ serde( untagged) ]
17
- pub enum DisallowedPath {
47
+ enum DisallowedPathEnum {
18
48
Simple ( String ) ,
19
- WithReason { path : String , reason : Option < String > } ,
49
+ WithReason {
50
+ path : String ,
51
+ reason : Option < String > ,
52
+ replacement : Option < String > ,
53
+ } ,
20
54
}
21
55
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 {
23
78
pub fn path ( & self ) -> & str {
24
79
let ( Self :: Simple ( path) | Self :: WithReason { path, .. } ) = self ;
25
80
26
81
path
27
82
}
28
83
29
- pub fn reason ( & self ) -> Option < & str > {
84
+ fn reason ( & self ) -> Option < & str > {
30
85
match & self {
31
86
Self :: WithReason { reason, .. } => reason. as_deref ( ) ,
32
87
Self :: Simple ( _) => None ,
33
88
}
34
89
}
90
+
91
+ fn replacement ( & self ) -> Option < & str > {
92
+ match & self {
93
+ Self :: WithReason { replacement, .. } => replacement. as_deref ( ) ,
94
+ Self :: Simple ( _) => None ,
95
+ }
96
+ }
35
97
}
36
98
37
99
/// 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 > (
39
101
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 > ) > {
42
104
disallowed
43
105
. 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
+ } )
46
110
. collect ( )
47
111
}
48
112
@@ -436,7 +500,6 @@ macro_rules! unimplemented_serialize {
436
500
}
437
501
438
502
unimplemented_serialize ! {
439
- DisallowedPath ,
440
503
Rename ,
441
504
MacroMatcher ,
442
505
}
0 commit comments