summaryrefslogtreecommitdiffstats
path: root/src/test/ui/mir/mir_assign_eval_order.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/mir/mir_assign_eval_order.rs')
-rw-r--r--src/test/ui/mir/mir_assign_eval_order.rs67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/test/ui/mir/mir_assign_eval_order.rs b/src/test/ui/mir/mir_assign_eval_order.rs
new file mode 100644
index 000000000..799bf7f3a
--- /dev/null
+++ b/src/test/ui/mir/mir_assign_eval_order.rs
@@ -0,0 +1,67 @@
+// Test evaluation order of assignment expressions is right to left.
+
+// run-pass
+
+// We would previously not finish evaluating borrow and FRU expressions before
+// starting on the LHS
+
+struct S(i32);
+
+fn evaluate_reborrow_before_assign() {
+ let mut x = &1;
+ let y = &mut &2;
+ let z = &3;
+ // There's an implicit reborrow of `x` on the right-hand side of the
+ // assignment. Note that writing an explicit reborrow would not show this
+ // bug, as now there would be two reborrows on the right-hand side and at
+ // least one of them would happen before the left-hand side is evaluated.
+ *{ x = z; &mut *y } = x;
+ assert_eq!(*x, 3);
+ assert_eq!(**y, 1); // y should be assigned the original value of `x`.
+}
+
+fn evaluate_mut_reborrow_before_assign() {
+ let mut x = &mut 1;
+ let y = &mut &mut 2;
+ let z = &mut 3;
+ *{ x = z; &mut *y } = x;
+ assert_eq!(*x, 3);
+ assert_eq!(**y, 1); // y should be assigned the original value of `x`.
+}
+
+// We should evaluate `x[2]` and borrow the value out *before* evaluating the
+// LHS and changing its value.
+fn evaluate_ref_to_temp_before_assign_slice() {
+ let mut x = &[S(0), S(1), S(2)][..];
+ let y = &mut &S(7);
+ *{ x = &[S(3), S(4), S(5)]; &mut *y } = &x[2];
+ assert_eq!(2, y.0);
+ assert_eq!(5, x[2].0);
+}
+
+// We should evaluate `x[2]` and copy the value out *before* evaluating the LHS
+// and changing its value.
+fn evaluate_fru_to_temp_before_assign_slice() {
+ let mut x = &[S(0), S(1), S(2)][..];
+ let y = &mut S(7);
+ *{ x = &[S(3), S(4), S(5)]; &mut *y } = S { ..x[2] };
+ assert_eq!(2, y.0);
+ assert_eq!(5, x[2].0);
+}
+
+// We should evaluate `*x` and copy the value out *before* evaluating the LHS
+// and dropping `x`.
+fn evaluate_fru_to_temp_before_assign_box() {
+ let x = Box::new(S(0));
+ let y = &mut S(1);
+ *{ drop(x); &mut *y } = S { ..*x };
+ assert_eq!(0, y.0);
+}
+
+fn main() {
+ evaluate_reborrow_before_assign();
+ evaluate_mut_reborrow_before_assign();
+ evaluate_ref_to_temp_before_assign_slice();
+ evaluate_fru_to_temp_before_assign_slice();
+ evaluate_fru_to_temp_before_assign_box();
+}