From a696cf704aa045bd177a26aa1d2addba371dc456 Mon Sep 17 00:00:00 2001 From: Christoph Burgdorf Date: Tue, 25 Oct 2022 11:12:54 +0200 Subject: [PATCH] Reject to_mem on primitive types in storage --- crates/analyzer/src/traversal/expressions.rs | 18 +++++++++++++++++- crates/analyzer/tests/errors.rs | 2 +- .../errors__call_to_mem_on_primitive.snap | 14 ++++++++++++++ .../compile_errors/call_to_mem_on_primitive.fe | 7 +++++++ newsfragments/801.bugfix.md | 1 + 5 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 crates/analyzer/tests/snapshots/errors__call_to_mem_on_primitive.snap create mode 100644 crates/test-files/fixtures/compile_errors/call_to_mem_on_primitive.fe create mode 100644 newsfragments/801.bugfix.md diff --git a/crates/analyzer/src/traversal/expressions.rs b/crates/analyzer/src/traversal/expressions.rs index df7024418b..ead10dac06 100644 --- a/crates/analyzer/src/traversal/expressions.rs +++ b/crates/analyzer/src/traversal/expressions.rs @@ -1767,7 +1767,23 @@ fn expr_call_builtin_value_method( vec![], ); } - Location::Storage { .. } => {} + Location::Storage { .. } => { + if value_attrs.typ.is_base(context.db()) + || matches!(value_attrs.typ.typ(context.db()), Type::Contract(_)) + { + context.fancy_error( + "`to_mem()` called on primitive type", + vec![ + Label::primary( + value.span, + "this value does not need to be copied to memory", + ), + Label::secondary(method_name.span, "hint: remove `.to_mem()`"), + ], + vec![], + ); + } + } Location::Value => { context.fancy_error( "`to_mem()` called on primitive type", diff --git a/crates/analyzer/tests/errors.rs b/crates/analyzer/tests/errors.rs index 15a1a2bb43..04fbf09f8b 100644 --- a/crates/analyzer/tests/errors.rs +++ b/crates/analyzer/tests/errors.rs @@ -323,7 +323,7 @@ test_file! { abi_encode_from_storage } test_file! { assert_sto_msg_no_copy } test_file! { for_loop_sto_iter_no_copy } test_file! { revert_sto_error_no_copy } - +test_file! { call_to_mem_on_primitive } test_file! { call_to_mut_fn_without_self } test_file! { call_to_pure_fn_on_self } test_file! { call_to_pure_struct_fn_on_instance } diff --git a/crates/analyzer/tests/snapshots/errors__call_to_mem_on_primitive.snap b/crates/analyzer/tests/snapshots/errors__call_to_mem_on_primitive.snap new file mode 100644 index 0000000000..10202ada85 --- /dev/null +++ b/crates/analyzer/tests/snapshots/errors__call_to_mem_on_primitive.snap @@ -0,0 +1,14 @@ +--- +source: crates/analyzer/tests/errors.rs +expression: "error_string(&path, test_files::fixture(path))" + +--- +error: `to_mem()` called on primitive type + ┌─ compile_errors/call_to_mem_on_primitive.fe:5:16 + │ +5 │ return self.bar.to_mem() + │ ^^^^^^^^ ------ hint: remove `.to_mem()` + │ │ + │ this value does not need to be copied to memory + + diff --git a/crates/test-files/fixtures/compile_errors/call_to_mem_on_primitive.fe b/crates/test-files/fixtures/compile_errors/call_to_mem_on_primitive.fe new file mode 100644 index 0000000000..907c6260b3 --- /dev/null +++ b/crates/test-files/fixtures/compile_errors/call_to_mem_on_primitive.fe @@ -0,0 +1,7 @@ +contract Foo { + bar: u256 + + fn call_me(self) -> u256 { + return self.bar.to_mem() + } +} diff --git a/newsfragments/801.bugfix.md b/newsfragments/801.bugfix.md new file mode 100644 index 0000000000..1505cdbb82 --- /dev/null +++ b/newsfragments/801.bugfix.md @@ -0,0 +1 @@ +Reject calling `to_mem()` on primitive types in storage