.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);
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);
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::<Vec<_>>();
- 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::<Vec<_>>();
+ 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::<Vec<_>>();
+ let vs = es.iter()
+ .map(|e| const_expr(cx, &**e, param_substs, fn_args).0)
+ .collect::<Vec<_>>();
// 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);
} 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) => {
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"),
}
}