1- use syntax:: { ast, ast_util, visit} ;
1+ use syntax:: { ast, ast_map , ast_util, visit} ;
22use ast:: * ;
33
44//
@@ -135,28 +135,7 @@ fn classify(e: @expr,
135135 // FIXME: (#3728) we can probably do something CCI-ish
136136 // surrounding nonlocal constants. But we don't yet.
137137 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)
160139 }
161140
162141 _ => non_const
@@ -167,6 +146,40 @@ fn classify(e: @expr,
167146 }
168147}
169148
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+
170183fn process_crate ( crate : @ast:: crate ,
171184 def_map : resolve:: DefMap ,
172185 tcx : ty:: ctxt ) {
@@ -204,58 +217,67 @@ impl const_val : cmp::Eq {
204217 pure fn ne ( other : & const_val ) -> bool { !self . eq ( other) }
205218}
206219
207- // FIXME: issue #1417
208220fn 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 > {
209229 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 ) ) }
211231 match e. node {
212232 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
219240 }
220241 }
221242 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")
227248 }
228249 }
229250 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) ) ) => {
232254 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) ) ,
238260 eq => fromb ( a == b) ,
239261 lt => fromb ( a < b) ,
240262 le => fromb ( a <= b) ,
241263 ne => fromb ( a != b) ,
242264 ge => fromb ( a >= b) ,
243265 gt => fromb ( a > b) ,
244- _ => fail ~"Can ' t do this op on floats"
266+ _ => Err ( ~"Can ' t do this op on floats")
245267 }
246268 }
247- ( const_int( a) , const_int( b) ) => {
269+ ( Ok ( const_int( a) ) , Ok ( const_int( b) ) ) => {
248270 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) ) ,
259281 eq => fromb ( a == b) ,
260282 lt => fromb ( a < b) ,
261283 le => fromb ( a <= b) ,
@@ -264,18 +286,18 @@ fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val {
264286 gt => fromb ( a > b)
265287 }
266288 }
267- ( const_uint( a) , const_uint( b) ) => {
289+ ( Ok ( const_uint( a) ) , Ok ( const_uint( b) ) ) => {
268290 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) ) ,
279301 eq => fromb ( a == b) ,
280302 lt => fromb ( a < b) ,
281303 le => fromb ( a <= b) ,
@@ -285,70 +307,76 @@ fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val {
285307 }
286308 }
287309 // 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) ) ) => {
289311 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")
293315 }
294316 }
295- ( const_uint( a) , const_int( b) ) => {
317+ ( Ok ( const_uint ( a) ) , Ok ( const_int ( b) ) ) => {
296318 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")
300322 }
301323 }
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 {
304326 and => a && b,
305327 or => a || b,
306328 bitxor => a ^ b,
307329 bitand => a & b,
308330 bitor => a | b,
309331 eq => a == b,
310332 ne => a != b,
311- _ => fail ~"Can ' t do this op on bools"
312- } )
333+ _ => return Err ( ~"Can ' t do this op on bools")
334+ } ) )
313335 }
314- _ => fail ~"Bad operands for binary"
336+ _ => Err ( ~"Bad operands for binary")
315337 }
316338 }
317339 expr_cast( base, _) => {
318340 let ety = ty:: expr_ty ( tcx, e) ;
319- let base = eval_const_expr ( tcx, base) ;
341+ let base = eval_const_expr_partial ( tcx, base) ;
320342 match ty:: get ( ety) . sty {
321343 ty:: ty_float( _) => {
322344 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")
327349 }
328350 }
329351 ty:: ty_uint( _) => {
330352 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")
335357 }
336358 }
337359 ty:: ty_int( _) | ty:: ty_bool => {
338360 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")
343365 }
344366 }
345- _ => fail ~"Can ' t cast this type "
367+ _ => Err ( ~"Can ' t cast this type")
346368 }
347369 }
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) ) ,
349377 // 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")
352380 }
353381}
354382
0 commit comments