//! > Test reboxing
//! > test_runner_name
test_reboxing_analysis
//! > function_name
main
//! > module_code
#[derive(Drop, Copy)]
struct A {
a: felt252,
b: felt252,
}
//! > function_code
fn main(a: Box<A>) -> Box<felt252> {
BoxTrait::new(a.b)
}
//! > semantic_diagnostics
//! > lowering_diagnostics
//! > candidates
v4
//! > before
Parameters: v0: core::box::Box::<test::A>
blk0 (root):
Statements:
(v1: test::A) <- unbox(v0)
(v2: core::felt252, v3: core::felt252) <- struct_destructure(v1)
(v4: core::box::Box::<core::felt252>) <- into_box(v3)
End:
Return(v4)
//! > after
Parameters: v0: core::box::Box::<test::A>
blk0 (root):
Statements:
(v1: test::A) <- unbox(v0)
(v5: core::box::Box::<core::felt252>, v6: core::box::Box::<core::felt252>) <- struct_destructure(v0)
(v2: core::felt252, v3: core::felt252) <- struct_destructure(v1)
End:
Return(v6)
//! > ==========================================================================
//! > Test reboxing with multiple members
//! > test_runner_name
test_reboxing_analysis
//! > function_name
multi_member
//! > module_code
#[derive(Drop, Copy)]
struct Point {
x: u32,
y: u32,
z: u32,
}
//! > function_code
fn multi_member(p: Box<Point>) -> (Box<u32>, Box<u32>) {
(BoxTrait::new(p.x), BoxTrait::new(p.z))
}
//! > semantic_diagnostics
//! > lowering_diagnostics
//! > candidates
v5, v10
//! > before
Parameters: v0: core::box::Box::<test::Point>
blk0 (root):
Statements:
(v1: test::Point) <- unbox(v0)
(v2: core::integer::u32, v3: core::integer::u32, v4: core::integer::u32) <- struct_destructure(v1)
(v5: core::box::Box::<core::integer::u32>) <- into_box(v2)
(v6: test::Point) <- unbox(v0)
(v7: core::integer::u32, v8: core::integer::u32, v9: core::integer::u32) <- struct_destructure(v6)
(v10: core::box::Box::<core::integer::u32>) <- into_box(v9)
(v11: (core::box::Box::<core::integer::u32>, core::box::Box::<core::integer::u32>)) <- struct_construct(v5, v10)
End:
Return(v11)
//! > after
Parameters: v0: core::box::Box::<test::Point>
blk0 (root):
Statements:
(v1: test::Point) <- unbox(v0)
(v12: core::box::Box::<core::integer::u32>, v13: core::box::Box::<core::integer::u32>, v14: core::box::Box::<core::integer::u32>) <- struct_destructure(v0)
(v2: core::integer::u32, v3: core::integer::u32, v4: core::integer::u32) <- struct_destructure(v1)
(v6: test::Point) <- unbox(v0)
(v15: core::box::Box::<core::integer::u32>, v16: core::box::Box::<core::integer::u32>, v17: core::box::Box::<core::integer::u32>) <- struct_destructure(v0)
(v7: core::integer::u32, v8: core::integer::u32, v9: core::integer::u32) <- struct_destructure(v6)
(v11: (core::box::Box::<core::integer::u32>, core::box::Box::<core::integer::u32>)) <- struct_construct(v12, v17)
End:
Return(v11)
//! > ==========================================================================
//! > Test reboxing with nested struct
//! > test_runner_name
test_reboxing_analysis
//! > function_name
nested_struct
//! > module_code
#[derive(Drop, Copy)]
struct Inner {
value: felt252,
}
#[derive(Drop, Copy)]
struct Outer {
inner: Inner,
other: felt252,
}
//! > function_code
fn nested_struct(o: Box<Outer>) -> Box<felt252> {
BoxTrait::new(o.inner.value)
}
//! > semantic_diagnostics
//! > lowering_diagnostics
//! > candidates
v5
//! > before
Parameters: v0: core::box::Box::<test::Outer>
blk0 (root):
Statements:
(v1: test::Outer) <- unbox(v0)
(v2: test::Inner, v3: core::felt252) <- struct_destructure(v1)
(v4: core::felt252) <- struct_destructure(v2)
(v5: core::box::Box::<core::felt252>) <- into_box(v4)
End:
Return(v5)
//! > after
Parameters: v0: core::box::Box::<test::Outer>
blk0 (root):
Statements:
(v1: test::Outer) <- unbox(v0)
(v6: core::box::Box::<test::Inner>, v7: core::box::Box::<core::felt252>) <- struct_destructure(v0)
(v2: test::Inner, v3: core::felt252) <- struct_destructure(v1)
(v8: core::box::Box::<core::felt252>) <- struct_destructure(v6)
(v4: core::felt252) <- struct_destructure(v2)
End:
Return(v8)
//! > ==========================================================================
//! > Test reboxing with snapshot struct
//! > test_runner_name
test_reboxing_analysis
//! > function_name
with_snapshot
//! > module_code
#[derive(Drop)]
struct Data {
non_copy: NonCopy,
b: felt252,
}
#[derive(Drop)]
struct NonCopy {
a: felt252,
}
//! > function_code
fn with_snapshot(data: Box<@Data>) -> Box<@NonCopy> {
BoxTrait::new(data.unbox().non_copy)
}
//! > semantic_diagnostics
//! > lowering_diagnostics
//! > candidates
v4
//! > before
Parameters: v0: core::box::Box::<@test::Data>
blk0 (root):
Statements:
(v1: @test::Data) <- unbox(v0)
(v2: @test::NonCopy, v3: @core::felt252) <- struct_destructure(v1)
(v4: core::box::Box::<@test::NonCopy>) <- into_box(v2)
End:
Return(v4)
//! > after
Parameters: v0: core::box::Box::<@test::Data>
blk0 (root):
Statements:
(v1: @test::Data) <- unbox(v0)
(v5: core::box::Box::<@test::NonCopy>, v6: core::box::Box::<@core::felt252>) <- struct_destructure(v0)
(v2: @test::NonCopy, v3: @core::felt252) <- struct_destructure(v1)
End:
Return(v5)
//! > ==========================================================================
//! > Test reboxing without destructure (rebox whole struct)
//! > test_runner_name
test_reboxing_analysis
//! > function_name
rebox_whole
//! > module_code
struct Simple {
value: felt252,
}
//! > function_code
fn rebox_whole(s: Box<Simple>) -> Box<Simple> {
BoxTrait::new(s.unbox())
}
//! > semantic_diagnostics
//! > lowering_diagnostics
//! > candidates
v2
//! > before
Parameters: v0: core::box::Box::<test::Simple>
blk0 (root):
Statements:
(v1: test::Simple) <- unbox(v0)
(v2: core::box::Box::<test::Simple>) <- into_box(v1)
End:
Return(v2)
//! > after
Parameters: v0: core::box::Box::<test::Simple>
blk0 (root):
Statements:
(v1: test::Simple) <- unbox(v0)
End:
Return(v0)
//! > ==========================================================================
//! > Test no variable confusion in reboxing analysis
//! > test_runner_name
test_reboxing_analysis
//! > function_name
no_opportunity
//! > module_code
#[derive(Drop, Copy)]
struct Data {
a: felt252,
b: felt252,
}
//! > function_code
fn no_opportunity(d: Box<Data>, x: felt252) -> Box<felt252> {
let _unused = d.a;
BoxTrait::new(x)
}
//! > semantic_diagnostics
//! > lowering_diagnostics
//! > candidates
//! > before
Parameters: v0: core::box::Box::<test::Data>, v1: core::felt252
blk0 (root):
Statements:
(v5: core::box::Box::<core::felt252>) <- into_box(v1)
End:
Return(v5)
//! > after
Parameters: v0: core::box::Box::<test::Data>, v1: core::felt252
blk0 (root):
Statements:
(v5: core::box::Box::<core::felt252>) <- into_box(v1)
End:
Return(v5)
//! > ==========================================================================
//! > Test reboxing with enum
//! > test_runner_name
test_reboxing_analysis
//! > function_name
enum_rebox
//! > module_code
#[derive(Drop, Copy)]
enum MyEnum {
A: u32,
B: u32,
}
//! > function_code
fn enum_rebox(e: Box<MyEnum>) -> Box<u32> {
let a = match e.unbox() {
MyEnum::A(x) => x,
MyEnum::B(x) => x,
};
BoxTrait::new(a)
}
//! > semantic_diagnostics
//! > lowering_diagnostics
//! > candidates
//! > before
Parameters: v0: core::box::Box::<test::MyEnum>
blk0 (root):
Statements:
(v1: test::MyEnum) <- unbox(v0)
End:
Match(match_enum(v1) {
MyEnum::A(v2) => blk1,
MyEnum::B(v3) => blk2,
})
blk1:
Statements:
End:
Goto(blk3, {v2 -> v4})
blk2:
Statements:
End:
Goto(blk3, {v3 -> v4})
blk3:
Statements:
(v5: core::box::Box::<core::integer::u32>) <- into_box(v4)
End:
Return(v5)
//! > after
Parameters: v0: core::box::Box::<test::MyEnum>
blk0 (root):
Statements:
(v1: test::MyEnum) <- unbox(v0)
End:
Match(match_enum(v1) {
MyEnum::A(v2) => blk1,
MyEnum::B(v3) => blk2,
})
blk1:
Statements:
End:
Goto(blk3, {v2 -> v4})
blk2:
Statements:
End:
Goto(blk3, {v3 -> v4})
blk3:
Statements:
(v5: core::box::Box::<core::integer::u32>) <- into_box(v4)
End:
Return(v5)
//! > ==========================================================================
//! > Test reboxing with tuple
//! > test_runner_name
test_reboxing_analysis
//! > function_name
tuple_rebox
//! > module_code
//! > function_code
fn tuple_rebox(t: Box<(u32, felt252, u64)>) -> Box<felt252> {
let (_, mid, _) = t.unbox();
BoxTrait::new(mid)
}
//! > semantic_diagnostics
//! > lowering_diagnostics
//! > candidates
v5
//! > before
Parameters: v0: core::box::Box::<(core::integer::u32, core::felt252, core::integer::u64)>
blk0 (root):
Statements:
(v1: (core::integer::u32, core::felt252, core::integer::u64)) <- unbox(v0)
(v2: core::integer::u32, v3: core::felt252, v4: core::integer::u64) <- struct_destructure(v1)
(v5: core::box::Box::<core::felt252>) <- into_box(v3)
End:
Return(v5)
//! > after
Parameters: v0: core::box::Box::<(core::integer::u32, core::felt252, core::integer::u64)>
blk0 (root):
Statements:
(v1: (core::integer::u32, core::felt252, core::integer::u64)) <- unbox(v0)
(v6: core::box::Box::<core::integer::u32>, v7: core::box::Box::<core::felt252>, v8: core::box::Box::<core::integer::u64>) <- struct_destructure(v0)
(v2: core::integer::u32, v3: core::felt252, v4: core::integer::u64) <- struct_destructure(v1)
End:
Return(v7)
//! > ==========================================================================
//! > Test reboxing with non-Copy struct
//! > test_runner_name
test_reboxing_analysis
//! > function_name
non_copy_struct_rebox
//! > TODO(eytan-starkware): Add support for non-copy structs where applicable
//! > module_code
#[derive(Drop)]
struct NonCopyStruct {
arr: Array<felt252>,
val: felt252,
}
//! > function_code
fn non_copy_struct_rebox(s: Box<NonCopyStruct>) -> Box<felt252> {
BoxTrait::new(s.unbox().val)
}
//! > semantic_diagnostics
//! > lowering_diagnostics
//! > candidates
//! > before
Parameters: v0: core::box::Box::<test::NonCopyStruct>
blk0 (root):
Statements:
(v1: test::NonCopyStruct) <- unbox(v0)
(v2: core::array::Array::<core::felt252>, v3: core::felt252) <- struct_destructure(v1)
(v4: core::box::Box::<core::felt252>) <- into_box(v3)
End:
Return(v4)
//! > after
Parameters: v0: core::box::Box::<test::NonCopyStruct>
blk0 (root):
Statements:
(v1: test::NonCopyStruct) <- unbox(v0)
(v2: core::array::Array::<core::felt252>, v3: core::felt252) <- struct_destructure(v1)
(v4: core::box::Box::<core::felt252>) <- into_box(v3)
End:
Return(v4)
//! > ==========================================================================
//! > Test reboxing with non-Copy tuple
//! > test_runner_name
test_reboxing_analysis
//! > function_name
non_copy_tuple_rebox
//! > module_code
//! > function_code
fn non_copy_tuple_rebox(t: Box<(Array<felt252>, felt252)>) -> Box<felt252> {
let (_, val) = t.unbox();
BoxTrait::new(val)
}
//! > semantic_diagnostics
//! > lowering_diagnostics
//! > candidates
//! > before
Parameters: v0: core::box::Box::<(core::array::Array::<core::felt252>, core::felt252)>
blk0 (root):
Statements:
(v1: (core::array::Array::<core::felt252>, core::felt252)) <- unbox(v0)
(v2: core::array::Array::<core::felt252>, v3: core::felt252) <- struct_destructure(v1)
(v4: core::box::Box::<core::felt252>) <- into_box(v3)
End:
Return(v4)
//! > after
Parameters: v0: core::box::Box::<(core::array::Array::<core::felt252>, core::felt252)>
blk0 (root):
Statements:
(v1: (core::array::Array::<core::felt252>, core::felt252)) <- unbox(v0)
(v2: core::array::Array::<core::felt252>, v3: core::felt252) <- struct_destructure(v1)
(v4: core::box::Box::<core::felt252>) <- into_box(v3)
End:
Return(v4)
//! > ==========================================================================
//! > Test reboxing with branch-specific unbox assignments
//! > test_runner_name
test_reboxing_analysis
//! > function_name
branch_mut_unbox
//! > TODO(eytan-starkware): Support equality tracking and replacing the original deconstruct statement
//! > module_code
#[derive(Drop, Copy)]
struct Pair {
left: felt252,
right: felt252,
}
//! > function_code
fn branch_mut_unbox(flag: bool, p1: Box<Pair>, p2: Box<Pair>) -> Box<felt252> {
let mut x = p1.unbox();
if flag {
x = p1.unbox();
} else {
x = p2.unbox();
}
BoxTrait::new(x.right)
}
//! > semantic_diagnostics
//! > lowering_diagnostics
//! > candidates
//! > before
Parameters: v0: core::bool, v1: core::box::Box::<test::Pair>, v2: core::box::Box::<test::Pair>
blk0 (root):
Statements:
End:
Match(match_enum(v0) {
bool::False(v4) => blk1,
bool::True(v5) => blk2,
})
blk1:
Statements:
(v6: test::Pair) <- unbox(v2)
End:
Goto(blk3, {v6 -> v7})
blk2:
Statements:
(v8: test::Pair) <- unbox(v1)
End:
Goto(blk3, {v8 -> v7})
blk3:
Statements:
(v9: core::felt252, v10: core::felt252) <- struct_destructure(v7)
(v11: core::box::Box::<core::felt252>) <- into_box(v10)
End:
Return(v11)
//! > after
Parameters: v0: core::bool, v1: core::box::Box::<test::Pair>, v2: core::box::Box::<test::Pair>
blk0 (root):
Statements:
End:
Match(match_enum(v0) {
bool::False(v4) => blk1,
bool::True(v5) => blk2,
})
blk1:
Statements:
(v6: test::Pair) <- unbox(v2)
End:
Goto(blk3, {v6 -> v7})
blk2:
Statements:
(v8: test::Pair) <- unbox(v1)
End:
Goto(blk3, {v8 -> v7})
blk3:
Statements:
(v9: core::felt252, v10: core::felt252) <- struct_destructure(v7)
(v11: core::box::Box::<core::felt252>) <- into_box(v10)
End:
Return(v11)
//! > ==========================================================================
//! > Test reboxing with non-drop struct and member
//! > test_runner_name
test_reboxing_analysis
//! > function_name
main
//! > TODO(eytan-starkware): Support non-drop by unboxing each member.
//! > module_code
#[derive(Copy)]
struct NonDrop {
b: felt252,
}
#[derive(Copy)]
struct A {
a: felt252,
non_drop: NonDrop,
}
//! > function_code
fn main(a: Box<A>) -> (Box<felt252>, NonDrop) {
let unboxed = a.unbox();
(BoxTrait::new(unboxed.a), unboxed.non_drop)
}
//! > semantic_diagnostics
//! > lowering_diagnostics
//! > candidates
//! > before
Parameters: v0: core::box::Box::<test::A>
blk0 (root):
Statements:
(v1: test::A) <- unbox(v0)
(v2: core::felt252, v3: test::NonDrop) <- struct_destructure(v1)
(v4: core::box::Box::<core::felt252>) <- into_box(v2)
(v5: (core::box::Box::<core::felt252>, test::NonDrop)) <- struct_construct(v4, v3)
End:
Return(v5)
//! > after
Parameters: v0: core::box::Box::<test::A>
blk0 (root):
Statements:
(v1: test::A) <- unbox(v0)
(v2: core::felt252, v3: test::NonDrop) <- struct_destructure(v1)
(v4: core::box::Box::<core::felt252>) <- into_box(v2)
(v5: (core::box::Box::<core::felt252>, test::NonDrop)) <- struct_construct(v4, v3)
End:
Return(v5)
//! > ==========================================================================
//! > Test reboxing with snapshot of non-drop struct and member
//! > test_runner_name
test_reboxing_analysis
//! > function_name
main
//! > module_code
use core::box::BoxTrait;
#[derive(Copy)]
struct NonDrop {
b: felt252,
}
#[derive(Copy)]
struct A {
a: felt252,
non_drop: NonDrop,
}
//! > function_code
fn main(a: Box<@A>) -> (Box<@felt252>, @NonDrop) {
let a = a.unbox();
(BoxTrait::new(a.a), a.non_drop)
}
//! > semantic_diagnostics
//! > lowering_diagnostics
//! > candidates
v4
//! > before
Parameters: v0: core::box::Box::<@test::A>
blk0 (root):
Statements:
(v1: @test::A) <- unbox(v0)
(v2: @core::felt252, v3: @test::NonDrop) <- struct_destructure(v1)
(v4: core::box::Box::<@core::felt252>) <- into_box(v2)
(v5: @core::felt252, v6: @test::NonDrop) <- struct_destructure(v1)
(v7: (core::box::Box::<@core::felt252>, @test::NonDrop)) <- struct_construct(v4, v6)
End:
Return(v7)
//! > after
Parameters: v0: core::box::Box::<@test::A>
blk0 (root):
Statements:
(v1: @test::A) <- unbox(v0)
(v8: core::box::Box::<@core::felt252>, v9: core::box::Box::<@test::NonDrop>) <- struct_destructure(v0)
(v2: @core::felt252, v3: @test::NonDrop) <- struct_destructure(v1)
(v5: @core::felt252, v6: @test::NonDrop) <- struct_destructure(v1)
(v7: (core::box::Box::<@core::felt252>, @test::NonDrop)) <- struct_construct(v8, v6)
End:
Return(v7)
//! > ==========================================================================
//! > Test mixed reboxing types in different blocks
//! > test_runner_name
test_reboxing_analysis
//! > function_name
mixed_reboxing
//! > TODO(eytan-starkware): When removing demand for Copy, check no double
//! > into_box remain
//! > module_code
#[derive(Drop, Copy)]
struct Point {
x: felt252,
y: felt252,
}
//! > function_code
fn mixed_reboxing(p: Box<Point>, flag: bool) -> Box<felt252> {
if flag {
let unboxed = p.unbox();
BoxTrait::new(unboxed.x)
} else {
let unboxed = p.unbox();
let boxed = BoxTrait::new(unboxed);
let unboxed2 = boxed.unbox();
BoxTrait::new(unboxed2.y)
}
}
//! > candidates
v5, v9, v14
//! > before
Parameters: v0: core::box::Box::<test::Point>, v1: core::bool
blk0 (root):
Statements:
End:
Match(match_enum(v1) {
bool::False(v2) => blk1,
bool::True(v3) => blk2,
})
blk1:
Statements:
(v4: test::Point) <- unbox(v0)
(v5: core::box::Box::<test::Point>) <- into_box(v4)
(v6: test::Point) <- unbox(v5)
(v7: core::felt252, v8: core::felt252) <- struct_destructure(v6)
(v9: core::box::Box::<core::felt252>) <- into_box(v8)
End:
Goto(blk3, {v9 -> v10})
blk2:
Statements:
(v11: test::Point) <- unbox(v0)
(v12: core::felt252, v13: core::felt252) <- struct_destructure(v11)
(v14: core::box::Box::<core::felt252>) <- into_box(v12)
End:
Goto(blk3, {v14 -> v10})
blk3:
Statements:
End:
Return(v10)
//! > after
Parameters: v0: core::box::Box::<test::Point>, v1: core::bool
blk0 (root):
Statements:
End:
Match(match_enum(v1) {
bool::False(v2) => blk1,
bool::True(v3) => blk2,
})
blk1:
Statements:
(v4: test::Point) <- unbox(v0)
(v6: test::Point) <- unbox(v0)
(v15: core::box::Box::<core::felt252>, v16: core::box::Box::<core::felt252>) <- struct_destructure(v0)
(v7: core::felt252, v8: core::felt252) <- struct_destructure(v6)
End:
Goto(blk3, {v16 -> v10})
blk2:
Statements:
(v11: test::Point) <- unbox(v0)
(v17: core::box::Box::<core::felt252>, v18: core::box::Box::<core::felt252>) <- struct_destructure(v0)
(v12: core::felt252, v13: core::felt252) <- struct_destructure(v11)
End:
Goto(blk3, {v17 -> v10})
blk3:
Statements:
End:
Return(v10)