1
- use syntax:: { ast, ast_util, visit} ;
1
+ use syntax:: { ast, ast_map , ast_util, visit} ;
2
2
use ast:: * ;
3
3
4
4
//
@@ -135,28 +135,7 @@ fn classify(e: @expr,
135
135
// FIXME: (#3728) we can probably do something CCI-ish
136
136
// surrounding nonlocal constants. But we don't yet.
137
137
ast:: expr_path( _) => {
138
- match def_map. find ( e. id ) {
139
- Some ( ast:: def_const( def_id) ) => {
140
- if ast_util:: is_local ( def_id) {
141
- let ty = ty:: expr_ty ( tcx, e) ;
142
- if ty:: type_is_integral ( ty) {
143
- integral_const
144
- } else {
145
- general_const
146
- }
147
- } else {
148
- non_const
149
- }
150
- }
151
- Some ( _) => {
152
- non_const
153
- }
154
- None => {
155
- tcx. sess . span_bug ( e. span ,
156
- ~"unknown path when \
157
- classifying constants") ;
158
- }
159
- }
138
+ lookup_constness ( tcx, e)
160
139
}
161
140
162
141
_ => non_const
@@ -167,6 +146,40 @@ fn classify(e: @expr,
167
146
}
168
147
}
169
148
149
+ fn lookup_const( tcx : ty:: ctxt , e: @expr) -> Option <@expr> {
150
+ match tcx. def_map . find ( e. id ) {
151
+ Some ( ast:: def_const( def_id) ) => {
152
+ if ast_util:: is_local ( def_id) {
153
+ match tcx. items . find ( def_id. node ) {
154
+ None => None ,
155
+ Some ( ast_map:: node_item( it, _) ) => match it. node {
156
+ item_const( _, const_expr) => Some ( const_expr) ,
157
+ _ => None
158
+ } ,
159
+ Some ( _) => None
160
+ }
161
+ }
162
+ else { None }
163
+ }
164
+ Some ( _) => None ,
165
+ None => None
166
+ }
167
+ }
168
+
169
+ fn lookup_constness ( tcx : ty:: ctxt , e: @expr) -> constness {
170
+ match lookup_const ( tcx, e) {
171
+ Some ( rhs) => {
172
+ let ty = ty:: expr_ty ( tcx, rhs) ;
173
+ if ty:: type_is_integral ( ty) {
174
+ integral_const
175
+ } else {
176
+ general_const
177
+ }
178
+ }
179
+ None => non_const
180
+ }
181
+ }
182
+
170
183
fn process_crate ( crate : @ast:: crate ,
171
184
def_map : resolve:: DefMap ,
172
185
tcx : ty:: ctxt ) {
@@ -204,58 +217,67 @@ impl const_val : cmp::Eq {
204
217
pure fn ne ( other : & const_val ) -> bool { !self . eq ( other) }
205
218
}
206
219
207
- // FIXME: issue #1417
208
220
fn eval_const_expr ( tcx : middle:: ty:: ctxt , e: @expr) -> const_val {
221
+ match eval_const_expr_partial ( tcx, e) {
222
+ Ok ( r) => r,
223
+ Err ( s) => fail s
224
+ }
225
+ }
226
+
227
+ fn eval_const_expr_partial( tcx : middle:: ty:: ctxt , e: @expr)
228
+ -> Result < const_val , ~str > {
209
229
use middle:: ty;
210
- fn fromb ( b : bool ) -> const_val { const_int ( b as i64 ) }
230
+ fn fromb ( b : bool ) -> Result < const_val , ~ str > { Ok ( const_int ( b as i64 ) ) }
211
231
match e. node {
212
232
expr_unary( neg, inner) => {
213
- match eval_const_expr ( tcx, inner) {
214
- const_float( f) => const_float ( -f) ,
215
- const_int( i) => const_int ( -i) ,
216
- const_uint( i) => const_uint ( -i) ,
217
- const_str( _) => fail ~"Negate on string",
218
- const_bool( _) => fail ~"Negate on boolean"
233
+ match eval_const_expr_partial ( tcx, inner) {
234
+ Ok ( const_float( f) ) => Ok ( const_float ( -f) ) ,
235
+ Ok ( const_int( i) ) => Ok ( const_int ( -i) ) ,
236
+ Ok ( const_uint( i) ) => Ok ( const_uint ( -i) ) ,
237
+ Ok ( const_str( _) ) => Err ( ~"Negate on string") ,
238
+ Ok ( const_bool( _) ) => Err ( ~"Negate on boolean") ,
239
+ err => err
219
240
}
220
241
}
221
242
expr_unary( not, inner) => {
222
- match eval_const_expr ( tcx, inner) {
223
- const_int( i) => const_int ( !i) ,
224
- const_uint( i) => const_uint ( !i) ,
225
- const_bool( b) => const_bool ( !b) ,
226
- _ => fail ~"Not on float or string"
243
+ match eval_const_expr_partial ( tcx, inner) {
244
+ Ok ( const_int( i) ) => Ok ( const_int ( !i) ) ,
245
+ Ok ( const_uint( i) ) => Ok ( const_uint ( !i) ) ,
246
+ Ok ( const_bool( b) ) => Ok ( const_bool ( !b) ) ,
247
+ _ => Err ( ~"Not on float or string")
227
248
}
228
249
}
229
250
expr_binary( op, a, b) => {
230
- match ( eval_const_expr ( tcx, a) , eval_const_expr ( tcx, b) ) {
231
- ( const_float( a) , const_float( b) ) => {
251
+ match ( eval_const_expr_partial ( tcx, a) ,
252
+ eval_const_expr_partial ( tcx, b) ) {
253
+ ( Ok ( const_float( a) ) , Ok ( const_float( b) ) ) => {
232
254
match op {
233
- add => const_float ( a + b) ,
234
- subtract => const_float ( a - b) ,
235
- mul => const_float ( a * b) ,
236
- div => const_float ( a / b) ,
237
- rem => const_float ( a % b) ,
255
+ add => Ok ( const_float ( a + b) ) ,
256
+ subtract => Ok ( const_float ( a - b) ) ,
257
+ mul => Ok ( const_float ( a * b) ) ,
258
+ div => Ok ( const_float ( a / b) ) ,
259
+ rem => Ok ( const_float ( a % b) ) ,
238
260
eq => fromb ( a == b) ,
239
261
lt => fromb ( a < b) ,
240
262
le => fromb ( a <= b) ,
241
263
ne => fromb ( a != b) ,
242
264
ge => fromb ( a >= b) ,
243
265
gt => fromb ( a > b) ,
244
- _ => fail ~"Can ' t do this op on floats"
266
+ _ => Err ( ~"Can ' t do this op on floats")
245
267
}
246
268
}
247
- ( const_int( a) , const_int( b) ) => {
269
+ ( Ok ( const_int( a) ) , Ok ( const_int( b) ) ) => {
248
270
match op {
249
- add => const_int ( a + b) ,
250
- subtract => const_int ( a - b) ,
251
- mul => const_int ( a * b) ,
252
- div => const_int ( a / b) ,
253
- rem => const_int ( a % b) ,
254
- and | bitand => const_int ( a & b) ,
255
- or | bitor => const_int ( a | b) ,
256
- bitxor => const_int ( a ^ b) ,
257
- shl => const_int ( a << b) ,
258
- shr => const_int ( a >> b) ,
271
+ add => Ok ( const_int ( a + b) ) ,
272
+ subtract => Ok ( const_int ( a - b) ) ,
273
+ mul => Ok ( const_int ( a * b) ) ,
274
+ div => Ok ( const_int ( a / b) ) ,
275
+ rem => Ok ( const_int ( a % b) ) ,
276
+ and | bitand => Ok ( const_int ( a & b) ) ,
277
+ or | bitor => Ok ( const_int ( a | b) ) ,
278
+ bitxor => Ok ( const_int ( a ^ b) ) ,
279
+ shl => Ok ( const_int ( a << b) ) ,
280
+ shr => Ok ( const_int ( a >> b) ) ,
259
281
eq => fromb ( a == b) ,
260
282
lt => fromb ( a < b) ,
261
283
le => fromb ( a <= b) ,
@@ -264,18 +286,18 @@ fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val {
264
286
gt => fromb ( a > b)
265
287
}
266
288
}
267
- ( const_uint( a) , const_uint( b) ) => {
289
+ ( Ok ( const_uint( a) ) , Ok ( const_uint( b) ) ) => {
268
290
match op {
269
- add => const_uint ( a + b) ,
270
- subtract => const_uint ( a - b) ,
271
- mul => const_uint ( a * b) ,
272
- div => const_uint ( a / b) ,
273
- rem => const_uint ( a % b) ,
274
- and | bitand => const_uint ( a & b) ,
275
- or | bitor => const_uint ( a | b) ,
276
- bitxor => const_uint ( a ^ b) ,
277
- shl => const_uint ( a << b) ,
278
- shr => const_uint ( a >> b) ,
291
+ add => Ok ( const_uint ( a + b) ) ,
292
+ subtract => Ok ( const_uint ( a - b) ) ,
293
+ mul => Ok ( const_uint ( a * b) ) ,
294
+ div => Ok ( const_uint ( a / b) ) ,
295
+ rem => Ok ( const_uint ( a % b) ) ,
296
+ and | bitand => Ok ( const_uint ( a & b) ) ,
297
+ or | bitor => Ok ( const_uint ( a | b) ) ,
298
+ bitxor => Ok ( const_uint ( a ^ b) ) ,
299
+ shl => Ok ( const_uint ( a << b) ) ,
300
+ shr => Ok ( const_uint ( a >> b) ) ,
279
301
eq => fromb ( a == b) ,
280
302
lt => fromb ( a < b) ,
281
303
le => fromb ( a <= b) ,
@@ -285,70 +307,76 @@ fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val {
285
307
}
286
308
}
287
309
// shifts can have any integral type as their rhs
288
- ( const_int( a) , const_uint( b) ) => {
310
+ ( Ok ( const_int( a) ) , Ok ( const_uint( b) ) ) => {
289
311
match op {
290
- shl => const_int ( a << b) ,
291
- shr => const_int ( a >> b) ,
292
- _ => fail ~"Can ' t do this op on an int and uint"
312
+ shl => Ok ( const_int ( a << b) ) ,
313
+ shr => Ok ( const_int ( a >> b) ) ,
314
+ _ => Err ( ~"Can ' t do this op on an int and uint")
293
315
}
294
316
}
295
- ( const_uint( a) , const_int( b) ) => {
317
+ ( Ok ( const_uint ( a) ) , Ok ( const_int ( b) ) ) => {
296
318
match op {
297
- shl => const_uint ( a << b) ,
298
- shr => const_uint ( a >> b) ,
299
- _ => fail ~"Can ' t do this op on a uint and int"
319
+ shl => Ok ( const_uint ( a << b) ) ,
320
+ shr => Ok ( const_uint ( a >> b) ) ,
321
+ _ => Err ( ~"Can ' t do this op on a uint and int")
300
322
}
301
323
}
302
- ( const_bool( a) , const_bool( b) ) => {
303
- const_bool ( match op {
324
+ ( Ok ( const_bool ( a) ) , Ok ( const_bool ( b) ) ) => {
325
+ Ok ( const_bool ( match op {
304
326
and => a && b,
305
327
or => a || b,
306
328
bitxor => a ^ b,
307
329
bitand => a & b,
308
330
bitor => a | b,
309
331
eq => a == b,
310
332
ne => a != b,
311
- _ => fail ~"Can ' t do this op on bools"
312
- } )
333
+ _ => return Err ( ~"Can ' t do this op on bools")
334
+ } ) )
313
335
}
314
- _ => fail ~"Bad operands for binary"
336
+ _ => Err ( ~"Bad operands for binary")
315
337
}
316
338
}
317
339
expr_cast( base, _) => {
318
340
let ety = ty:: expr_ty ( tcx, e) ;
319
- let base = eval_const_expr ( tcx, base) ;
341
+ let base = eval_const_expr_partial ( tcx, base) ;
320
342
match ty:: get ( ety) . sty {
321
343
ty:: ty_float( _) => {
322
344
match base {
323
- const_uint( u) => const_float ( u as f64 ) ,
324
- const_int( i) => const_float ( i as f64 ) ,
325
- const_float( _) => base,
326
- _ => fail ~"Can ' t cast float to str"
345
+ Ok ( const_uint( u) ) => Ok ( const_float ( u as f64 ) ) ,
346
+ Ok ( const_int( i) ) => Ok ( const_float ( i as f64 ) ) ,
347
+ Ok ( const_float( _) ) => base,
348
+ _ => Err ( ~"Can ' t cast float to str")
327
349
}
328
350
}
329
351
ty:: ty_uint( _) => {
330
352
match base {
331
- const_uint( _) => base,
332
- const_int( i) => const_uint ( i as u64 ) ,
333
- const_float( f) => const_uint ( f as u64 ) ,
334
- _ => fail ~"Can ' t cast str to uint"
353
+ Ok ( const_uint( _) ) => base,
354
+ Ok ( const_int( i) ) => Ok ( const_uint ( i as u64 ) ) ,
355
+ Ok ( const_float( f) ) => Ok ( const_uint ( f as u64 ) ) ,
356
+ _ => Err ( ~"Can ' t cast str to uint")
335
357
}
336
358
}
337
359
ty:: ty_int( _) | ty:: ty_bool => {
338
360
match base {
339
- const_uint( u) => const_int ( u as i64 ) ,
340
- const_int( _) => base,
341
- const_float( f) => const_int ( f as i64 ) ,
342
- _ => fail ~"Can ' t cast str to int"
361
+ Ok ( const_uint( u) ) => Ok ( const_int ( u as i64 ) ) ,
362
+ Ok ( const_int( _) ) => base,
363
+ Ok ( const_float( f) ) => Ok ( const_int ( f as i64 ) ) ,
364
+ _ => Err ( ~"Can ' t cast str to int")
343
365
}
344
366
}
345
- _ => fail ~"Can ' t cast this type "
367
+ _ => Err ( ~"Can ' t cast this type")
346
368
}
347
369
}
348
- expr_lit( lit) => lit_to_const ( lit) ,
370
+ expr_path( _) => {
371
+ match lookup_const ( tcx, e) {
372
+ Some ( actual_e) => eval_const_expr_partial ( tcx, actual_e) ,
373
+ None => Err ( ~"Non -constant path in constant expr")
374
+ }
375
+ }
376
+ expr_lit ( lit) => Ok ( lit_to_const ( lit) ) ,
349
377
// If we have a vstore, just keep going; it has to be a string
350
- expr_vstore( e, _) => eval_const_expr ( tcx, e) ,
351
- _ => fail ~"Unsupported constant expr"
378
+ expr_vstore ( e, _) => eval_const_expr_partial ( tcx, e) ,
379
+ _ => Err ( ~"Unsupported constant expr")
352
380
}
353
381
}
354
382
0 commit comments