diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index e7e2793fc7e9d..ece52b3ad4d6d 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -486,13 +486,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, .map(|e| const_expr(cx, &**e, param_substs, fn_args).0) .collect() }; - unsafe { - let _icx = push_ctxt("const_expr"); - match e.node { - ast::ExprLit(ref lit) => { - const_lit(cx, e, &**lit) - } - ast::ExprBinary(b, ref e1, ref e2) => { + let _icx = push_ctxt("const_expr"); + match e.node { + ast::ExprLit(ref lit) => { + const_lit(cx, e, &**lit) + }, + ast::ExprBinary(b, ref e1, ref e2) => { /* Neither type is bottom, and we expect them to be unified * already, so the following is safe. */ let (te1, ty) = const_expr(cx, &**e1, param_substs, fn_args); @@ -512,145 +511,136 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, check_binary_expr_validity(cx, e, ty, te1, te2); - match b.node { - ast::BiAdd => { - if is_float { llvm::LLVMConstFAdd(te1, te2) } - else { llvm::LLVMConstAdd(te1, te2) } - } - ast::BiSub => { - if is_float { llvm::LLVMConstFSub(te1, te2) } - else { llvm::LLVMConstSub(te1, te2) } - } - ast::BiMul => { - if is_float { llvm::LLVMConstFMul(te1, te2) } - else { llvm::LLVMConstMul(te1, te2) } - } - ast::BiDiv => { - if is_float { llvm::LLVMConstFDiv(te1, te2) } - else if signed { llvm::LLVMConstSDiv(te1, te2) } - else { llvm::LLVMConstUDiv(te1, te2) } - } - ast::BiRem => { - if is_float { llvm::LLVMConstFRem(te1, te2) } - else if signed { llvm::LLVMConstSRem(te1, te2) } - else { llvm::LLVMConstURem(te1, te2) } - } - ast::BiAnd => llvm::LLVMConstAnd(te1, te2), - ast::BiOr => llvm::LLVMConstOr(te1, te2), - ast::BiBitXor => llvm::LLVMConstXor(te1, te2), - ast::BiBitAnd => llvm::LLVMConstAnd(te1, te2), - ast::BiBitOr => llvm::LLVMConstOr(te1, te2), - ast::BiShl => { - let te2 = base::cast_shift_const_rhs(b.node, te1, te2); - llvm::LLVMConstShl(te1, te2) - } - ast::BiShr => { - let te2 = base::cast_shift_const_rhs(b.node, te1, te2); - if signed { llvm::LLVMConstAShr(te1, te2) } - else { llvm::LLVMConstLShr(te1, te2) } - } - ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGt | ast::BiGe => { - if is_float { - let cmp = base::bin_op_to_fcmp_predicate(cx, b.node); - ConstFCmp(cmp, te1, te2) - } else { - let cmp = base::bin_op_to_icmp_predicate(cx, b.node, signed); - let bool_val = ConstICmp(cmp, te1, te2); - if is_simd { - // LLVM outputs an `< size x i1 >`, so we need to perform - // a sign extension to get the correctly sized type. - llvm::LLVMConstIntCast(bool_val, val_ty(te1).to_ref(), True) - } else { - bool_val - } - } - } - } - }, - ast::ExprUnary(u, ref inner_e) => { + unsafe { match b.node { + ast::BiAdd if is_float => llvm::LLVMConstFAdd(te1, te2), + ast::BiAdd => llvm::LLVMConstAdd(te1, te2), + + ast::BiSub if is_float => llvm::LLVMConstFSub(te1, te2), + ast::BiSub => llvm::LLVMConstSub(te1, te2), + + ast::BiMul if is_float => llvm::LLVMConstFMul(te1, te2), + ast::BiMul => llvm::LLVMConstMul(te1, te2), + + ast::BiDiv if is_float => llvm::LLVMConstFDiv(te1, te2), + ast::BiDiv if signed => llvm::LLVMConstSDiv(te1, te2), + ast::BiDiv => llvm::LLVMConstUDiv(te1, te2), + + ast::BiRem if is_float => llvm::LLVMConstFRem(te1, te2), + ast::BiRem if signed => llvm::LLVMConstSRem(te1, te2), + ast::BiRem => llvm::LLVMConstURem(te1, te2), + + ast::BiAnd => llvm::LLVMConstAnd(te1, te2), + ast::BiOr => llvm::LLVMConstOr(te1, te2), + ast::BiBitXor => llvm::LLVMConstXor(te1, te2), + ast::BiBitAnd => llvm::LLVMConstAnd(te1, te2), + ast::BiBitOr => llvm::LLVMConstOr(te1, te2), + ast::BiShl => { + let te2 = base::cast_shift_const_rhs(b.node, te1, te2); + llvm::LLVMConstShl(te1, te2) + }, + ast::BiShr => { + let te2 = base::cast_shift_const_rhs(b.node, te1, te2); + if signed { llvm::LLVMConstAShr(te1, te2) } + else { llvm::LLVMConstLShr(te1, te2) } + }, + ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGt | ast::BiGe => { + if is_float { + let cmp = base::bin_op_to_fcmp_predicate(cx, b.node); + ConstFCmp(cmp, te1, te2) + } else { + let cmp = base::bin_op_to_icmp_predicate(cx, b.node, signed); + let bool_val = ConstICmp(cmp, te1, te2); + if is_simd { + // LLVM outputs an `< size x i1 >`, so we need to perform + // a sign extension to get the correctly sized type. + llvm::LLVMConstIntCast(bool_val, val_ty(te1).to_ref(), True) + } else { + bool_val + } + } + }, + } } // unsafe { match b.node { + }, + ast::ExprUnary(u, ref inner_e) => { let (te, ty) = const_expr(cx, &**inner_e, param_substs, fn_args); check_unary_expr_validity(cx, e, ty, te); let is_float = ty.is_fp(); - match u { - ast::UnUniq | ast::UnDeref => { - const_deref(cx, te, ty).0 - } - ast::UnNot => llvm::LLVMConstNot(te), - ast::UnNeg => { - if is_float { llvm::LLVMConstFNeg(te) } - else { llvm::LLVMConstNeg(te) } - } + unsafe { match u { + ast::UnUniq | ast::UnDeref => const_deref(cx, te, ty).0, + ast::UnNot => llvm::LLVMConstNot(te), + ast::UnNeg if is_float => llvm::LLVMConstFNeg(te), + ast::UnNeg => llvm::LLVMConstNeg(te), + } } + }, + ast::ExprField(ref base, field) => { + let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args); + let brepr = adt::represent_type(cx, bt); + expr::with_field_tys(cx.tcx(), bt, None, |discr, field_tys| { + let ix = cx.tcx().field_idx_strict(field.node.name, field_tys); + adt::const_get_field(cx, &*brepr, bv, discr, ix) + }) + }, + ast::ExprTupField(ref base, idx) => { + let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args); + let brepr = adt::represent_type(cx, bt); + expr::with_field_tys(cx.tcx(), bt, None, |discr, _| { + adt::const_get_field(cx, &*brepr, bv, discr, idx.node) + }) + }, + + ast::ExprIndex(ref base, ref index) => { + let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args); + let iv = match const_eval::eval_const_expr_partial(cx.tcx(), &**index, None) { + Ok(ConstVal::Int(i)) => i as u64, + Ok(ConstVal::Uint(u)) => u, + _ => cx.sess().span_bug(index.span, + "index is not an integer-constant expression") + }; + let (arr, len) = match bt.sty { + ty::TyArray(_, u) => (bv, C_uint(cx, u)), + ty::TySlice(_) | ty::TyStr => { + let e1 = const_get_elt(cx, bv, &[0]); + (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1])) + }, + ty::TyRef(_, mt) => match mt.ty.sty { + ty::TyArray(_, u) => { + (const_deref_ptr(cx, bv), C_uint(cx, u)) + }, + _ => cx.sess().span_bug(base.span, + &format!("index-expr base must be a vector \ + or string type, found {:?}", + bt)), + }, + _ => cx.sess().span_bug(base.span, + &format!("index-expr base must be a vector \ + or string type, found {:?}", + bt)), + }; + + let len = unsafe { llvm::LLVMConstIntGetZExtValue(len) as u64 }; + let len = match bt.sty { + ty::TyBox(ty) | ty::TyRef(_, ty::mt{ty, ..}) => match ty.sty { + ty::TyStr => { + assert!(len > 0); + len - 1 + }, + _ => len, + }, + _ => len, + }; + if iv >= len { + // FIXME #3170: report this earlier on in the const-eval + // pass. Reporting here is a bit late. + cx.sess().span_err(e.span, + "const index-expr is out of bounds"); + C_undef(type_of::type_of(cx, bt).element_type()) + } else { + const_get_elt(cx, arr, &[iv as c_uint]) } - } - ast::ExprField(ref base, field) => { - let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args); - let brepr = adt::represent_type(cx, bt); - expr::with_field_tys(cx.tcx(), bt, None, |discr, field_tys| { - let ix = cx.tcx().field_idx_strict(field.node.name, field_tys); - adt::const_get_field(cx, &*brepr, bv, discr, ix) - }) - } - ast::ExprTupField(ref base, idx) => { - let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args); - let brepr = adt::represent_type(cx, bt); - expr::with_field_tys(cx.tcx(), bt, None, |discr, _| { - adt::const_get_field(cx, &*brepr, bv, discr, idx.node) - }) - } - - ast::ExprIndex(ref base, ref index) => { - let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args); - let iv = match const_eval::eval_const_expr_partial(cx.tcx(), &**index, None) { - Ok(ConstVal::Int(i)) => i as u64, - Ok(ConstVal::Uint(u)) => u, - _ => cx.sess().span_bug(index.span, - "index is not an integer-constant expression") - }; - let (arr, len) = match bt.sty { - ty::TyArray(_, u) => (bv, C_uint(cx, u)), - ty::TySlice(_) | ty::TyStr => { - let e1 = const_get_elt(cx, bv, &[0]); - (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1])) - } - ty::TyRef(_, mt) => match mt.ty.sty { - ty::TyArray(_, u) => { - (const_deref_ptr(cx, bv), C_uint(cx, u)) - }, - _ => cx.sess().span_bug(base.span, - &format!("index-expr base must be a vector \ - or string type, found {:?}", - bt)) - }, - _ => cx.sess().span_bug(base.span, - &format!("index-expr base must be a vector \ - or string type, found {:?}", - bt)) - }; - - let len = llvm::LLVMConstIntGetZExtValue(len) as u64; - let len = match bt.sty { - ty::TyBox(ty) | ty::TyRef(_, ty::mt{ty, ..}) => match ty.sty { - ty::TyStr => { - assert!(len > 0); - len - 1 - } - _ => len - }, - _ => len - }; - if iv >= len { - // FIXME #3170: report this earlier on in the const-eval - // pass. Reporting here is a bit late. - cx.sess().span_err(e.span, - "const index-expr is out of bounds"); - C_undef(type_of::type_of(cx, bt).element_type()) - } else { - const_get_elt(cx, arr, &[iv as c_uint]) - } - } - ast::ExprCast(ref base, _) => { + }, + ast::ExprCast(ref base, _) => { let t_cast = ety; let llty = type_of::type_of(cx, t_cast); let (v, t_expr) = const_expr(cx, &**base, param_substs, fn_args); @@ -671,136 +661,121 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, return addr; } } - match (CastTy::from_ty(cx.tcx(), t_expr).expect("bad input type for cast"), - CastTy::from_ty(cx.tcx(), t_cast).expect("bad output type for cast")) { - (CastTy::Int(IntTy::CEnum), CastTy::Int(_)) => { - let repr = adt::represent_type(cx, t_expr); - let discr = adt::const_get_discrim(cx, &*repr, v); - let iv = C_integral(cx.int_type(), discr, false); - let s = adt::is_discr_signed(&*repr) as Bool; - llvm::LLVMConstIntCast(iv, llty.to_ref(), s) - } - (CastTy::Int(_), CastTy::Int(_)) => { - let s = t_expr.is_signed() as Bool; - llvm::LLVMConstIntCast(v, llty.to_ref(), s) - } - (CastTy::Int(_), CastTy::Float) => { - if t_expr.is_signed() { - llvm::LLVMConstSIToFP(v, llty.to_ref()) - } else { - llvm::LLVMConstUIToFP(v, llty.to_ref()) - } - } - (CastTy::Float, CastTy::Float) => { - llvm::LLVMConstFPCast(v, llty.to_ref()) - } - (CastTy::Float, CastTy::Int(IntTy::I)) => { - llvm::LLVMConstFPToSI(v, llty.to_ref()) - } - (CastTy::Float, CastTy::Int(_)) => { - llvm::LLVMConstFPToUI(v, llty.to_ref()) - } - (CastTy::Ptr(_), CastTy::Ptr(_)) | (CastTy::FnPtr, CastTy::Ptr(_)) - | (CastTy::RPtr(_), CastTy::Ptr(_)) => { - ptrcast(v, llty) - } - (CastTy::FnPtr, CastTy::FnPtr) => ptrcast(v, llty), // isn't this a coercion? - (CastTy::Int(_), CastTy::Ptr(_)) => { - llvm::LLVMConstIntToPtr(v, llty.to_ref()) - } - (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => { - llvm::LLVMConstPtrToInt(v, llty.to_ref()) - } - _ => { - cx.sess().impossible_case(e.span, - "bad combination of types for cast") - } - } - } - ast::ExprAddrOf(ast::MutImmutable, ref sub) => { - // If this is the address of some static, then we need to return - // the actual address of the static itself (short circuit the rest - // of const eval). - let mut cur = sub; - loop { - match cur.node { - ast::ExprParen(ref sub) => cur = sub, - ast::ExprBlock(ref blk) => { + unsafe { match ( + CastTy::from_ty(cx.tcx(), t_expr).expect("bad input type for cast"), + CastTy::from_ty(cx.tcx(), t_cast).expect("bad output type for cast"), + ) { + (CastTy::Int(IntTy::CEnum), CastTy::Int(_)) => { + let repr = adt::represent_type(cx, t_expr); + let discr = adt::const_get_discrim(cx, &*repr, v); + let iv = C_integral(cx.int_type(), discr, false); + let s = adt::is_discr_signed(&*repr) as Bool; + llvm::LLVMConstIntCast(iv, llty.to_ref(), s) + }, + (CastTy::Int(_), CastTy::Int(_)) => { + let s = t_expr.is_signed() as Bool; + llvm::LLVMConstIntCast(v, llty.to_ref(), s) + }, + (CastTy::Int(_), CastTy::Float) => { + if t_expr.is_signed() { + llvm::LLVMConstSIToFP(v, llty.to_ref()) + } else { + llvm::LLVMConstUIToFP(v, llty.to_ref()) + } + }, + (CastTy::Float, CastTy::Float) => llvm::LLVMConstFPCast(v, llty.to_ref()), + (CastTy::Float, CastTy::Int(IntTy::I)) => llvm::LLVMConstFPToSI(v, llty.to_ref()), + (CastTy::Float, CastTy::Int(_)) => llvm::LLVMConstFPToUI(v, llty.to_ref()), + (CastTy::Ptr(_), CastTy::Ptr(_)) | (CastTy::FnPtr, CastTy::Ptr(_)) + | (CastTy::RPtr(_), CastTy::Ptr(_)) => { + ptrcast(v, llty) + }, + (CastTy::FnPtr, CastTy::FnPtr) => ptrcast(v, llty), // isn't this a coercion? + (CastTy::Int(_), CastTy::Ptr(_)) => llvm::LLVMConstIntToPtr(v, llty.to_ref()), + (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => { + llvm::LLVMConstPtrToInt(v, llty.to_ref()) + }, + _ => { + cx.sess().impossible_case(e.span, + "bad combination of types for cast") + }, + } } // unsafe { match ( ... ) { + }, + ast::ExprAddrOf(ast::MutImmutable, ref sub) => { + // If this is the address of some static, then we need to return + // the actual address of the static itself (short circuit the rest + // of const eval). + let mut cur = sub; + loop { + match cur.node { + ast::ExprParen(ref sub) => cur = sub, + ast::ExprBlock(ref blk) => { if let Some(ref sub) = blk.expr { cur = sub; } else { break; } - } - _ => break, - } - } - let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def()); - if let Some(def::DefStatic(def_id, _)) = opt_def { - get_static_val(cx, def_id, ety) - } else { - // If this isn't the address of a static, then keep going through - // normal constant evaluation. - let (v, _) = const_expr(cx, &**sub, param_substs, fn_args); - addr_of(cx, v, "ref") - } - } - ast::ExprAddrOf(ast::MutMutable, ref sub) => { - let (v, _) = const_expr(cx, &**sub, param_substs, fn_args); - addr_of_mut(cx, v, "ref_mut_slice") - } - ast::ExprTup(ref es) => { - let repr = adt::represent_type(cx, ety); - let vals = map_list(&es[..]); - adt::trans_const(cx, &*repr, 0, &vals[..]) - } - ast::ExprStruct(_, ref fs, ref base_opt) => { - let repr = adt::represent_type(cx, ety); - - let base_val = match *base_opt { + }, + _ => break, + } + } + let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def()); + if let Some(def::DefStatic(def_id, _)) = opt_def { + get_static_val(cx, def_id, ety) + } else { + // If this isn't the address of a static, then keep going through + // normal constant evaluation. + let (v, _) = const_expr(cx, &**sub, param_substs, fn_args); + addr_of(cx, v, "ref") + } + }, + ast::ExprAddrOf(ast::MutMutable, ref sub) => { + let (v, _) = const_expr(cx, &**sub, param_substs, fn_args); + addr_of_mut(cx, v, "ref_mut_slice") + }, + ast::ExprTup(ref es) => { + let repr = adt::represent_type(cx, ety); + let vals = map_list(&es[..]); + adt::trans_const(cx, &*repr, 0, &vals[..]) + }, + ast::ExprStruct(_, ref fs, ref base_opt) => { + let repr = adt::represent_type(cx, ety); + + let base_val = match *base_opt { Some(ref base) => Some(const_expr(cx, &**base, param_substs, fn_args)), None => None - }; - - expr::with_field_tys(cx.tcx(), ety, Some(e.id), |discr, field_tys| { - let cs = field_tys.iter().enumerate() - .map(|(ix, &field_ty)| { - match fs.iter().find(|f| field_ty.name == f.ident.node.name) { - Some(ref f) => const_expr(cx, &*f.expr, param_substs, fn_args).0, - None => { - match base_val { - Some((bv, _)) => { - adt::const_get_field(cx, &*repr, bv, - discr, ix) - } - None => { - cx.sess().span_bug(e.span, - "missing struct field") - } - } - } - } - }).collect::>(); - if ety.is_simd(cx.tcx()) { - C_vector(&cs[..]) - } else { - adt::trans_const(cx, &*repr, discr, &cs[..]) - } - }) - } - ast::ExprVec(ref es) => { + }; + + expr::with_field_tys(cx.tcx(), ety, Some(e.id), |discr, field_tys| { + let cs = field_tys.iter().enumerate() + .map(|(ix, &field_ty)| { + match (fs.iter().find(|f| field_ty.name == f.ident.node.name), base_val) { + (Some(ref f), _) => const_expr(cx, &*f.expr, param_substs, fn_args).0, + (_, Some((bv, _))) => adt::const_get_field(cx, &*repr, bv, discr, ix), + (_, None) => cx.sess().span_bug(e.span, "missing struct field"), + } + }).collect::>(); + if ety.is_simd(cx.tcx()) { + C_vector(&cs[..]) + } else { + adt::trans_const(cx, &*repr, discr, &cs[..]) + } + }) + }, + ast::ExprVec(ref es) => { let unit_ty = ety.sequence_element_type(cx.tcx()); let llunitty = type_of::type_of(cx, unit_ty); - let vs = es.iter().map(|e| const_expr(cx, &**e, param_substs, fn_args).0) - .collect::>(); + let vs = es.iter() + .map(|e| const_expr(cx, &**e, param_substs, fn_args).0) + .collect::>(); // If the vector contains enums, an LLVM array won't work. if vs.iter().any(|vi| val_ty(*vi) != llunitty) { C_struct(cx, &vs[..], false) } else { C_array(llunitty, &vs[..]) } - } - ast::ExprRepeat(ref elem, ref count) => { + }, + ast::ExprRepeat(ref elem, ref count) => { let unit_ty = ety.sequence_element_type(cx.tcx()); let llunitty = type_of::type_of(cx, unit_ty); let n = cx.tcx().eval_repeat_count(count); @@ -811,8 +786,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } else { C_array(llunitty, &vs[..]) } - } - ast::ExprPath(..) => { + }, + ast::ExprPath(..) => { let def = cx.tcx().def_map.borrow().get(&e.id).unwrap().full_def(); match def { def::DefLocal(id) => { @@ -853,69 +828,68 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, or variant def") } } - } - ast::ExprCall(ref callee, ref args) => { - let mut callee = &**callee; - loop { - callee = match callee.node { - ast::ExprParen(ref inner) => &**inner, - ast::ExprBlock(ref block) => match block.expr { - Some(ref tail) => &**tail, - None => break - }, - _ => break - }; - } - let def = cx.tcx().def_map.borrow()[&callee.id].full_def(); - let arg_vals = map_list(args); - match def { - def::DefFn(did, _) | def::DefMethod(did, _) => { - const_fn_call(cx, ExprId(callee.id), did, &arg_vals, param_substs) - } - def::DefStruct(_) => { - if ety.is_simd(cx.tcx()) { - C_vector(&arg_vals[..]) - } else { - let repr = adt::represent_type(cx, ety); - adt::trans_const(cx, &*repr, 0, &arg_vals[..]) - } - } - def::DefVariant(enum_did, variant_did, _) => { - let repr = adt::represent_type(cx, ety); - let vinfo = cx.tcx().enum_variant_with_id(enum_did, variant_did); - adt::trans_const(cx, - &*repr, - vinfo.disr_val, - &arg_vals[..]) - } - _ => cx.sess().span_bug(e.span, "expected a struct, variant, or const fn def") - } - } - ast::ExprMethodCall(_, _, ref args) => { - let arg_vals = map_list(args); - let method_call = ty::MethodCall::expr(e.id); + }, + ast::ExprCall(ref callee, ref args) => { + let mut callee = &**callee; + loop { + callee = match callee.node { + ast::ExprParen(ref inner) => &**inner, + ast::ExprBlock(ref block) => match block.expr { + Some(ref tail) => &**tail, + None => break, + }, + _ => break, + }; + } + let def = cx.tcx().def_map.borrow()[&callee.id].full_def(); + let arg_vals = map_list(args); + match def { + def::DefFn(did, _) | def::DefMethod(did, _) => { + const_fn_call(cx, ExprId(callee.id), did, &arg_vals, param_substs) + }, + def::DefStruct(_) => { + if ety.is_simd(cx.tcx()) { + C_vector(&arg_vals[..]) + } else { + let repr = adt::represent_type(cx, ety); + adt::trans_const(cx, &*repr, 0, &arg_vals[..]) + } + }, + def::DefVariant(enum_did, variant_did, _) => { + let repr = adt::represent_type(cx, ety); + let vinfo = cx.tcx().enum_variant_with_id(enum_did, variant_did); + adt::trans_const(cx, + &*repr, + vinfo.disr_val, + &arg_vals[..]) + }, + _ => cx.sess().span_bug(e.span, "expected a struct, variant, or const fn def"), + } + }, + ast::ExprMethodCall(_, _, ref args) => { + let arg_vals = map_list(args); + let method_call = ty::MethodCall::expr(e.id); let method_did = cx.tcx().tables.borrow().method_map[&method_call].def_id; - const_fn_call(cx, MethodCallKey(method_call), - method_did, &arg_vals, param_substs) - } - ast::ExprParen(ref e) => const_expr(cx, &**e, param_substs, fn_args).0, - ast::ExprBlock(ref block) => { + const_fn_call(cx, MethodCallKey(method_call), + method_did, &arg_vals, param_substs) + }, + ast::ExprParen(ref e) => const_expr(cx, &**e, param_substs, fn_args).0, + ast::ExprBlock(ref block) => { match block.expr { Some(ref expr) => const_expr(cx, &**expr, param_substs, fn_args).0, - None => C_nil(cx) + None => C_nil(cx), } - } - ast::ExprClosure(_, ref decl, ref body) => { + }, + ast::ExprClosure(_, ref decl, ref body) => { closure::trans_closure_expr(closure::Dest::Ignore(cx), decl, body, e.id, param_substs); C_null(type_of::type_of(cx, ety)) - } - _ => cx.sess().span_bug(e.span, - "bad constant expression type in consts::const_expr") - } + }, + _ => cx.sess().span_bug(e.span, + "bad constant expression type in consts::const_expr"), } }