From 75f9429d03774dbf88019205316def552d0d5ae2 Mon Sep 17 00:00:00 2001 From: Wolfgang Grieskamp Date: Mon, 26 Feb 2024 00:56:11 -0800 Subject: [PATCH] Adapting freeze to new analysis, fixing a bug in reference analysis --- .../pipeline/reference_safety_processor.rs | 84 +++++---- .../tests/checking/inlining/bug_11112.exp | 19 +- .../tests/checking/inlining/lambda_cast.exp | 13 -- .../tests/file-format-generator/vector.exp | 25 --- .../tests/reference-safety/eq_ref.move | 2 +- .../tests/reference-safety/freeze.move | 34 ++++ .../reference-safety/multiple_use_invalid.exp | 6 +- .../v1-tests/borrow_field_combo.exp | 170 +++--------------- .../v1-tests/borrow_field_full.exp | 158 +++------------- .../v1-tests/call_mutual_borrows_invalid.exp | 18 +- .../v1-tests/call_ordering.exp | 17 +- .../v1-tests/mutate_full_invalid.exp | 52 +++--- .../return_mutual_borrows_invalid.exp | 14 +- 13 files changed, 195 insertions(+), 417 deletions(-) create mode 100644 third_party/move/move-compiler-v2/tests/reference-safety/freeze.move diff --git a/third_party/move/move-compiler-v2/src/pipeline/reference_safety_processor.rs b/third_party/move/move-compiler-v2/src/pipeline/reference_safety_processor.rs index 81ef82f2412a1a..2ac78cc39bc3df 100644 --- a/third_party/move/move-compiler-v2/src/pipeline/reference_safety_processor.rs +++ b/third_party/move/move-compiler-v2/src/pipeline/reference_safety_processor.rs @@ -216,6 +216,8 @@ enum BorrowEdgeKind { /// call outcome can be different, they are distinguished by code offset -- two call edges are never the /// same. Call(bool, Operation, CodeOffset), + /// Freezes a mutable reference. + Freeze, } impl BorrowEdgeKind { @@ -226,16 +228,7 @@ impl BorrowEdgeKind { | BorrowGlobal(is_mut) | BorrowField(is_mut, _) | Call(is_mut, _, _) => *is_mut, - } - } - - fn set_mut(&mut self, value: bool) { - use BorrowEdgeKind::*; - match self { - BorrowLocal(is_mut) - | BorrowGlobal(is_mut) - | BorrowField(is_mut, _) - | Call(is_mut, _, _) => *is_mut = value, + Freeze => false, } } } @@ -1020,7 +1013,15 @@ impl<'env, 'state> LifetimeAnalysisStep<'env, 'state> { /// /// If we walk this graph now from the root to the leaves, we can determine safety by directly comparing /// hyper edge siblings. - fn check_borrow_safety(&mut self, temps: &BTreeSet) { + fn check_borrow_safety(&mut self, temps_vec: &[TempIndex]) { + // First check direct duplicates + for (i, temp) in temps_vec.iter().enumerate() { + if temps_vec[i + 1..].contains(temp) { + self.exclusive_access_direct_dup_error(*temp) + } + } + // Now build and analyze the hyper graph + let temps = &temps_vec.iter().cloned().collect::>(); let filtered_leaves = self .state .leaves() @@ -1083,9 +1084,9 @@ impl<'env, 'state> LifetimeAnalysisStep<'env, 'state> { let target = edge.target; targets.insert(target); if edge.kind.is_mut() { - if let Some(temps) = filtered_leaves.get(&target) { + if let Some(ts) = filtered_leaves.get(&target) { let mut inter = - temps.intersection(temps).cloned().collect::>(); + ts.intersection(temps).cloned().collect::>(); if !inter.is_empty() { if !self.state.is_leaf(&target) { // A mut leaf node must have exclusive access @@ -1098,7 +1099,7 @@ impl<'env, 'state> LifetimeAnalysisStep<'env, 'state> { } if mapped_temps.len() > 1 { // We cannot associate the same mut node with more than one local - self.exclusive_access_dup_error(&hyper, &mapped_temps) + self.exclusive_access_indirect_dup_error(&hyper, &mapped_temps) } hyper_nodes.insert(targets); } @@ -1171,8 +1172,9 @@ impl<'env, 'state> LifetimeAnalysisStep<'env, 'state> { } /// Reports an error about exclusive access requirement for duplicate usage. See safety - /// condition (d) in the file header documentation. - fn exclusive_access_dup_error( + /// condition (d) in the file header documentation. This handles the case were the + /// same node is used by multiple temps + fn exclusive_access_indirect_dup_error( &self, labels: &BTreeSet, temps: &BTreeSet, @@ -1182,7 +1184,7 @@ impl<'env, 'state> LifetimeAnalysisStep<'env, 'state> { self.error_with_hints( self.cur_loc(), format!( - "same mutable reference in {} is also used in other {} in same argument list", + "same mutable reference in {} is also used in other {} in argument list", self.display(*ts[0]), self.display(*ts[1]) ), @@ -1191,6 +1193,21 @@ impl<'env, 'state> LifetimeAnalysisStep<'env, 'state> { ) } + /// Reports an error about exclusive access requirement for duplicate usage. See safety + /// condition (d) in the file header documentation. This handles the case were the + /// same local is used multiple times. + fn exclusive_access_direct_dup_error(&self, temp: TempIndex) { + self.error_with_hints( + self.cur_loc(), + format!( + "same mutable reference in {} is used again in argument list", + self.display(temp), + ), + "requirement enforced here", + iter::empty(), + ) + } + /// Reports an error together with hints fn error_with_hints( &self, @@ -1262,6 +1279,7 @@ impl<'env, 'state> LifetimeAnalysisStep<'env, 'state> { BorrowGlobal(_) => "global borrow", BorrowField(..) => "field borrow", Call(..) => "call result", + Freeze => "freeze", },), ) } @@ -1474,18 +1492,12 @@ impl<'env, 'state> LifetimeAnalysisStep<'env, 'state> { .label_for_temp(src) .expect("label for reference") .clone(); - let redirected = self.state.make_temp(dest, code_offset, 0, false); - for (parent, mut edge) in self - .state - .parent_edges(&label) - .map(|(p, e)| (p, e.clone())) - .collect::>() - // need to mutate state - { - edge.target = redirected.clone(); - edge.kind.set_mut(false); - self.state.add_edge(parent, edge) - } + let target = self.state.make_temp(dest, code_offset, 0, false); + self.state.add_edge(label, BorrowEdge { + kind: BorrowEdgeKind::Freeze, + loc: self.cur_loc(), + target, + }) } /// Process a MoveFrom instruction. @@ -1614,14 +1626,21 @@ impl<'env> TransferFunctions for LifeTimeAnalysis<'env> { | Operation::Function(..) | Operation::Eq | Operation::Neq => { - let exclusive_refs = - srcs.iter().filter(|t| step.is_ref(**t)).cloned().collect(); + let exclusive_refs = srcs + .iter() + .filter(|t| step.is_ref(**t)) + .cloned() + .collect_vec(); step.check_borrow_safety(&exclusive_refs) }, _ => {}, }, Ret(_, srcs) => { - let exclusive_refs = srcs.iter().filter(|t| step.is_ref(**t)).cloned().collect(); + let exclusive_refs = srcs + .iter() + .filter(|t| step.is_ref(**t)) + .cloned() + .collect_vec(); step.check_borrow_safety(&exclusive_refs) }, _ => {}, @@ -1816,6 +1835,7 @@ impl<'a> Display for BorrowEdgeDisplay<'a> { BorrowGlobal(is_mut) => write!(f, "borrow_global({})", is_mut), BorrowField(is_mut, _) => write!(f, "borrow_field({})", is_mut), Call(is_mut, _, _) => write!(f, "call({})", is_mut), + Freeze => write!(f, "freeze"), })?; if display_child { write!(f, " -> {}", edge.target) diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11112.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11112.exp index 0c1108fa061baf..31b2cbf2905839 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11112.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11112.exp @@ -235,23 +235,6 @@ fun vectors::test_for_each_mut() { 44: return () } - -Diagnostics: -error: cannot mutably borrow since immutable references exist - ┌─ tests/checking/inlining/bug_11112.move:8:23 - │ - 8 │ vector::for_each_mut(&mut v, |e| { *e = s; s = s + 1 }); - │ ---------------------^^^^^^---------------------------- - │ │ │ - │ │ mutable borrow attempted here - │ │ previous local borrow - │ from a call inlined at this callsite - │ - ┌─ /Users/wrwg/aptos-core/third_party/move/move-compiler-v2/../move-stdlib/sources/vector.move:181:20 - │ -181 │ while (i < length(v)) { - │ --------- requirement enforced here - ============ after ReferenceSafetyProcessor: ================ [variant baseline] @@ -374,7 +357,7 @@ fun vectors::test_for_each_mut() { # 12: $t13 := freeze_ref($t7) # live vars: $t0, $t5, $t7, $t9, $t13 - # graph: {@700=local($t0)[borrow(false) -> @C00,borrow(true) -> @701],@701=derived[],@C00=derived[]} + # graph: {@700=local($t0)[borrow(true) -> @701],@701=derived[freeze -> @C00],@C00=derived[]} # locals: {$t0=@700,$t7=@701,$t13=@C00} # globals: {} # moved: {$t2,$t3,$t4,$t7,$t12,$t13,$t17,$t19} diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast.exp index daa84fd48a5a41..6462e35c10d980 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast.exp @@ -72,16 +72,3 @@ module 0x12391283::M { spec fun $test_1(): u64; spec fun $test_2(): u64; } // end 0x12391283::M - - -Diagnostics: -error: cannot mutably borrow since immutable references exist - ┌─ /Users/wrwg/aptos-core/third_party/move/move-compiler-v2/../move-stdlib/sources/vector.move:65:33 - │ -65 │ public fun reverse(v: &mut vector) { - │ ^ - │ │ - │ mutable borrow attempted here - │ previous local borrow -66 │ let len = length(v); - │ --------- requirement enforced here diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/vector.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/vector.exp index 8e055bdc07bac7..e78048582a81ee 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/vector.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/vector.exp @@ -1,29 +1,4 @@ -Diagnostics: -error: cannot mutably borrow since immutable references exist - ┌─ tests/file-format-generator/vector.move:13:32 - │ -13 │ public fun remove(v: &mut vector, i: u64): Element { - │ ^ - │ │ - │ mutable borrow attempted here - │ previous local borrow -14 │ use std::vector; -15 │ let len = vector::length(v); - │ ----------------- requirement enforced here - -error: cannot mutably borrow since immutable references exist - ┌─ /Users/wrwg/aptos-core/third_party/move/move-compiler-v2/../move-stdlib/sources/vector.move:65:33 - │ -65 │ public fun reverse(v: &mut vector) { - │ ^ - │ │ - │ mutable borrow attempted here - │ previous local borrow -66 │ let len = length(v); - │ --------- requirement enforced here - - ============ disassembled file-format ================== // Move bytecode v7 module 42.vector { diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/eq_ref.move b/third_party/move/move-compiler-v2/tests/reference-safety/eq_ref.move index b98a177cfe38a0..13120c9d78c431 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/eq_ref.move +++ b/third_party/move/move-compiler-v2/tests/reference-safety/eq_ref.move @@ -13,6 +13,6 @@ module 0x42::m { } fun mut_ref_id(x: u64) { - &mut x == &mut x; // error expected, will be fixed with new reference safety + &mut x == &mut x; } } diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/freeze.move b/third_party/move/move-compiler-v2/tests/reference-safety/freeze.move new file mode 100644 index 00000000000000..1a0c2d820a4e0e --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/reference-safety/freeze.move @@ -0,0 +1,34 @@ +module 0x42::m { + + fun ref_mut_mut(x: &mut u64, y: &mut u64) { + x == y; + } + + fun ref_imm_mut(x: &u64, y: &mut u64) { + x == y; + } + + fun ref_imm_imm(x: &u64, y: &u64) { + x == y; + } + + fun f1() { + let x = 1; + let r = &mut x; + ref_mut_mut(r, r); // error + } + + fun f2() { + let x = 1; + let r = &mut x; + ref_imm_mut(r, r); // error + } + + fun f3() { + let x = 1; + let r = &mut x; + ref_imm_imm(r, r); // ok + } + + +} diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.exp b/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.exp index 37b7b8a1e22790..acaf1e69915e5c 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/multiple_use_invalid.exp @@ -1,6 +1,6 @@ Diagnostics: -error: same mutable reference in value is also used in other value in same argument list +error: same mutable reference in value is also used in other value in argument list ┌─ tests/reference-safety/multiple_use_invalid.move:5:9 │ 5 │ s(&mut s.x, &mut s.x) @@ -10,7 +10,7 @@ error: same mutable reference in value is also used in other value in same argum │ │ previous mutable field borrow │ requirement enforced here -error: same mutable reference in local `r` is also used in other local `x` in same argument list +error: same mutable reference in local `r` is also used in other local `x` in argument list ┌─ tests/reference-safety/multiple_use_invalid.move:11:9 │ 9 │ let r = &mut s.x; @@ -19,7 +19,7 @@ error: same mutable reference in local `r` is also used in other local `x` in sa 11 │ s(r, x) │ ^^^^^^^ requirement enforced here -error: same mutable reference in local `r1` is also used in other local `r2` in same argument list +error: same mutable reference in local `r1` is also used in other local `r2` in argument list ┌─ tests/reference-safety/multiple_use_invalid.move:20:9 │ 18 │ let r1 = &mut x; diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/borrow_field_combo.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/borrow_field_combo.exp index 2feac19d9a0db2..8d6675b7312382 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/borrow_field_combo.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/borrow_field_combo.exp @@ -1,179 +1,65 @@ Diagnostics: -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:30:21 +error: mutable reference in local `inner` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:34:9 │ -30 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow - · +31 │ let c; if (cond) c = freeze(copy inner) else c = &other.s1; + │ ------------------ previous freeze +32 │ let f1 = &inner.f1; + │ --------- previous field borrow 33 │ *c; - │ -- requirement enforced here - · -37 │ *c; - │ -- conflicting reference `c`used here - · -40 │ let c; if (cond) c = id(freeze(copy inner)) else c = &other.s1; // error in v2 - │ --------- conflicting reference `other`used here - -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:30:21 - │ -30 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow - · 34 │ *inner; - │ ------ requirement enforced here - · -37 │ *c; - │ -- conflicting reference `c`used here - · -40 │ let c; if (cond) c = id(freeze(copy inner)) else c = &other.s1; // error in v2 - │ --------- conflicting reference `other`used here - -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:30:21 - │ -30 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow - · + │ ^^^^^^ requirement enforced here 35 │ *f1; - │ --- requirement enforced here + │ --- conflicting reference `f1`used here 36 │ *inner; 37 │ *c; │ -- conflicting reference `c`used here - · -40 │ let c; if (cond) c = id(freeze(copy inner)) else c = &other.s1; // error in v2 - │ --------- conflicting reference `other`used here -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:30:21 +error: mutable reference in local `inner` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:36:9 │ -30 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow +31 │ let c; if (cond) c = freeze(copy inner) else c = &other.s1; + │ ------------------ previous freeze · 36 │ *inner; - │ ------ requirement enforced here + │ ^^^^^^ requirement enforced here 37 │ *c; │ -- conflicting reference `c`used here - · -40 │ let c; if (cond) c = id(freeze(copy inner)) else c = &other.s1; // error in v2 - │ --------- conflicting reference `other`used here error: mutable reference in local `inner` requires exclusive access but is borrowed - ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:34:9 - │ -32 │ let f1 = &inner.f1; - │ --------- previous field borrow -33 │ *c; -34 │ *inner; - │ ^^^^^^ requirement enforced here -35 │ *f1; - │ --- conflicting reference `f1`used here - -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:39:21 + ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:43:9 │ -39 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow 40 │ let c; if (cond) c = id(freeze(copy inner)) else c = &other.s1; // error in v2 - │ ---------------------- used by call result + │ ---------------------- + │ │ │ + │ │ previous freeze + │ used by call result 41 │ let f1 = &inner.f1; + │ --------- previous field borrow 42 │ *c; - │ -- requirement enforced here - · -46 │ *c; - │ -- conflicting reference `c`used here - -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:39:21 - │ -39 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow -40 │ let c; if (cond) c = id(freeze(copy inner)) else c = &other.s1; // error in v2 - │ ---------------------- used by call result - · 43 │ *inner; - │ ------ requirement enforced here - · -46 │ *c; - │ -- conflicting reference `c`used here - -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:39:21 - │ -39 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow -40 │ let c; if (cond) c = id(freeze(copy inner)) else c = &other.s1; // error in v2 - │ ---------------------- used by call result - · + │ ^^^^^^ requirement enforced here 44 │ *f1; - │ --- requirement enforced here + │ --- conflicting reference `f1`used here 45 │ *inner; 46 │ *c; │ -- conflicting reference `c`used here -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:39:21 +error: mutable reference in local `inner` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:45:9 │ -39 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow 40 │ let c; if (cond) c = id(freeze(copy inner)) else c = &other.s1; // error in v2 - │ ---------------------- used by call result + │ ---------------------- + │ │ │ + │ │ previous freeze + │ used by call result · 45 │ *inner; - │ ------ requirement enforced here + │ ^^^^^^ requirement enforced here 46 │ *c; │ -- conflicting reference `c`used here -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:39:21 - │ -39 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow -40 │ let c; if (cond) c = id(freeze(copy inner)) else c = &other.s1; // error in v2 - │ ---------------------- requirement enforced here - · -48 │ let inner = &mut outer.s1; - │ ------------- conflicting reference `outer`used here - -error: mutable reference in local `inner` requires exclusive access but is borrowed - ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:43:9 - │ -41 │ let f1 = &inner.f1; - │ --------- previous field borrow -42 │ *c; -43 │ *inner; - │ ^^^^^^ requirement enforced here -44 │ *f1; - │ --- conflicting reference `f1`used here - error: mutable reference in local `inner` requires exclusive access but is borrowed ┌─ tests/reference-safety/v1-tests/borrow_field_combo.move:86:9 │ diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/borrow_field_full.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/borrow_field_full.exp index a90d96dc272f0f..553d768350f72b 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/borrow_field_full.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/borrow_field_full.exp @@ -1,163 +1,61 @@ Diagnostics: -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:30:21 +error: mutable reference in local `inner` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:34:9 │ -30 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow - · +31 │ let c = freeze(inner); + │ ------------- previous freeze +32 │ let f1 = &inner.f1; + │ --------- previous field borrow 33 │ *c; - │ -- requirement enforced here - · -37 │ *c; - │ -- conflicting reference `c`used here - -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:30:21 - │ -30 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow - · 34 │ *inner; - │ ------ requirement enforced here - · -37 │ *c; - │ -- conflicting reference `c`used here - -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:30:21 - │ -30 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow - · + │ ^^^^^^ requirement enforced here 35 │ *f1; - │ --- requirement enforced here + │ --- conflicting reference `f1`used here 36 │ *inner; 37 │ *c; │ -- conflicting reference `c`used here -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:30:21 +error: mutable reference in local `inner` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:36:9 │ -30 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow +31 │ let c = freeze(inner); + │ ------------- previous freeze · 36 │ *inner; - │ ------ requirement enforced here + │ ^^^^^^ requirement enforced here 37 │ *c; │ -- conflicting reference `c`used here error: mutable reference in local `inner` requires exclusive access but is borrowed - ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:34:9 - │ -32 │ let f1 = &inner.f1; - │ --------- previous field borrow -33 │ *c; -34 │ *inner; - │ ^^^^^^ requirement enforced here -35 │ *f1; - │ --- conflicting reference `f1`used here - -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:39:21 + ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:43:9 │ -39 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow 40 │ let c = id(freeze(inner)); - │ ----------------- used by call result + │ ----------------- + │ │ │ + │ │ previous freeze + │ used by call result 41 │ let f1 = &inner.f1; + │ --------- previous field borrow 42 │ *c; - │ -- requirement enforced here - · -46 │ *c; - │ -- conflicting reference `c`used here - -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:39:21 - │ -39 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow -40 │ let c = id(freeze(inner)); - │ ----------------- used by call result - · 43 │ *inner; - │ ------ requirement enforced here - · -46 │ *c; - │ -- conflicting reference `c`used here - -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:39:21 - │ -39 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow -40 │ let c = id(freeze(inner)); - │ ----------------- used by call result - · + │ ^^^^^^ requirement enforced here 44 │ *f1; - │ --- requirement enforced here + │ --- conflicting reference `f1`used here 45 │ *inner; 46 │ *c; │ -- conflicting reference `c`used here -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:39:21 +error: mutable reference in local `inner` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:45:9 │ -39 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow 40 │ let c = id(freeze(inner)); - │ ----------------- used by call result + │ ----------------- + │ │ │ + │ │ previous freeze + │ used by call result · 45 │ *inner; - │ ------ requirement enforced here + │ ^^^^^^ requirement enforced here 46 │ *c; │ -- conflicting reference `c`used here - -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:39:21 - │ -39 │ let inner = &mut outer.s1; - │ ^^^^^^^^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous field borrow -40 │ let c = id(freeze(inner)); - │ ----------------- requirement enforced here - · -48 │ let inner = &mut outer.s1; - │ ------------- conflicting reference `outer`used here - -error: mutable reference in local `inner` requires exclusive access but is borrowed - ┌─ tests/reference-safety/v1-tests/borrow_field_full.move:43:9 - │ -41 │ let f1 = &inner.f1; - │ --------- previous field borrow -42 │ *c; -43 │ *inner; - │ ^^^^^^ requirement enforced here -44 │ *f1; - │ --- conflicting reference `f1`used here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.exp index 03f2a5ef6c6033..d434ee5ffc0dc7 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_mutual_borrows_invalid.exp @@ -1,16 +1,12 @@ Diagnostics: -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:13:12 +error: mutable reference in local `s1` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:15:9 │ -13 │ fun t0(s1: &mut S, _s2: &mut S) { - │ ^^ - │ │ - │ mutable borrow attempted here - │ previous local borrow 14 │ let f = freeze(s1); + │ ---------- previous freeze 15 │ mut_imm(s1, f); - │ -------------- requirement enforced here + │ ^^^^^^^^^^^^^^ requirement enforced here error: mutable reference in local `s1` requires exclusive access but is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:17:9 @@ -47,6 +43,12 @@ error: cannot mutably borrow since immutable references exist │ │ mutable borrow attempted here │ requirement enforced here +error: same mutable reference in local `s1` is used again in argument list + ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:23:9 + │ +23 │ mut_mut(s1, s1); + │ ^^^^^^^^^^^^^^^ requirement enforced here + error: mutable reference in local `s1` requires exclusive access but is borrowed ┌─ tests/reference-safety/v1-tests/call_mutual_borrows_invalid.move:25:9 │ diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_ordering.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_ordering.exp index 79ca8cbad28076..6dd19116b2918f 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_ordering.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/call_ordering.exp @@ -1,16 +1,11 @@ Diagnostics: -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/call_ordering.move:5:12 +error: cannot immutably borrow since mutable references exist + ┌─ tests/reference-safety/v1-tests/call_ordering.move:7:13 │ -5 │ fun t0(s: &mut S) { - │ ^ - │ │ - │ mutable borrow attempted here - │ previous local borrow 6 │ let f = &mut s.f; + │ -------- previous mutable field borrow 7 │ foo(freeze(s), { *f = 0; 1 }) - │ ----------------------------- - │ │ │ - │ │ requirement enforced here - │ conflicting reference used here + │ ^^^^^^^^^ ------ requirement enforced here + │ │ + │ immutable borrow attempted here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/mutate_full_invalid.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/mutate_full_invalid.exp index d6ff00710079fa..43abc189f1402d 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/mutate_full_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/mutate_full_invalid.exp @@ -1,42 +1,44 @@ Diagnostics: -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/mutate_full_invalid.move:16:17 +error: cannot write to reference in local `x` which is still borrowed + ┌─ tests/reference-safety/v1-tests/mutate_full_invalid.move:18:9 + │ +17 │ let f = freeze(x); + │ --------- previous freeze +18 │ *x = 0; + │ ^^^^^^ written here + +error: mutable reference in local `x` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/mutate_full_invalid.move:18:9 │ -16 │ let x = &mut 0; - │ ^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous local borrow 17 │ let f = freeze(x); + │ --------- previous freeze 18 │ *x = 0; - │ ------ requirement enforced here + │ ^^^^^^ requirement enforced here 19 │ *f; │ -- conflicting reference `f`used here -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/mutate_full_invalid.move:21:17 +error: cannot write to reference in local `x` which is still borrowed + ┌─ tests/reference-safety/v1-tests/mutate_full_invalid.move:23:9 │ -21 │ let x = &mut 0; - │ ^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous local borrow 22 │ let f = id(x); - │ ----- requirement enforced here + │ ----- + │ │ │ + │ │ previous freeze + │ used by call result +23 │ *x = 0; + │ ^^^^^^ written here -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/mutate_full_invalid.move:21:17 +error: mutable reference in local `x` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/mutate_full_invalid.move:23:9 │ -21 │ let x = &mut 0; - │ ^^^^^^ - │ │ - │ mutable borrow attempted here - │ previous local borrow 22 │ let f = id(x); - │ ----- used by call result + │ ----- + │ │ │ + │ │ previous freeze + │ used by call result 23 │ *x = 0; - │ ------ requirement enforced here + │ ^^^^^^ requirement enforced here 24 │ *f; │ -- conflicting reference `f`used here diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/return_mutual_borrows_invalid.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/return_mutual_borrows_invalid.exp index 54887a6db8a86e..a633b698b8dfcc 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/return_mutual_borrows_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/return_mutual_borrows_invalid.exp @@ -1,16 +1,12 @@ Diagnostics: -error: cannot mutably borrow since immutable references exist - ┌─ tests/reference-safety/v1-tests/return_mutual_borrows_invalid.move:14:19 +error: mutable reference in local `return[0]` requires exclusive access but is borrowed + ┌─ tests/reference-safety/v1-tests/return_mutual_borrows_invalid.move:16:9 │ -14 │ fun mut_imm_0(s1: &mut S): (&mut S, &S) { - │ ^^ - │ │ - │ mutable borrow attempted here - │ previous local borrow 15 │ let f = freeze(s1); + │ ---------- previous freeze 16 │ (s1, f) - │ ------- requirement enforced here + │ ^^^^^^^ requirement enforced here error: mutable reference in local `return[0]` requires exclusive access but is borrowed ┌─ tests/reference-safety/v1-tests/return_mutual_borrows_invalid.move:20:9 @@ -45,7 +41,7 @@ error: cannot mutably borrow since immutable references exist │ │mutable borrow attempted here │ requirement enforced here -error: same mutable reference in local `return[0]` is also used in other local `return[1]` in same argument list +error: same mutable reference in local `return[0]` is also used in other local `return[1]` in argument list ┌─ tests/reference-safety/v1-tests/return_mutual_borrows_invalid.move:32:9 │ 31 │ fun mut_mut_0(s1: &mut S): (&mut S, &mut S) {