diff --git a/crates/analyzer/src/traversal/expressions.rs b/crates/analyzer/src/traversal/expressions.rs index df7024418b..e006e12205 100644 --- a/crates/analyzer/src/traversal/expressions.rs +++ b/crates/analyzer/src/traversal/expressions.rs @@ -1767,7 +1767,21 @@ fn expr_call_builtin_value_method( vec![], ); } - Location::Storage { .. } => {} + Location::Storage { .. } => { + if value_attrs.typ.is_base(context.db()) { + 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/foo.fe b/foo.fe new file mode 100644 index 0000000000..da1aeb5bef --- /dev/null +++ b/foo.fe @@ -0,0 +1,17 @@ +use std::context::Context + + +contract WavePortal { + foo: u256 + totalWaves: Map + + pub fn wave(self,ctx:Context) { + self.totalWaves[ctx.msg_sender()] +=1; + } + + pub fn getTotalWaves(self, addr: address)-> u256{ + return self.foo.to_mem() + //return self.totalWaves[addr].to_mem() + } + +} \ No newline at end of file diff --git a/newsfragments/4711.bugfix.md b/newsfragments/4711.bugfix.md new file mode 100644 index 0000000000..1505cdbb82 --- /dev/null +++ b/newsfragments/4711.bugfix.md @@ -0,0 +1 @@ +Reject calling `to_mem()` on primitive types in storage