From 31869ef43a7ef22333aa9d06242ddc83f4f97b39 Mon Sep 17 00:00:00 2001 From: Christoph Burgdorf Date: Mon, 11 Jul 2022 11:40:28 +0200 Subject: [PATCH] Ensure contract pure fns can be called via `ContractName::fn_name()` --- crates/analyzer/src/namespace/items.rs | 52 +++++++++++++------ crates/analyzer/src/traversal/expressions.rs | 3 +- .../fixtures/features/contract_pure_fns.fe | 19 +++++++ crates/tests/src/features.rs | 3 +- ...fe_compiler_tests__features__case_158.snap | 7 +++ ...r_tests__features__case_159_map_tuple.snap | 7 +++ ...atures__case_160_int_literal_coercion.snap | 7 +++ ...ts__features__case_161_associated_fns.snap | 7 +++ ..._tests__features__case_162_struct_fns.snap | 7 +++ ...atures__case_163_cast_address_to_u256.snap | 7 +++ ...fe_compiler_tests__features__case_164.snap | 7 +++ ...s__features__case_4_contract_pure_fns.snap | 7 +++ 12 files changed, 116 insertions(+), 17 deletions(-) create mode 100644 crates/test-files/fixtures/features/contract_pure_fns.fe create mode 100644 crates/tests/src/snapshots/fe_compiler_tests__features__case_158.snap create mode 100644 crates/tests/src/snapshots/fe_compiler_tests__features__case_159_map_tuple.snap create mode 100644 crates/tests/src/snapshots/fe_compiler_tests__features__case_160_int_literal_coercion.snap create mode 100644 crates/tests/src/snapshots/fe_compiler_tests__features__case_161_associated_fns.snap create mode 100644 crates/tests/src/snapshots/fe_compiler_tests__features__case_162_struct_fns.snap create mode 100644 crates/tests/src/snapshots/fe_compiler_tests__features__case_163_cast_address_to_u256.snap create mode 100644 crates/tests/src/snapshots/fe_compiler_tests__features__case_164.snap create mode 100644 crates/tests/src/snapshots/fe_compiler_tests__features__case_4_contract_pure_fns.snap diff --git a/crates/analyzer/src/namespace/items.rs b/crates/analyzer/src/namespace/items.rs index 2877303966..1368445536 100644 --- a/crates/analyzer/src/namespace/items.rs +++ b/crates/analyzer/src/namespace/items.rs @@ -814,26 +814,17 @@ pub enum TypeDef { Contract(ContractId), Primitive(types::Base), } + impl TypeDef { pub fn items(&self, db: &dyn AnalyzerDb) -> Rc> { match self { TypeDef::Struct(val) => { - Rc::new( - val.functions(db) - .iter() - .filter_map(|(name, field)| { - if field.takes_self(db) { - // In the future we probably want to resolve instance methods as well. But this would require - // the caller to pass an instance as the first argument e.g. `Rectangle::can_hold(self_instance, other)`. - // This isn't yet supported so for now path access to functions is limited to static functions only. - None - } else { - Some((name.to_owned(), Item::Function(*field))) - } - }) - .collect(), - ) + // In the future we probably want to resolve instance methods as well. But this would require + // the caller to pass an instance as the first argument e.g. `Rectangle::can_hold(self_instance, other)`. + // This isn't yet supported so for now path access to functions is limited to static functions only. + val.pure_functions_as_items(db) } + TypeDef::Contract(val) => val.pure_functions_as_items(db), _ => todo!("cannot access items in types yet"), } } @@ -1323,6 +1314,37 @@ impl FunctionId { } } +trait FunctionsAsItems { + fn functions(&self, db: &dyn AnalyzerDb) -> Rc>; + + fn pure_functions_as_items(&self, db: &dyn AnalyzerDb) -> Rc> { + Rc::new( + self.functions(db) + .iter() + .filter_map(|(name, field)| { + if field.takes_self(db) { + None + } else { + Some((name.to_owned(), Item::Function(*field))) + } + }) + .collect(), + ) + } +} + +impl FunctionsAsItems for StructId { + fn functions(&self, db: &dyn AnalyzerDb) -> Rc> { + self.functions(db) + } +} + +impl FunctionsAsItems for ContractId { + fn functions(&self, db: &dyn AnalyzerDb) -> Rc> { + self.functions(db) + } +} + #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub struct Struct { pub ast: Node, diff --git a/crates/analyzer/src/traversal/expressions.rs b/crates/analyzer/src/traversal/expressions.rs index 520e14e4d8..c9ca77a81b 100644 --- a/crates/analyzer/src/traversal/expressions.rs +++ b/crates/analyzer/src/traversal/expressions.rs @@ -1459,7 +1459,8 @@ fn expr_call_method( // and the global objects are replaced by `Context`, we can remove this. // All other `NamedThing`s will be handled correctly by `expr()`. if let fe::Expr::Name(name) = &target.kind { - if let Ok(Some(NamedThing::Item(Item::Type(def)))) = context.resolve_name(name, target.span) { + if let Ok(Some(NamedThing::Item(Item::Type(def)))) = context.resolve_name(name, target.span) + { let typ = def.typ(context.db())?; return expr_call_type_attribute(context, typ, target.span, field, generic_args, args); } diff --git a/crates/test-files/fixtures/features/contract_pure_fns.fe b/crates/test-files/fixtures/features/contract_pure_fns.fe new file mode 100644 index 0000000000..0d0f46f1e3 --- /dev/null +++ b/crates/test-files/fixtures/features/contract_pure_fns.fe @@ -0,0 +1,19 @@ +contract Example { + + pub fn run_test(self) { + assert self.bar(42, 26) == 68 + assert self.bar2(42, 26) == 68 + } + + pub fn bar(self, _ x: u256, _ y: u256) -> u256 { + return pure_bar(x, y) + } + + pub fn bar2(self, _ x: u256, _ y: u256) -> u256 { + return Example::pure_bar(x, y) + } + + fn pure_bar(x: u256, y: u256) -> u256 { + return x + y + } +} diff --git a/crates/tests/src/features.rs b/crates/tests/src/features.rs index 3b85f067d7..92f46eee35 100644 --- a/crates/tests/src/features.rs +++ b/crates/tests/src/features.rs @@ -2070,7 +2070,8 @@ fn ctx_init_in_call() { fixture_file, case::simple_traits("simple_traits.fe"), case::generic_functions("generic_functions.fe"), - case::generic_functions_primitves("generic_functions_primitves.fe") + case::generic_functions_primitves("generic_functions_primitves.fe"), + case::contract_pure_fns("contract_pure_fns.fe") )] fn execution_tests(fixture_file: &str) { with_executor(&|mut executor| { diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__case_158.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__case_158.snap new file mode 100644 index 0000000000..963565f5bd --- /dev/null +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__case_158.snap @@ -0,0 +1,7 @@ +--- +source: crates/tests/src/features.rs +expression: "format!(\"{}\", harness.gas_reporter)" + +--- +bar([]) used 102 gas + diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__case_159_map_tuple.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__case_159_map_tuple.snap new file mode 100644 index 0000000000..bc699f452d --- /dev/null +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__case_159_map_tuple.snap @@ -0,0 +1,7 @@ +--- +source: crates/tests/src/features.rs +expression: "format!(\"{}\", harness.gas_reporter)" + +--- +bar([Uint(1234)]) used 45055 gas + diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__case_160_int_literal_coercion.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__case_160_int_literal_coercion.snap new file mode 100644 index 0000000000..461dfde510 --- /dev/null +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__case_160_int_literal_coercion.snap @@ -0,0 +1,7 @@ +--- +source: crates/tests/src/features.rs +expression: "format!(\"{}\", harness.gas_reporter)" + +--- +bar([]) used 311 gas + diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__case_161_associated_fns.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__case_161_associated_fns.snap new file mode 100644 index 0000000000..eaf7fdb7c5 --- /dev/null +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__case_161_associated_fns.snap @@ -0,0 +1,7 @@ +--- +source: crates/tests/src/features.rs +expression: "format!(\"{}\", harness.gas_reporter)" + +--- +bar([Uint(12)]) used 22698 gas + diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__case_162_struct_fns.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__case_162_struct_fns.snap new file mode 100644 index 0000000000..9b6a53c067 --- /dev/null +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__case_162_struct_fns.snap @@ -0,0 +1,7 @@ +--- +source: crates/tests/src/features.rs +expression: "format!(\"{}\", harness.gas_reporter)" + +--- +bar([Uint(10), Uint(20)]) used 2082 gas + diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__case_163_cast_address_to_u256.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__case_163_cast_address_to_u256.snap new file mode 100644 index 0000000000..e91aa41d83 --- /dev/null +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__case_163_cast_address_to_u256.snap @@ -0,0 +1,7 @@ +--- +source: crates/tests/src/features.rs +expression: "format!(\"{}\", harness.gas_reporter)" + +--- +bar([Address(0x2012301230123012301230123012301230123002)]) used 192 gas + diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__case_164.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__case_164.snap new file mode 100644 index 0000000000..37b6559a96 --- /dev/null +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__case_164.snap @@ -0,0 +1,7 @@ +--- +source: crates/tests/src/features.rs +expression: "format!(\"{}\", harness.gas_reporter)" + +--- +bar([Uint(42), Uint(26)]) used 202 gas + diff --git a/crates/tests/src/snapshots/fe_compiler_tests__features__case_4_contract_pure_fns.snap b/crates/tests/src/snapshots/fe_compiler_tests__features__case_4_contract_pure_fns.snap new file mode 100644 index 0000000000..09b509cccb --- /dev/null +++ b/crates/tests/src/snapshots/fe_compiler_tests__features__case_4_contract_pure_fns.snap @@ -0,0 +1,7 @@ +--- +source: crates/tests/src/features.rs +expression: "format!(\"{}\", harness.gas_reporter)" + +--- +run_test([]) used 35 gas +