4
4
// The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd.
5
5
// See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28
6
6
7
- use crate :: GLOBALS ;
8
7
use crate :: { BytePos , SpanData } ;
9
8
use crate :: hygiene:: SyntaxContext ;
10
9
11
10
use rustc_data_structures:: fx:: FxHashMap ;
12
- use std:: hash:: { Hash , Hasher } ;
13
11
14
12
/// A compressed span.
15
13
/// Contains either fields of `SpanData` inline if they are small, or index into span interner.
16
14
/// The primary goal of `Span` is to be as small as possible and fit into other structures
17
15
/// (that's why it uses `packed` as well). Decoding speed is the second priority.
18
16
/// See `SpanData` for the info on span fields in decoded representation.
19
- #[ repr ( packed ) ]
17
+ #[ derive ( Clone , Copy , Eq , PartialEq , Hash ) ]
20
18
pub struct Span ( u32 ) ;
21
19
22
- impl Copy for Span { }
23
- impl Clone for Span {
24
- #[ inline]
25
- fn clone ( & self ) -> Span {
26
- * self
27
- }
28
- }
29
- impl PartialEq for Span {
30
- #[ inline]
31
- fn eq ( & self , other : & Span ) -> bool {
32
- let a = self . 0 ;
33
- let b = other. 0 ;
34
- a == b
35
- }
36
- }
37
- impl Eq for Span { }
38
- impl Hash for Span {
39
- #[ inline]
40
- fn hash < H : Hasher > ( & self , state : & mut H ) {
41
- let a = self . 0 ;
42
- a. hash ( state)
43
- }
44
- }
45
-
46
20
/// Dummy span, both position and length are zero, syntax context is zero as well.
47
21
/// This span is kept inline and encoded with format 0.
48
22
pub const DUMMY_SP : Span = Span ( 0 ) ;
@@ -98,7 +72,7 @@ fn encode(sd: &SpanData) -> Span {
98
72
( base << INLINE_OFFSETS [ BASE_INDEX ] ) | ( len << INLINE_OFFSETS [ LEN_INDEX ] ) |
99
73
( ctxt << INLINE_OFFSETS [ CTXT_INDEX ] ) | TAG_INLINE
100
74
} else {
101
- let index = with_span_interner ( |interner| interner . intern ( sd) ) ;
75
+ let index = unsafe { ( * SPAN_INTERNER_BACKDOOR ) . intern ( sd) } ;
102
76
( index << INTERNED_INDEX_OFFSET ) | TAG_INTERNED
103
77
} ;
104
78
Span ( val)
@@ -109,7 +83,7 @@ fn decode(span: Span) -> SpanData {
109
83
let val = span. 0 ;
110
84
111
85
// Extract a field at position `pos` having size `size`.
112
- let extract = |pos : u32 , size : u32 | {
86
+ let extract = # [ inline ] |pos: u32, size: u32| {
113
87
let mask = ( ( !0u32 ) as u64 >> ( 32 - size) ) as u32 ; // Can't shift u32 by 32
114
88
( val >> pos) & mask
115
89
} ;
@@ -120,7 +94,7 @@ fn decode(span: Span) -> SpanData {
120
94
extract ( INLINE_OFFSETS [ CTXT_INDEX ] , INLINE_SIZES [ CTXT_INDEX ] ) ,
121
95
) } else {
122
96
let index = extract ( INTERNED_INDEX_OFFSET , INTERNED_INDEX_SIZE ) ;
123
- return with_span_interner ( |interner| * interner . get ( index) ) ;
97
+ return unsafe { * ( * SPAN_INTERNER_BACKDOOR ) . get ( index) } ;
124
98
} ;
125
99
SpanData { lo : BytePos ( base) , hi : BytePos ( base + len) , ctxt : SyntaxContext :: from_u32 ( ctxt) }
126
100
}
@@ -149,8 +123,4 @@ impl SpanInterner {
149
123
}
150
124
}
151
125
152
- // If an interner exists, return it. Otherwise, prepare a fresh one.
153
- #[ inline]
154
- fn with_span_interner < T , F : FnOnce ( & mut SpanInterner ) -> T > ( f : F ) -> T {
155
- GLOBALS . with ( |globals| f ( & mut * globals. span_interner . lock ( ) ) )
156
- }
126
+ pub static mut SPAN_INTERNER_BACKDOOR : * mut SpanInterner = std:: ptr:: null_mut ( ) ;
0 commit comments