2
2
use std:: sync:: Arc ;
3
3
4
4
use hir_expand:: name:: Name ;
5
- use la_arena:: { Arena , Idx } ;
5
+ use la_arena:: { Arena , Idx , IdxRange , RawIdx } ;
6
6
use rustc_hash:: FxHashMap ;
7
7
8
8
use crate :: {
@@ -17,6 +17,7 @@ pub type ScopeId = Idx<ScopeData>;
17
17
#[ derive( Debug , PartialEq , Eq ) ]
18
18
pub struct ExprScopes {
19
19
scopes : Arena < ScopeData > ,
20
+ scope_entries : Arena < ScopeEntry > ,
20
21
scope_by_expr : FxHashMap < ExprId , ScopeId > ,
21
22
}
22
23
@@ -41,7 +42,7 @@ pub struct ScopeData {
41
42
parent : Option < ScopeId > ,
42
43
block : Option < BlockId > ,
43
44
label : Option < ( LabelId , Name ) > ,
44
- entries : Vec < ScopeEntry > ,
45
+ entries : IdxRange < ScopeEntry > ,
45
46
}
46
47
47
48
impl ExprScopes {
@@ -53,7 +54,7 @@ impl ExprScopes {
53
54
}
54
55
55
56
pub fn entries ( & self , scope : ScopeId ) -> & [ ScopeEntry ] {
56
- & self . scopes [ scope] . entries
57
+ & self . scope_entries [ self . scopes [ scope] . entries . clone ( ) ]
57
58
}
58
59
59
60
/// If `scope` refers to a block expression scope, returns the corresponding `BlockId`.
@@ -85,31 +86,48 @@ impl ExprScopes {
85
86
}
86
87
}
87
88
89
+ fn empty_entries ( idx : usize ) -> IdxRange < ScopeEntry > {
90
+ IdxRange :: new ( Idx :: from_raw ( RawIdx :: from ( idx as u32 ) ) ..Idx :: from_raw ( RawIdx :: from ( idx as u32 ) ) )
91
+ }
92
+
88
93
impl ExprScopes {
89
94
fn new ( body : & Body ) -> ExprScopes {
90
- let mut scopes =
91
- ExprScopes { scopes : Arena :: default ( ) , scope_by_expr : FxHashMap :: default ( ) } ;
95
+ let mut scopes = ExprScopes {
96
+ scopes : Arena :: default ( ) ,
97
+ scope_entries : Arena :: default ( ) ,
98
+ scope_by_expr : FxHashMap :: default ( ) ,
99
+ } ;
92
100
let mut root = scopes. root_scope ( ) ;
93
101
scopes. add_params_bindings ( body, root, & body. params ) ;
94
102
compute_expr_scopes ( body. body_expr , body, & mut scopes, & mut root) ;
95
103
scopes
96
104
}
97
105
98
106
fn root_scope ( & mut self ) -> ScopeId {
99
- self . scopes . alloc ( ScopeData { parent : None , block : None , label : None , entries : vec ! [ ] } )
107
+ self . scopes . alloc ( ScopeData {
108
+ parent : None ,
109
+ block : None ,
110
+ label : None ,
111
+ entries : empty_entries ( self . scope_entries . len ( ) ) ,
112
+ } )
100
113
}
101
114
102
115
fn new_scope ( & mut self , parent : ScopeId ) -> ScopeId {
103
116
self . scopes . alloc ( ScopeData {
104
117
parent : Some ( parent) ,
105
118
block : None ,
106
119
label : None ,
107
- entries : vec ! [ ] ,
120
+ entries : empty_entries ( self . scope_entries . len ( ) ) ,
108
121
} )
109
122
}
110
123
111
124
fn new_labeled_scope ( & mut self , parent : ScopeId , label : Option < ( LabelId , Name ) > ) -> ScopeId {
112
- self . scopes . alloc ( ScopeData { parent : Some ( parent) , block : None , label, entries : vec ! [ ] } )
125
+ self . scopes . alloc ( ScopeData {
126
+ parent : Some ( parent) ,
127
+ block : None ,
128
+ label,
129
+ entries : empty_entries ( self . scope_entries . len ( ) ) ,
130
+ } )
113
131
}
114
132
115
133
fn new_block_scope (
@@ -118,13 +136,19 @@ impl ExprScopes {
118
136
block : Option < BlockId > ,
119
137
label : Option < ( LabelId , Name ) > ,
120
138
) -> ScopeId {
121
- self . scopes . alloc ( ScopeData { parent : Some ( parent) , block, label, entries : vec ! [ ] } )
139
+ self . scopes . alloc ( ScopeData {
140
+ parent : Some ( parent) ,
141
+ block,
142
+ label,
143
+ entries : empty_entries ( self . scope_entries . len ( ) ) ,
144
+ } )
122
145
}
123
146
124
147
fn add_bindings ( & mut self , body : & Body , scope : ScopeId , binding : BindingId ) {
125
148
let Binding { name, .. } = & body. bindings [ binding] ;
126
- let entry = ScopeEntry { name : name. clone ( ) , binding } ;
127
- self . scopes [ scope] . entries . push ( entry) ;
149
+ let entry = self . scope_entries . alloc ( ScopeEntry { name : name. clone ( ) , binding } ) ;
150
+ self . scopes [ scope] . entries =
151
+ IdxRange :: new_inclusive ( self . scopes [ scope] . entries . start ( ) ..=entry) ;
128
152
}
129
153
130
154
fn add_pat_bindings ( & mut self , body : & Body , scope : ScopeId , pat : PatId ) {
@@ -145,9 +169,9 @@ impl ExprScopes {
145
169
}
146
170
147
171
fn shrink_to_fit ( & mut self ) {
148
- let ExprScopes { scopes, scope_by_expr } = self ;
172
+ let ExprScopes { scopes, scope_entries , scope_by_expr } = self ;
149
173
scopes. shrink_to_fit ( ) ;
150
- scopes . values_mut ( ) . for_each ( |it| it . entries . shrink_to_fit ( ) ) ;
174
+ scope_entries . shrink_to_fit ( ) ;
151
175
scope_by_expr. shrink_to_fit ( ) ;
152
176
}
153
177
}
0 commit comments