Skip to content

Commit

Permalink
[compiler-v2] Fix issue with autoref of variant field selection (#14312)
Browse files Browse the repository at this point in the history
Fixes #14300

When recently introducing the new VariantField selection ops, the logic for autoref for such operations wasn't updated.

Adds the test from the bug, as well as moves another test already failing earlier into bytecode generator test suite. Also completes the test to ensure all scenarios of variant field selection update are covered. Adds that test also to transactional test to ensure correct execution behavior.
  • Loading branch information
wrwg authored Aug 19, 2024
1 parent 0097a21 commit 7964b40
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 51 deletions.
4 changes: 3 additions & 1 deletion third_party/move/move-compiler-v2/src/bytecode_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,9 @@ impl<'env> Generator<'env> {
match exp.as_ref() {
ExpData::Temporary(_, temp) if !with_forced_temp => *temp,
ExpData::LocalVar(id, sym) if !with_forced_temp => self.find_local(*id, *sym),
ExpData::Call(id, Operation::Select(..), _) if self.reference_mode() => {
ExpData::Call(id, Operation::Select(..) | Operation::SelectVariants(..), _)
if self.reference_mode() =>
{
// In reference mode, a selection is interpreted as selecting a reference to the
// field.
let ty =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// -- Model dump before bytecode pipeline
module 0x815::m {
enum CommonFields {
Foo {
x: u64,
y: u8,
}
Bar {
x: u64,
y: u8,
z: u32,
}
Baz {
y: u8,
}
}
private fun update_common_field(): u64 {
{
let common: m::CommonFields = pack m::CommonFields::Bar(30, 40, 50);
select_variants m::CommonFields.Foo.x|m::CommonFields.Bar.x<m::CommonFields>(common) = 15;
select_variants m::CommonFields.Foo.x|m::CommonFields.Bar.x<m::CommonFields>(common)
}
}
private fun update_common_field_different_offset(): u8 {
{
let common: m::CommonFields = pack m::CommonFields::Bar(30, 40, 50);
select_variants m::CommonFields.Foo.y|m::CommonFields.Bar.y|m::CommonFields.Baz.y<m::CommonFields>(common) = 15;
select_variants m::CommonFields.Foo.y|m::CommonFields.Bar.y|m::CommonFields.Baz.y<m::CommonFields>(common)
}
}
private fun update_non_common_field(): u32 {
{
let common: m::CommonFields = pack m::CommonFields::Bar(30, 40, 50);
select_variants m::CommonFields.Bar.z<m::CommonFields>(common) = 15;
select_variants m::CommonFields.Bar.z<m::CommonFields>(common)
}
}
} // end 0x815::m

============ initial bytecode ================

[variant baseline]
fun m::update_common_field(): u64 {
var $t0: u64
var $t1: m::CommonFields
var $t2: u64
var $t3: u8
var $t4: u32
var $t5: u64
var $t6: &mut u64
var $t7: &mut m::CommonFields
var $t8: &m::CommonFields
var $t9: &u64
0: $t2 := 30
1: $t3 := 40
2: $t4 := 50
3: $t1 := pack_variant m::CommonFields::Bar($t2, $t3, $t4)
4: $t5 := 15
5: $t7 := borrow_local($t1)
6: $t6 := borrow_variant_field<m::CommonFields::Foo|Bar>.x($t7)
7: write_ref($t6, $t5)
8: $t8 := borrow_local($t1)
9: $t9 := borrow_variant_field<m::CommonFields::Foo|Bar>.x($t8)
10: $t0 := read_ref($t9)
11: return $t0
}


[variant baseline]
fun m::update_common_field_different_offset(): u8 {
var $t0: u8
var $t1: m::CommonFields
var $t2: u64
var $t3: u8
var $t4: u32
var $t5: u8
var $t6: &mut u8
var $t7: &mut m::CommonFields
var $t8: bool
var $t9: &m::CommonFields
var $t10: &u8
var $t11: bool
0: $t2 := 30
1: $t3 := 40
2: $t4 := 50
3: $t1 := pack_variant m::CommonFields::Bar($t2, $t3, $t4)
4: $t5 := 15
5: $t7 := borrow_local($t1)
6: $t8 := test_variant m::CommonFields::Foo($t7)
7: if ($t8) goto 13 else goto 8
8: label L3
9: $t8 := test_variant m::CommonFields::Bar($t7)
10: if ($t8) goto 13 else goto 11
11: label L4
12: goto 16
13: label L2
14: $t6 := borrow_variant_field<m::CommonFields::Foo|Bar>.y($t7)
15: goto 18
16: label L1
17: $t6 := borrow_variant_field<m::CommonFields::Baz>.y($t7)
18: label L0
19: write_ref($t6, $t5)
20: $t9 := borrow_local($t1)
21: $t11 := test_variant m::CommonFields::Foo($t9)
22: if ($t11) goto 28 else goto 23
23: label L8
24: $t11 := test_variant m::CommonFields::Bar($t9)
25: if ($t11) goto 28 else goto 26
26: label L9
27: goto 31
28: label L7
29: $t10 := borrow_variant_field<m::CommonFields::Foo|Bar>.y($t9)
30: goto 33
31: label L6
32: $t10 := borrow_variant_field<m::CommonFields::Baz>.y($t9)
33: label L5
34: $t0 := read_ref($t10)
35: return $t0
}


[variant baseline]
fun m::update_non_common_field(): u32 {
var $t0: u32
var $t1: m::CommonFields
var $t2: u64
var $t3: u8
var $t4: u32
var $t5: u32
var $t6: &mut u32
var $t7: &mut m::CommonFields
var $t8: &m::CommonFields
var $t9: &u32
0: $t2 := 30
1: $t3 := 40
2: $t4 := 50
3: $t1 := pack_variant m::CommonFields::Bar($t2, $t3, $t4)
4: $t5 := 15
5: $t7 := borrow_local($t1)
6: $t6 := borrow_variant_field<m::CommonFields::Bar>.z($t7)
7: write_ref($t6, $t5)
8: $t8 := borrow_local($t1)
9: $t9 := borrow_variant_field<m::CommonFields::Bar>.z($t8)
10: $t0 := read_ref($t9)
11: return $t0
}


============ bytecode verification succeeded ========
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module 0x815::m {

enum CommonFields has drop {
Foo{x: u64, y: u8},
Bar{x: u64, y: u8, z: u32}
Baz{y: u8}
}

fun update_common_field(): u64 {
let common = CommonFields::Bar {
x: 30,
y: 40,
z: 50
};
common.x = 15;
common.x
}

fun update_non_common_field(): u32 {
let common = CommonFields::Bar {
x: 30,
y: 40,
z: 50
};
common.z = 15;
common.z
}

fun update_common_field_different_offset(): u8 {
let common = CommonFields::Bar {
x: 30,
y: 40,
z: 50
};
common.y = 15;
common.y
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// -- Model dump before bytecode pipeline
module 0x815::m {
enum Positional {
A {
0: u8,
}
B {
0: u8,
}
}
private fun test_common_access(): u8 {
{
let x: m::Positional = pack m::Positional::A(42);
select_variants m::Positional.A.0|m::Positional.B.0<m::Positional>(x) = 19;
20
}
}
} // end 0x815::m

============ initial bytecode ================

[variant baseline]
fun m::test_common_access(): u8 {
var $t0: u8
var $t1: m::Positional
var $t2: u8
var $t3: u8
var $t4: &mut u8
var $t5: &mut m::Positional
0: $t2 := 42
1: $t1 := pack_variant m::Positional::A($t2)
2: $t3 := 19
3: $t5 := borrow_local($t1)
4: $t4 := borrow_variant_field<m::Positional::A|B>.0($t5)
5: write_ref($t4, $t3)
6: $t0 := 20
7: return $t0
}


============ bytecode verification succeeded ========
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module 0x815::m {

enum Positional has drop {
A(u8),
B(u8),
}
fun test_common_access(): u8 {
let x = Positional::A(42);
x.0 = 19;
20
}

}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
processed 4 tasks

task 1 'run'. lines 41-41:
return values: 15

task 2 'run'. lines 43-43:
return values: 15

task 3 'run'. lines 45-45:
return values: 15
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//# publish
module 0x815::m {

enum CommonFields has drop {
Foo{x: u64, y: u8},
Bar{x: u64, y: u8, z: u32}
Baz{y: u8}
}

fun update_common_field(): u64 {
let common = CommonFields::Bar {
x: 30,
y: 40,
z: 50
};
common.x = 15;
common.x
}

fun update_non_common_field(): u32 {
let common = CommonFields::Bar {
x: 30,
y: 40,
z: 50
};
common.z = 15;
common.z
}

fun update_common_field_different_offset(): u8 {
let common = CommonFields::Bar {
x: 30,
y: 40,
z: 50
};
common.y = 15;
common.y
}
}

//# run 0x815::m::update_common_field

//# run 0x815::m::update_non_common_field

//# run 0x815::m::update_common_field_different_offset

0 comments on commit 7964b40

Please sign in to comment.