44// The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd.
55// See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28
66
7- use crate :: GLOBALS ;
87use crate :: { BytePos , SpanData } ;
98use crate :: hygiene:: SyntaxContext ;
109
1110use rustc_data_structures:: fx:: FxHashMap ;
12- use std:: hash:: { Hash , Hasher } ;
1311
1412/// A compressed span.
1513/// Contains either fields of `SpanData` inline if they are small, or index into span interner.
1614/// The primary goal of `Span` is to be as small as possible and fit into other structures
1715/// (that's why it uses `packed` as well). Decoding speed is the second priority.
1816/// See `SpanData` for the info on span fields in decoded representation.
19- #[ repr ( packed ) ]
17+ #[ derive ( Clone , Copy , Eq , PartialEq , Hash ) ]
2018pub struct Span ( u32 ) ;
2119
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-
4620/// Dummy span, both position and length are zero, syntax context is zero as well.
4721/// This span is kept inline and encoded with format 0.
4822pub const DUMMY_SP : Span = Span ( 0 ) ;
@@ -98,7 +72,7 @@ fn encode(sd: &SpanData) -> Span {
9872 ( base << INLINE_OFFSETS [ BASE_INDEX ] ) | ( len << INLINE_OFFSETS [ LEN_INDEX ] ) |
9973 ( ctxt << INLINE_OFFSETS [ CTXT_INDEX ] ) | TAG_INLINE
10074 } else {
101- let index = with_span_interner ( |interner| interner . intern ( sd) ) ;
75+ let index = unsafe { ( * SPAN_INTERNER_BACKDOOR ) . intern ( sd) } ;
10276 ( index << INTERNED_INDEX_OFFSET ) | TAG_INTERNED
10377 } ;
10478 Span ( val)
@@ -109,7 +83,7 @@ fn decode(span: Span) -> SpanData {
10983 let val = span. 0 ;
11084
11185 // Extract a field at position `pos` having size `size`.
112- let extract = |pos : u32 , size : u32 | {
86+ let extract = # [ inline ] |pos: u32, size: u32| {
11387 let mask = ( ( !0u32 ) as u64 >> ( 32 - size) ) as u32 ; // Can't shift u32 by 32
11488 ( val >> pos) & mask
11589 } ;
@@ -120,7 +94,7 @@ fn decode(span: Span) -> SpanData {
12094 extract ( INLINE_OFFSETS [ CTXT_INDEX ] , INLINE_SIZES [ CTXT_INDEX ] ) ,
12195 ) } else {
12296 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) } ;
12498 } ;
12599 SpanData { lo : BytePos ( base) , hi : BytePos ( base + len) , ctxt : SyntaxContext :: from_u32 ( ctxt) }
126100}
@@ -149,8 +123,4 @@ impl SpanInterner {
149123 }
150124}
151125
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