@@ -15,7 +15,7 @@ use rustc::middle::const_val::{ConstVal, ConstEvalErr, EvalResult, ErrKind};
1515use rustc:: hir:: map as hir_map;
1616use rustc:: hir:: map:: blocks:: FnLikeNode ;
1717use rustc:: traits;
18- use rustc:: hir:: def:: Def ;
18+ use rustc:: hir:: def:: { Def , CtorKind } ;
1919use rustc:: hir:: def_id:: DefId ;
2020use rustc:: ty:: { self , Ty , TyCtxt } ;
2121use rustc:: ty:: maps:: Providers ;
@@ -48,28 +48,6 @@ macro_rules! math {
4848 }
4949}
5050
51- fn lookup_variant_by_id < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
52- variant_def : DefId )
53- -> Option < ( & ' tcx Expr , & ' a ty:: TypeckTables < ' tcx > ) > {
54- if let Some ( variant_node_id) = tcx. hir . as_local_node_id ( variant_def) {
55- let enum_node_id = tcx. hir . get_parent ( variant_node_id) ;
56- if let Some ( hir_map:: NodeItem ( it) ) = tcx. hir . find ( enum_node_id) {
57- if let hir:: ItemEnum ( ref edef, _) = it. node {
58- for variant in & edef. variants {
59- if variant. node . data . id ( ) == variant_node_id {
60- return variant. node . disr_expr . map ( |e| {
61- let def_id = tcx. hir . body_owner_def_id ( e) ;
62- ( & tcx. hir . body ( e) . value ,
63- tcx. item_tables ( def_id) )
64- } ) ;
65- }
66- }
67- }
68- }
69- }
70- None
71- }
72-
7351/// * `def_id` is the id of the constant.
7452/// * `substs` is the monomorphized substitutions for the expression.
7553///
@@ -289,9 +267,22 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
289267 }
290268 }
291269 hir:: ExprCast ( ref base, _) => {
292- match cast_const ( tcx, cx. eval ( base) ?, ety) {
293- Ok ( val) => val,
294- Err ( kind) => return Err ( ConstEvalErr { span : e. span , kind : kind } ) ,
270+ let base_val = cx. eval ( base) ?;
271+ let base_ty = cx. tables . expr_ty ( base) ;
272+
273+ // Avoid applying substitutions if they're empty, that'd ICE.
274+ let base_ty = if cx. substs . is_empty ( ) {
275+ base_ty
276+ } else {
277+ base_ty. subst ( tcx, cx. substs )
278+ } ;
279+ if ety == base_ty {
280+ base_val
281+ } else {
282+ match cast_const ( tcx, base_val, ety) {
283+ Ok ( val) => val,
284+ Err ( kind) => signal ! ( e, kind) ,
285+ }
295286 }
296287 }
297288 hir:: ExprPath ( ref qpath) => {
@@ -317,27 +308,20 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
317308 debug ! ( "bad reference: {:?}, {:?}" , err. description( ) , err. span) ;
318309 signal ! ( e, ErroneousReferencedConstant ( box err) )
319310 } ,
311+ }
320312 } ,
321- Def :: VariantCtor ( variant_def, ..) => {
322- if let Some ( ( expr, tables) ) = lookup_variant_by_id ( tcx, variant_def) {
323- let cx = ConstContext :: with_tables ( tcx, tables) ;
324- match cx. eval ( expr) {
325- Ok ( val) => val,
326- Err ( ConstEvalErr { kind : TypeckError , .. } ) => {
327- signal ! ( e, TypeckError ) ;
328- }
329- Err ( err) => {
330- debug ! ( "bad reference: {:?}, {:?}" , err. description( ) , err. span) ;
331- signal ! ( e, ErroneousReferencedConstant ( box err) )
332- } ,
333- }
334- } else {
335- signal ! ( e, UnimplementedConstVal ( "enum variants" ) ) ;
336- }
313+ Def :: VariantCtor ( variant_def, CtorKind :: Const ) => {
314+ Variant ( variant_def)
315+ }
316+ Def :: VariantCtor ( _, CtorKind :: Fn ) => {
317+ signal ! ( e, UnimplementedConstVal ( "enum variants" ) ) ;
337318 }
338- Def :: StructCtor ( .. ) => {
319+ Def :: StructCtor ( _ , CtorKind :: Const ) => {
339320 ConstVal :: Struct ( Default :: default ( ) )
340321 }
322+ Def :: StructCtor ( _, CtorKind :: Fn ) => {
323+ signal ! ( e, UnimplementedConstVal ( "tuple struct constructors" ) )
324+ }
341325 Def :: Local ( def_id) => {
342326 debug ! ( "Def::Local({:?}): {:?}" , def_id, cx. fn_args) ;
343327 if let Some ( val) = cx. fn_args . as_ref ( ) . and_then ( |args| args. get ( & def_id) ) {
@@ -578,7 +562,7 @@ fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
578562 U8 ( u) => Ok ( Char ( u as char ) ) ,
579563 _ => bug ! ( ) ,
580564 } ,
581- _ => bug ! ( ) ,
565+ _ => Err ( CannotCast ) ,
582566 }
583567}
584568
@@ -622,6 +606,11 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
622606 Bool ( b) => cast_const_int ( tcx, U8 ( b as u8 ) , ty) ,
623607 Float ( f) => cast_const_float ( tcx, f, ty) ,
624608 Char ( c) => cast_const_int ( tcx, U32 ( c as u32 ) , ty) ,
609+ Variant ( v) => {
610+ let adt = tcx. lookup_adt_def ( tcx. parent_def_id ( v) . unwrap ( ) ) ;
611+ let idx = adt. variant_index_with_id ( v) ;
612+ cast_const_int ( tcx, adt. discriminant_for_variant ( tcx, idx) , ty)
613+ }
625614 Function ( ..) => Err ( UnimplementedConstVal ( "casting fn pointers" ) ) ,
626615 ByteStr ( b) => match ty. sty {
627616 ty:: TyRawPtr ( _) => {
0 commit comments