Generate a direct assignment in MIR for let x = y;
This commit is contained in:
parent
4aff10bb1b
commit
9185bb3061
@ -11,7 +11,6 @@
|
||||
//! See docs in build/expr/mod.rs
|
||||
|
||||
use build::{BlockAnd, BlockAndExtension, Builder};
|
||||
use build::expr::category::Category;
|
||||
use hair::*;
|
||||
use rustc::middle::region;
|
||||
use rustc::mir::*;
|
||||
@ -57,23 +56,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
});
|
||||
}
|
||||
|
||||
// Careful here not to cause an infinite cycle. If we always
|
||||
// called `into`, then for places like `x.f`, it would
|
||||
// eventually fallback to us, and we'd loop. There's a reason
|
||||
// for this: `as_temp` is the point where we bridge the "by
|
||||
// reference" semantics of `as_place` with the "by value"
|
||||
// semantics of `into`, `as_operand`, `as_rvalue`, and (of
|
||||
// course) `as_temp`.
|
||||
match Category::of(&expr.kind).unwrap() {
|
||||
Category::Place => {
|
||||
let place = unpack!(block = this.as_place(block, expr));
|
||||
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
|
||||
this.cfg.push_assign(block, source_info, &Place::Local(temp), rvalue);
|
||||
}
|
||||
_ => {
|
||||
unpack!(block = this.into(&Place::Local(temp), block, expr));
|
||||
}
|
||||
}
|
||||
unpack!(block = this.into(&Place::Local(temp), block, expr));
|
||||
|
||||
// In constants, temp_lifetime is None. We should not need to drop
|
||||
// anything because no values with a destructor can be created in
|
||||
|
@ -288,6 +288,37 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
block.unit()
|
||||
}
|
||||
|
||||
// Avoid creating a temporary
|
||||
ExprKind::VarRef { .. } |
|
||||
ExprKind::SelfRef |
|
||||
ExprKind::StaticRef { .. } => {
|
||||
debug_assert!(Category::of(&expr.kind) == Some(Category::Place));
|
||||
|
||||
let place = unpack!(block = this.as_place(block, expr));
|
||||
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
|
||||
this.cfg.push_assign(block, source_info, destination, rvalue);
|
||||
block.unit()
|
||||
}
|
||||
ExprKind::Index { .. } |
|
||||
ExprKind::Deref { .. } |
|
||||
ExprKind::Field { .. } => {
|
||||
debug_assert!(Category::of(&expr.kind) == Some(Category::Place));
|
||||
|
||||
// Create a "fake" temporary variable so that we check that the
|
||||
// value is Sized. Usually, this is caught in type checking, but
|
||||
// in the case of box expr there is no such check.
|
||||
if let Place::Projection(..) = destination {
|
||||
this.local_decls.push(LocalDecl::new_temp(expr.ty, expr.span));
|
||||
}
|
||||
|
||||
debug_assert!(Category::of(&expr.kind) == Some(Category::Place));
|
||||
|
||||
let place = unpack!(block = this.as_place(block, expr));
|
||||
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
|
||||
this.cfg.push_assign(block, source_info, destination, rvalue);
|
||||
block.unit()
|
||||
}
|
||||
|
||||
// these are the cases that are more naturally handled by some other mode
|
||||
ExprKind::Unary { .. } |
|
||||
ExprKind::Binary { .. } |
|
||||
@ -300,18 +331,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
ExprKind::Unsize { .. } |
|
||||
ExprKind::Repeat { .. } |
|
||||
ExprKind::Borrow { .. } |
|
||||
ExprKind::VarRef { .. } |
|
||||
ExprKind::SelfRef |
|
||||
ExprKind::StaticRef { .. } |
|
||||
ExprKind::Array { .. } |
|
||||
ExprKind::Tuple { .. } |
|
||||
ExprKind::Adt { .. } |
|
||||
ExprKind::Closure { .. } |
|
||||
ExprKind::Index { .. } |
|
||||
ExprKind::Deref { .. } |
|
||||
ExprKind::Literal { .. } |
|
||||
ExprKind::Yield { .. } |
|
||||
ExprKind::Field { .. } => {
|
||||
ExprKind::Yield { .. } => {
|
||||
debug_assert!(match Category::of(&expr.kind).unwrap() {
|
||||
Category::Rvalue(RvalueFunc::Into) => false,
|
||||
_ => true,
|
||||
|
@ -65,7 +65,7 @@
|
||||
//! which can fallback to `into`. So if one of the `ExprKind` variants is not, in fact,
|
||||
//! implemented in the category where it is supposed to be, there will be a problem.
|
||||
//!
|
||||
//! Of those fallbacks, the most interesting one is `as_temp`, because
|
||||
//! Of those fallbacks, the most interesting one is `into`, because
|
||||
//! it discriminates based on the category of the expression. This is
|
||||
//! basically the point where the "by value" operations are bridged
|
||||
//! over to the "by reference" mode (`as_place`).
|
||||
|
Loading…
Reference in New Issue
Block a user