1
1
use crate :: { EarlyContext , EarlyLintPass , LintContext } ;
2
2
use rustc_ast:: ast;
3
3
use rustc_data_structures:: fx:: FxHashMap ;
4
- use rustc_span:: symbol:: SymbolStr ;
4
+ use rustc_span:: symbol:: Symbol ;
5
5
6
6
declare_lint ! {
7
7
pub NON_ASCII_IDENTS ,
@@ -39,7 +39,6 @@ impl EarlyLintPass for NonAsciiIdents {
39
39
use rustc_span:: Span ;
40
40
use std:: collections:: BTreeMap ;
41
41
use unicode_security:: GeneralSecurityProfile ;
42
- use utils:: CowBoxSymStr ;
43
42
44
43
let check_non_ascii_idents = cx. builder . lint_level ( NON_ASCII_IDENTS ) . 0 != Level :: Allow ;
45
44
let check_uncommon_codepoints =
@@ -58,6 +57,12 @@ impl EarlyLintPass for NonAsciiIdents {
58
57
59
58
let mut has_non_ascii_idents = false ;
60
59
let symbols = cx. sess . parse_sess . symbol_gallery . symbols . lock ( ) ;
60
+
61
+ // Sort by `Span` so that error messages make sense with respect to the
62
+ // order of identifier locations in the code.
63
+ let mut symbols: Vec < _ > = symbols. iter ( ) . collect ( ) ;
64
+ symbols. sort_by_key ( |k| k. 1 ) ;
65
+
61
66
for ( symbol, & sp) in symbols. iter ( ) {
62
67
let symbol_str = symbol. as_str ( ) ;
63
68
if symbol_str. is_ascii ( ) {
@@ -77,33 +82,34 @@ impl EarlyLintPass for NonAsciiIdents {
77
82
}
78
83
79
84
if has_non_ascii_idents && check_confusable_idents {
80
- let mut skeleton_map: FxHashMap < CowBoxSymStr , ( SymbolStr , Span , bool ) > =
85
+ let mut skeleton_map: FxHashMap < Symbol , ( Symbol , Span , bool ) > =
81
86
FxHashMap :: with_capacity_and_hasher ( symbols. len ( ) , Default :: default ( ) ) ;
82
- let mut str_buf = String :: new ( ) ;
83
- for ( symbol, & sp) in symbols. iter ( ) {
84
- fn calc_skeleton ( symbol_str : & SymbolStr , buffer : & mut String ) -> CowBoxSymStr {
85
- use std:: mem:: replace;
86
- use unicode_security:: confusable_detection:: skeleton;
87
- buffer. clear ( ) ;
88
- buffer. extend ( skeleton ( symbol_str) ) ;
89
- if * symbol_str == * buffer {
90
- CowBoxSymStr :: Interned ( symbol_str. clone ( ) )
91
- } else {
92
- let owned = replace ( buffer, String :: new ( ) ) ;
93
- CowBoxSymStr :: Owned ( owned. into_boxed_str ( ) )
94
- }
95
- }
87
+ let mut skeleton_buf = String :: new ( ) ;
88
+
89
+ for ( & symbol, & sp) in symbols. iter ( ) {
90
+ use unicode_security:: confusable_detection:: skeleton;
91
+
96
92
let symbol_str = symbol. as_str ( ) ;
97
93
let is_ascii = symbol_str. is_ascii ( ) ;
98
- let skeleton = calc_skeleton ( & symbol_str, & mut str_buf) ;
94
+
95
+ // Get the skeleton as a `Symbol`.
96
+ skeleton_buf. clear ( ) ;
97
+ skeleton_buf. extend ( skeleton ( & symbol_str) ) ;
98
+ let skeleton_sym = if * symbol_str == * skeleton_buf {
99
+ symbol
100
+ } else {
101
+ Symbol :: intern ( & skeleton_buf)
102
+ } ;
103
+
99
104
skeleton_map
100
- . entry ( skeleton )
101
- . and_modify ( |( existing_symbolstr , existing_span, existing_is_ascii) | {
105
+ . entry ( skeleton_sym )
106
+ . and_modify ( |( existing_symbol , existing_span, existing_is_ascii) | {
102
107
if !* existing_is_ascii || !is_ascii {
103
108
cx. struct_span_lint ( CONFUSABLE_IDENTS , sp, |lint| {
104
109
lint. build ( & format ! (
105
110
"identifier pair considered confusable between `{}` and `{}`" ,
106
- existing_symbolstr, symbol_str
111
+ existing_symbol. as_str( ) ,
112
+ symbol. as_str( )
107
113
) )
108
114
. span_label (
109
115
* existing_span,
@@ -113,12 +119,12 @@ impl EarlyLintPass for NonAsciiIdents {
113
119
} ) ;
114
120
}
115
121
if * existing_is_ascii && !is_ascii {
116
- * existing_symbolstr = symbol_str . clone ( ) ;
122
+ * existing_symbol = symbol ;
117
123
* existing_span = sp;
118
124
* existing_is_ascii = is_ascii;
119
125
}
120
126
} )
121
- . or_insert ( ( symbol_str , sp, is_ascii) ) ;
127
+ . or_insert ( ( symbol , sp, is_ascii) ) ;
122
128
}
123
129
}
124
130
@@ -232,41 +238,3 @@ impl EarlyLintPass for NonAsciiIdents {
232
238
}
233
239
}
234
240
}
235
-
236
- mod utils {
237
- use rustc_span:: symbol:: SymbolStr ;
238
- use std:: hash:: { Hash , Hasher } ;
239
- use std:: ops:: Deref ;
240
-
241
- pub ( super ) enum CowBoxSymStr {
242
- Interned ( SymbolStr ) ,
243
- Owned ( Box < str > ) ,
244
- }
245
-
246
- impl Deref for CowBoxSymStr {
247
- type Target = str ;
248
-
249
- fn deref ( & self ) -> & str {
250
- match self {
251
- CowBoxSymStr :: Interned ( interned) => interned,
252
- CowBoxSymStr :: Owned ( ref owned) => owned,
253
- }
254
- }
255
- }
256
-
257
- impl Hash for CowBoxSymStr {
258
- #[ inline]
259
- fn hash < H : Hasher > ( & self , state : & mut H ) {
260
- Hash :: hash ( & * * self , state)
261
- }
262
- }
263
-
264
- impl PartialEq < CowBoxSymStr > for CowBoxSymStr {
265
- #[ inline]
266
- fn eq ( & self , other : & CowBoxSymStr ) -> bool {
267
- PartialEq :: eq ( & * * self , & * * other)
268
- }
269
- }
270
-
271
- impl Eq for CowBoxSymStr { }
272
- }
0 commit comments