@@ -18,6 +18,7 @@ use ich::{StableHashingContext, NodeIdHashingMode};
18
18
use util:: nodemap:: { FxHashMap , FxHashSet } ;
19
19
use ty;
20
20
21
+ use std:: fmt;
21
22
use std:: mem;
22
23
use std:: rc:: Rc ;
23
24
use syntax:: codemap;
@@ -31,6 +32,7 @@ use hir::def_id::DefId;
31
32
use hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
32
33
use hir:: { Block , Arm , Pat , PatKind , Stmt , Expr , Local } ;
33
34
use mir:: transform:: MirSource ;
35
+ use rustc_data_structures:: indexed_vec:: Idx ;
34
36
use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher ,
35
37
StableHasherResult } ;
36
38
@@ -95,8 +97,24 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
95
97
/// placate the same deriving in `ty::FreeRegion`, but we may want to
96
98
/// actually attach a more meaningful ordering to scopes than the one
97
99
/// generated via deriving here.
100
+ ///
101
+ /// Scope is a bit-packed to save space - if `code` is SCOPE_DATA_REMAINDER_MAX
102
+ /// or less, it is a `ScopeData::Remainder`, otherwise it is a type specified
103
+ /// by the bitpacking.
104
+ #[ derive( Clone , PartialEq , PartialOrd , Eq , Ord , Hash , Copy , RustcEncodable , RustcDecodable ) ]
105
+ pub struct Scope {
106
+ pub ( crate ) id : hir:: ItemLocalId ,
107
+ pub ( crate ) code : u32
108
+ }
109
+
110
+ const SCOPE_DATA_NODE : u32 = !0 ;
111
+ const SCOPE_DATA_CALLSITE : u32 = !1 ;
112
+ const SCOPE_DATA_ARGUMENTS : u32 = !2 ;
113
+ const SCOPE_DATA_DESTRUCTION : u32 = !3 ;
114
+ const SCOPE_DATA_REMAINDER_MAX : u32 = !4 ;
115
+
98
116
#[ derive( Clone , PartialEq , PartialOrd , Eq , Ord , Hash , Debug , Copy , RustcEncodable , RustcDecodable ) ]
99
- pub enum Scope {
117
+ pub enum ScopeData {
100
118
Node ( hir:: ItemLocalId ) ,
101
119
102
120
// Scope of the call-site for a function or closure
@@ -135,7 +153,90 @@ pub enum Scope {
135
153
RustcDecodable , Debug , Copy ) ]
136
154
pub struct BlockRemainder {
137
155
pub block : hir:: ItemLocalId ,
138
- pub first_statement_index : u32 ,
156
+ pub first_statement_index : FirstStatementIndex ,
157
+ }
158
+
159
+ #[ derive( Clone , PartialEq , PartialOrd , Eq , Ord , Hash , RustcEncodable ,
160
+ RustcDecodable , Copy ) ]
161
+ pub struct FirstStatementIndex { pub idx : u32 }
162
+
163
+ impl Idx for FirstStatementIndex {
164
+ fn new ( idx : usize ) -> Self {
165
+ assert ! ( idx <= SCOPE_DATA_REMAINDER_MAX as usize ) ;
166
+ FirstStatementIndex { idx : idx as u32 }
167
+ }
168
+
169
+ fn index ( self ) -> usize {
170
+ self . idx as usize
171
+ }
172
+ }
173
+
174
+ impl fmt:: Debug for FirstStatementIndex {
175
+ fn fmt ( & self , formatter : & mut fmt:: Formatter ) -> fmt:: Result {
176
+ fmt:: Debug :: fmt ( & self . index ( ) , formatter)
177
+ }
178
+ }
179
+
180
+ impl From < ScopeData > for Scope {
181
+ #[ inline]
182
+ fn from ( scope_data : ScopeData ) -> Self {
183
+ let ( id, code) = match scope_data {
184
+ ScopeData :: Node ( id) => ( id, SCOPE_DATA_NODE ) ,
185
+ ScopeData :: CallSite ( id) => ( id, SCOPE_DATA_CALLSITE ) ,
186
+ ScopeData :: Arguments ( id) => ( id, SCOPE_DATA_ARGUMENTS ) ,
187
+ ScopeData :: Destruction ( id) => ( id, SCOPE_DATA_DESTRUCTION ) ,
188
+ ScopeData :: Remainder ( r) => ( r. block , r. first_statement_index . index ( ) as u32 )
189
+ } ;
190
+ Self { id, code }
191
+ }
192
+ }
193
+
194
+ impl fmt:: Debug for Scope {
195
+ fn fmt ( & self , formatter : & mut fmt:: Formatter ) -> fmt:: Result {
196
+ fmt:: Debug :: fmt ( & self . data ( ) , formatter)
197
+ }
198
+ }
199
+
200
+ #[ allow( non_snake_case) ]
201
+ impl Scope {
202
+ #[ inline]
203
+ pub fn data ( self ) -> ScopeData {
204
+ match self . code {
205
+ SCOPE_DATA_NODE => ScopeData :: Node ( self . id ) ,
206
+ SCOPE_DATA_CALLSITE => ScopeData :: CallSite ( self . id ) ,
207
+ SCOPE_DATA_ARGUMENTS => ScopeData :: Arguments ( self . id ) ,
208
+ SCOPE_DATA_DESTRUCTION => ScopeData :: Destruction ( self . id ) ,
209
+ idx => ScopeData :: Remainder ( BlockRemainder {
210
+ block : self . id ,
211
+ first_statement_index : FirstStatementIndex { idx }
212
+ } )
213
+ }
214
+ }
215
+
216
+ #[ inline]
217
+ pub fn Node ( id : hir:: ItemLocalId ) -> Self {
218
+ Self :: from ( ScopeData :: Node ( id) )
219
+ }
220
+
221
+ #[ inline]
222
+ pub fn CallSite ( id : hir:: ItemLocalId ) -> Self {
223
+ Self :: from ( ScopeData :: CallSite ( id) )
224
+ }
225
+
226
+ #[ inline]
227
+ pub fn Arguments ( id : hir:: ItemLocalId ) -> Self {
228
+ Self :: from ( ScopeData :: Arguments ( id) )
229
+ }
230
+
231
+ #[ inline]
232
+ pub fn Destruction ( id : hir:: ItemLocalId ) -> Self {
233
+ Self :: from ( ScopeData :: Destruction ( id) )
234
+ }
235
+
236
+ #[ inline]
237
+ pub fn Remainder ( r : BlockRemainder ) -> Self {
238
+ Self :: from ( ScopeData :: Remainder ( r) )
239
+ }
139
240
}
140
241
141
242
impl Scope {
@@ -144,16 +245,7 @@ impl Scope {
144
245
/// NB: likely to be replaced as API is refined; e.g. pnkfelix
145
246
/// anticipates `fn entry_node_id` and `fn each_exit_node_id`.
146
247
pub fn item_local_id ( & self ) -> hir:: ItemLocalId {
147
- match * self {
148
- Scope :: Node ( id) => id,
149
-
150
- // These cases all return rough approximations to the
151
- // precise scope denoted by `self`.
152
- Scope :: Remainder ( br) => br. block ,
153
- Scope :: Destruction ( id) |
154
- Scope :: CallSite ( id) |
155
- Scope :: Arguments ( id) => id,
156
- }
248
+ self . id
157
249
}
158
250
159
251
pub fn node_id ( & self , tcx : TyCtxt , scope_tree : & ScopeTree ) -> ast:: NodeId {
@@ -177,7 +269,7 @@ impl Scope {
177
269
return DUMMY_SP ;
178
270
}
179
271
let span = tcx. hir . span ( node_id) ;
180
- if let Scope :: Remainder ( r) = * self {
272
+ if let ScopeData :: Remainder ( r) = self . data ( ) {
181
273
if let hir:: map:: NodeBlock ( ref blk) = tcx. hir . get ( node_id) {
182
274
// Want span for scope starting after the
183
275
// indexed statement and ending at end of
@@ -187,7 +279,7 @@ impl Scope {
187
279
// (This is the special case aluded to in the
188
280
// doc-comment for this method)
189
281
190
- let stmt_span = blk. stmts [ r. first_statement_index as usize ] . span ;
282
+ let stmt_span = blk. stmts [ r. first_statement_index . index ( ) ] . span ;
191
283
192
284
// To avoid issues with macro-generated spans, the span
193
285
// of the statement must be nested in that of the block.
@@ -387,7 +479,7 @@ impl<'tcx> ScopeTree {
387
479
}
388
480
389
481
// record the destruction scopes for later so we can query them
390
- if let Scope :: Destruction ( n) = child {
482
+ if let ScopeData :: Destruction ( n) = child. data ( ) {
391
483
self . destruction_scopes . insert ( n, child) ;
392
484
}
393
485
}
@@ -482,8 +574,8 @@ impl<'tcx> ScopeTree {
482
574
let mut id = Scope :: Node ( expr_id) ;
483
575
484
576
while let Some ( & p) = self . parent_map . get ( & id) {
485
- match p {
486
- Scope :: Destruction ( ..) => {
577
+ match p. data ( ) {
578
+ ScopeData :: Destruction ( ..) => {
487
579
debug ! ( "temporary_scope({:?}) = {:?} [enclosing]" ,
488
580
expr_id, id) ;
489
581
return Some ( id) ;
@@ -573,9 +665,9 @@ impl<'tcx> ScopeTree {
573
665
// infer::region_inference for more details.
574
666
let a_root_scope = a_ancestors[ a_index] ;
575
667
let b_root_scope = a_ancestors[ a_index] ;
576
- return match ( a_root_scope, b_root_scope) {
577
- ( Scope :: Destruction ( a_root_id) ,
578
- Scope :: Destruction ( b_root_id) ) => {
668
+ return match ( a_root_scope. data ( ) , b_root_scope. data ( ) ) {
669
+ ( ScopeData :: Destruction ( a_root_id) ,
670
+ ScopeData :: Destruction ( b_root_id) ) => {
579
671
if self . closure_is_enclosed_by ( a_root_id, b_root_id) {
580
672
// `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
581
673
scope_b
@@ -764,7 +856,7 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
764
856
visitor. enter_scope (
765
857
Scope :: Remainder ( BlockRemainder {
766
858
block : blk. hir_id . local_id ,
767
- first_statement_index : i as u32
859
+ first_statement_index : FirstStatementIndex :: new ( i )
768
860
} )
769
861
) ;
770
862
visitor. cx . var_parent = visitor. cx . parent ;
@@ -915,8 +1007,10 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
915
1007
// Keep traversing up while we can.
916
1008
match visitor. scope_tree . parent_map . get ( & scope) {
917
1009
// Don't cross from closure bodies to their parent.
918
- Some ( & Scope :: CallSite ( _) ) => break ,
919
- Some ( & superscope) => scope = superscope,
1010
+ Some ( & superscope) => match superscope. data ( ) {
1011
+ ScopeData :: CallSite ( _) => break ,
1012
+ _ => scope = superscope
1013
+ } ,
920
1014
None => break
921
1015
}
922
1016
}
0 commit comments