@@ -60,6 +60,8 @@ pub enum constness {
60
60
non_const
61
61
}
62
62
63
+ type constness_cache = HashMap < ast:: DefId , constness > ;
64
+
63
65
pub fn join ( a : constness , b : constness ) -> constness {
64
66
match ( a, b) {
65
67
( integral_const, integral_const) => integral_const,
@@ -74,102 +76,12 @@ pub fn join_all<It: Iterator<constness>>(mut cs: It) -> constness {
74
76
cs. fold ( integral_const, |a, b| join ( a, b) )
75
77
}
76
78
77
- pub fn classify ( e : & Expr ,
78
- tcx : ty:: ctxt )
79
- -> constness {
80
- let did = ast_util:: local_def ( e. id ) ;
81
- match tcx. ccache . find ( & did) {
82
- Some ( & x) => x,
83
- None => {
84
- let cn =
85
- match e. node {
86
- ast:: ExprLit ( lit) => {
87
- match lit. node {
88
- ast:: lit_str( * ) |
89
- ast:: lit_float( * ) => general_const,
90
- _ => integral_const
91
- }
92
- }
93
-
94
- ast:: ExprUnary ( _, _, inner) |
95
- ast:: ExprParen ( inner) => {
96
- classify ( inner, tcx)
97
- }
98
-
99
- ast:: ExprBinary ( _, _, a, b) => {
100
- join ( classify ( a, tcx) ,
101
- classify ( b, tcx) )
102
- }
103
-
104
- ast:: ExprTup ( ref es) |
105
- ast:: ExprVec ( ref es, ast:: MutImmutable ) => {
106
- join_all ( es. iter ( ) . map ( |e| classify ( * e, tcx) ) )
107
- }
108
-
109
- ast:: ExprVstore ( e, vstore) => {
110
- match vstore {
111
- ast:: ExprVstoreSlice => classify ( e, tcx) ,
112
- ast:: ExprVstoreUniq |
113
- ast:: ExprVstoreBox |
114
- ast:: ExprVstoreMutBox |
115
- ast:: ExprVstoreMutSlice => non_const
116
- }
117
- }
118
-
119
- ast:: ExprStruct ( _, ref fs, None ) => {
120
- let cs = do fs. iter ( ) . map |f| {
121
- classify ( f. expr , tcx)
122
- } ;
123
- join_all ( cs)
124
- }
125
-
126
- ast:: ExprCast ( base, _) => {
127
- let ty = ty:: expr_ty ( tcx, e) ;
128
- let base = classify ( base, tcx) ;
129
- if ty:: type_is_integral ( ty) {
130
- join ( integral_const, base)
131
- } else if ty:: type_is_fp ( ty) {
132
- join ( general_const, base)
133
- } else {
134
- non_const
135
- }
136
- }
137
-
138
- ast:: ExprField ( base, _, _) => {
139
- classify ( base, tcx)
140
- }
141
-
142
- ast:: ExprIndex ( _, base, idx) => {
143
- join ( classify ( base, tcx) ,
144
- classify ( idx, tcx) )
145
- }
146
-
147
- ast:: ExprAddrOf ( ast:: MutImmutable , base) => {
148
- classify ( base, tcx)
149
- }
150
-
151
- // FIXME: (#3728) we can probably do something CCI-ish
152
- // surrounding nonlocal constants. But we don't yet.
153
- ast:: ExprPath ( _) => {
154
- lookup_constness ( tcx, e)
155
- }
156
-
157
- ast:: ExprRepeat ( * ) => general_const,
158
-
159
- _ => non_const
160
- } ;
161
- tcx. ccache . insert ( did, cn) ;
162
- cn
163
- }
164
- }
165
- }
166
-
167
79
pub fn lookup_const ( tcx : ty:: ctxt , e : & Expr ) -> Option < @Expr > {
168
80
match tcx. def_map . find ( & e. id ) {
169
- Some ( & ast:: DefStatic ( def_id, false ) ) => lookup_const_by_id ( tcx , def_id ) ,
170
- Some ( & ast :: DefVariant ( enum_def , variant_def , _ ) ) => lookup_variant_by_id ( tcx,
171
- enum_def ,
172
- variant_def) ,
81
+ Some ( & ast:: DefStatic ( def_id, false ) ) =>
82
+ lookup_const_by_id ( tcx, def_id ) ,
83
+ Some ( & ast :: DefVariant ( enum_def , variant_def , _ ) ) =>
84
+ lookup_variant_by_id ( tcx , enum_def , variant_def) ,
173
85
_ => None
174
86
}
175
87
}
@@ -199,14 +111,18 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
199
111
Some ( _) => None
200
112
}
201
113
} else {
114
+ match tcx. extern_const_variants . find ( & variant_def) {
115
+ Some ( & e) => return e,
116
+ None => { }
117
+ }
202
118
let maps = astencode:: Maps {
203
119
root_map : @mut HashMap :: new ( ) ,
204
120
method_map : @mut HashMap :: new ( ) ,
205
121
vtable_map : @mut HashMap :: new ( ) ,
206
122
write_guard_map : @mut HashSet :: new ( ) ,
207
123
capture_map : @mut HashMap :: new ( )
208
124
} ;
209
- match csearch:: maybe_get_item_ast ( tcx, enum_def,
125
+ let e = match csearch:: maybe_get_item_ast ( tcx, enum_def,
210
126
|a, b, c, d| astencode:: decode_inlined_item ( a,
211
127
b,
212
128
maps,
@@ -219,7 +135,9 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
219
135
_ => None
220
136
} ,
221
137
_ => None
222
- }
138
+ } ;
139
+ tcx. extern_const_variants . insert ( variant_def, e) ;
140
+ return e;
223
141
}
224
142
}
225
143
@@ -236,49 +154,136 @@ pub fn lookup_const_by_id(tcx: ty::ctxt,
236
154
Some ( _) => None
237
155
}
238
156
} else {
157
+ match tcx. extern_const_statics . find ( & def_id) {
158
+ Some ( & e) => return e,
159
+ None => { }
160
+ }
239
161
let maps = astencode:: Maps {
240
162
root_map : @mut HashMap :: new ( ) ,
241
163
method_map : @mut HashMap :: new ( ) ,
242
164
vtable_map : @mut HashMap :: new ( ) ,
243
165
write_guard_map : @mut HashSet :: new ( ) ,
244
166
capture_map : @mut HashMap :: new ( )
245
167
} ;
246
- match csearch:: maybe_get_item_ast ( tcx, def_id,
168
+ let e = match csearch:: maybe_get_item_ast ( tcx, def_id,
247
169
|a, b, c, d| astencode:: decode_inlined_item ( a, b, maps, c, d) ) {
248
170
csearch:: found( ast:: ii_item( item) ) => match item. node {
249
171
item_static( _, ast:: MutImmutable , const_expr) => Some ( const_expr) ,
250
172
_ => None
251
173
} ,
252
174
_ => None
253
- }
175
+ } ;
176
+ tcx. extern_const_statics . insert ( def_id, e) ;
177
+ return e;
254
178
}
255
179
}
256
180
257
- pub fn lookup_constness ( tcx : ty:: ctxt , e : & Expr ) -> constness {
258
- match lookup_const ( tcx, e) {
259
- Some ( rhs) => {
260
- let ty = ty:: expr_ty ( tcx, rhs) ;
261
- if ty:: type_is_integral ( ty) {
262
- integral_const
263
- } else {
264
- general_const
181
+ struct ConstEvalVisitor {
182
+ tcx : ty:: ctxt ,
183
+ ccache : constness_cache ,
184
+ }
185
+
186
+ impl ConstEvalVisitor {
187
+ fn classify ( & mut self , e : & Expr ) -> constness {
188
+ let did = ast_util:: local_def ( e. id ) ;
189
+ match self . ccache . find ( & did) {
190
+ Some ( & x) => return x,
191
+ None => { }
192
+ }
193
+ let cn = match e. node {
194
+ ast:: ExprLit ( lit) => {
195
+ match lit. node {
196
+ ast:: lit_str( * ) | ast:: lit_float( * ) => general_const,
197
+ _ => integral_const
198
+ }
199
+ }
200
+
201
+ ast:: ExprUnary ( _, _, inner) | ast:: ExprParen ( inner) =>
202
+ self . classify ( inner) ,
203
+
204
+ ast:: ExprBinary ( _, _, a, b) =>
205
+ join ( self . classify ( a) , self . classify ( b) ) ,
206
+
207
+ ast:: ExprTup ( ref es) |
208
+ ast:: ExprVec ( ref es, ast:: MutImmutable ) =>
209
+ join_all ( es. iter ( ) . map ( |e| self . classify ( * e) ) ) ,
210
+
211
+ ast:: ExprVstore ( e, vstore) => {
212
+ match vstore {
213
+ ast:: ExprVstoreSlice => self . classify ( e) ,
214
+ ast:: ExprVstoreUniq |
215
+ ast:: ExprVstoreBox |
216
+ ast:: ExprVstoreMutBox |
217
+ ast:: ExprVstoreMutSlice => non_const
218
+ }
219
+ }
220
+
221
+ ast:: ExprStruct ( _, ref fs, None ) => {
222
+ let cs = do fs. iter ( ) . map |f| {
223
+ self . classify ( f. expr )
224
+ } ;
225
+ join_all ( cs)
226
+ }
227
+
228
+ ast:: ExprCast ( base, _) => {
229
+ let ty = ty:: expr_ty ( self . tcx , e) ;
230
+ let base = self . classify ( base) ;
231
+ if ty:: type_is_integral ( ty) {
232
+ join ( integral_const, base)
233
+ } else if ty:: type_is_fp ( ty) {
234
+ join ( general_const, base)
235
+ } else {
236
+ non_const
237
+ }
238
+ }
239
+
240
+ ast:: ExprField ( base, _, _) => self . classify ( base) ,
241
+
242
+ ast:: ExprIndex ( _, base, idx) =>
243
+ join ( self . classify ( base) , self . classify ( idx) ) ,
244
+
245
+ ast:: ExprAddrOf ( ast:: MutImmutable , base) => self . classify ( base) ,
246
+
247
+ // FIXME: (#3728) we can probably do something CCI-ish
248
+ // surrounding nonlocal constants. But we don't yet.
249
+ ast:: ExprPath ( _) => self . lookup_constness ( e) ,
250
+
251
+ ast:: ExprRepeat ( * ) => general_const,
252
+
253
+ _ => non_const
254
+ } ;
255
+ self . ccache . insert ( did, cn) ;
256
+ cn
257
+ }
258
+
259
+ fn lookup_constness ( & self , e : & Expr ) -> constness {
260
+ match lookup_const ( self . tcx , e) {
261
+ Some ( rhs) => {
262
+ let ty = ty:: expr_ty ( self . tcx , rhs) ;
263
+ if ty:: type_is_integral ( ty) {
264
+ integral_const
265
+ } else {
266
+ general_const
267
+ }
265
268
}
269
+ None => non_const
266
270
}
267
- None => non_const
268
271
}
269
- }
270
272
271
- struct ConstEvalVisitor { tcx : ty :: ctxt }
273
+ }
272
274
273
275
impl Visitor < ( ) > for ConstEvalVisitor {
274
276
fn visit_expr_post ( & mut self , e : @Expr , _: ( ) ) {
275
- classify ( e, self . tcx ) ;
277
+ self . classify ( e) ;
276
278
}
277
279
}
278
280
279
281
pub fn process_crate ( crate : & ast:: Crate ,
280
282
tcx : ty:: ctxt ) {
281
- let mut v = ConstEvalVisitor { tcx : tcx } ;
283
+ let mut v = ConstEvalVisitor {
284
+ tcx : tcx,
285
+ ccache : HashMap :: new ( ) ,
286
+ } ;
282
287
visit:: walk_crate ( & mut v, crate , ( ) ) ;
283
288
tcx. sess . abort_if_errors ( ) ;
284
289
}
0 commit comments