diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 23ca22129fd..e351215276a 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -44,8 +44,8 @@ impl<'a,'tcx> Builder<'a,'tcx> { } ExprKind::Repeat { value, count } => { let value_operand = unpack!(block = this.as_operand(block, value)); - let count_operand = unpack!(block = this.as_operand(block, count)); - block.and(Rvalue::Repeat(value_operand, count_operand)) + let count = this.as_constant(count); + block.and(Rvalue::Repeat(value_operand, count)) } ExprKind::Borrow { region, borrow_kind, arg } => { let arg_lvalue = unpack!(block = this.as_lvalue(block, arg)); diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index a590a2c61e1..56ec0881811 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -15,7 +15,6 @@ use hair::cx::Cx; use hair::cx::block; use hair::cx::to_ref::ToRef; use rustc::front::map; -use rustc::middle::const_eval; use rustc::middle::def; use rustc::middle::region::CodeExtent; use rustc::middle::pat_util; @@ -80,10 +79,9 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { } } - hir::ExprLit(..) => { - let value = const_eval::eval_const_expr(cx.tcx, self); - ExprKind::Literal { literal: Literal::Value { value: value } } - } + hir::ExprLit(..) => ExprKind::Literal { + literal: cx.const_eval_literal(self) + }, hir::ExprBinary(op, ref lhs, ref rhs) => { if cx.tcx.is_method_call(self.id) { @@ -272,8 +270,17 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { // Now comes the rote stuff: - hir::ExprRepeat(ref v, ref c) => - ExprKind::Repeat { value: v.to_ref(), count: c.to_ref() }, + hir::ExprRepeat(ref v, ref c) => ExprKind::Repeat { + value: v.to_ref(), + count: Expr { + ty: cx.tcx.expr_ty(c), + temp_lifetime: None, + span: c.span, + kind: ExprKind::Literal { + literal: cx.const_eval_literal(c) + } + }.to_ref() + }, hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() }, hir::ExprBreak(label) => diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 70a64a5653a..cb04df91042 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -18,13 +18,14 @@ use hair::*; use repr::*; -use rustc::middle::const_eval::ConstVal; +use rustc::middle::const_eval::{self, ConstVal}; use rustc::middle::def_id::DefId; use rustc::middle::infer::InferCtxt; use rustc::middle::subst::{Subst, Substs}; use rustc::middle::ty::{self, Ty}; use syntax::codemap::Span; use syntax::parse::token; +use rustc_front::hir; #[derive(Copy, Clone)] pub struct Cx<'a, 'tcx: 'a> { @@ -71,6 +72,10 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> { Literal::Value { value: ConstVal::Bool(false) } } + pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> { + Literal::Value { value: const_eval::eval_const_expr(self.tcx, e) } + } + pub fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> { let eq_def_id = self.tcx.lang_items.eq_trait().unwrap(); self.cmp_method_ref(eq_def_id, "eq", ty) diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 60667915014..d2d7faac627 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -210,6 +210,9 @@ pub enum ExprKind<'tcx> { }, Repeat { value: ExprRef<'tcx>, + // FIXME(#29789): Add a separate hair::Constant<'tcx> so this could be more explicit about + // its contained data. Currently this should only contain expression of ExprKind::Literal + // kind. count: ExprRef<'tcx>, }, Vec { diff --git a/src/librustc_mir/repr.rs b/src/librustc_mir/repr.rs index 2871ebcaafc..610c983ce32 100644 --- a/src/librustc_mir/repr.rs +++ b/src/librustc_mir/repr.rs @@ -569,7 +569,7 @@ pub enum Rvalue<'tcx> { Use(Operand<'tcx>), // [x; 32] - Repeat(Operand<'tcx>, Operand<'tcx>), + Repeat(Operand<'tcx>, Constant<'tcx>), // &x or &mut x Ref(Region, BorrowKind, Lvalue<'tcx>), diff --git a/src/librustc_mir/visit.rs b/src/librustc_mir/visit.rs index 06a5c9fa9b7..b3ec2f10cf6 100644 --- a/src/librustc_mir/visit.rs +++ b/src/librustc_mir/visit.rs @@ -141,7 +141,7 @@ pub trait Visitor<'tcx> { Rvalue::Repeat(ref value, ref len) => { self.visit_operand(value); - self.visit_operand(len); + self.visit_constant(len); } Rvalue::Ref(r, bk, ref path) => { diff --git a/src/librustc_trans/trans/mir/rvalue.rs b/src/librustc_trans/trans/mir/rvalue.rs index ad89ee79de4..218edc200d4 100644 --- a/src/librustc_trans/trans/mir/rvalue.rs +++ b/src/librustc_trans/trans/mir/rvalue.rs @@ -49,8 +49,14 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { unimplemented!() } - mir::Rvalue::Repeat(..) => { - unimplemented!() + mir::Rvalue::Repeat(ref elem, ref count) => { + let elem = self.trans_operand(bcx, elem); + let size = self.trans_constant(bcx, count); + let base = expr::get_dataptr(bcx, lldest); + tvec::iter_vec_raw(bcx, base, elem.ty, size, |b, vref, _| { + build::Store(b, elem.llval, vref); + b + }) } mir::Rvalue::Aggregate(_, ref operands) => { diff --git a/src/test/run-pass/mir_trans_array.rs b/src/test/run-pass/mir_trans_array.rs new file mode 100644 index 00000000000..e6ffb895825 --- /dev/null +++ b/src/test/run-pass/mir_trans_array.rs @@ -0,0 +1,21 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![feature(rustc_attrs)] + +#[rustc_mir] +fn into_inner() -> [u64; 1024] { + let mut x = 10 + 20; + [x; 1024] +} + +fn main(){ + let x: &[u64] = &[30; 1024]; + assert_eq!(&into_inner()[..], x); +} diff --git a/src/test/run-pass/mir_trans_array_2.rs b/src/test/run-pass/mir_trans_array_2.rs new file mode 100644 index 00000000000..4aa686298e9 --- /dev/null +++ b/src/test/run-pass/mir_trans_array_2.rs @@ -0,0 +1,20 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![feature(rustc_attrs)] + +#[rustc_mir] +fn into_inner(x: u64) -> [u64; 1024] { + [x; 2*4*8*16] +} + +fn main(){ + let x: &[u64] = &[42; 1024]; + assert_eq!(&into_inner(42)[..], x); +}