diff --git a/ast/src/functions/function.rs b/ast/src/functions/function.rs index 34bf69c8ce..c6a92c3a6f 100644 --- a/ast/src/functions/function.rs +++ b/ast/src/functions/function.rs @@ -76,6 +76,16 @@ impl Function { self.input.iter().find(|param| param.is_mut_self()).is_some() } + /// + /// Returns a vector of [&FunctionInput] removing `self` and `mut self` inputs. + /// + pub fn filter_self_inputs(&self) -> Vec<&FunctionInput> { + self.input + .iter() + .filter(|input| !input.is_self()) + .collect::>() + } + fn format(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "function {}", self.identifier)?; diff --git a/compiler/src/errors/expression.rs b/compiler/src/errors/expression.rs index 41a83cd6f2..be0deb5925 100644 --- a/compiler/src/errors/expression.rs +++ b/compiler/src/errors/expression.rs @@ -206,7 +206,7 @@ impl ExpressionError { } pub fn undefined_identifier(identifier: Identifier) -> Self { - let message = format!("cannot find value `{}` in this scope", identifier.name); + let message = format!("Cannot find value `{}` in this scope", identifier.name); Self::new_from_span(message, identifier.span) } diff --git a/compiler/src/function/function.rs b/compiler/src/function/function.rs index d873144cc2..4d438d5221 100644 --- a/compiler/src/function/function.rs +++ b/compiler/src/function/function.rs @@ -42,8 +42,11 @@ impl> ConstrainedProgram { ) -> Result, FunctionError> { let function_name = new_scope(scope, function.get_name()); + // Store if function contains input `mut self`. + let mut_self = function.contains_mut_self(); + // Store input values as new variables in resolved program - for (input_model, input_expression) in function.input.iter().zip(input.into_iter()) { + for (input_model, input_expression) in function.filter_self_inputs().iter().zip(input.into_iter()) { let (name, value) = match input_model { FunctionInput::InputKeyword(keyword) => { let value = @@ -87,8 +90,6 @@ impl> ConstrainedProgram { self.store(input_program_identifier, value); } - let mut_self = function.contains_mut_self(); - // Evaluate every statement in the function and save all potential results let mut results = vec![]; diff --git a/compiler/tests/circuits/member_function_nested.leo b/compiler/tests/circuits/member_function_nested.leo index cc6cae2475..9e07cc9acf 100644 --- a/compiler/tests/circuits/member_function_nested.leo +++ b/compiler/tests/circuits/member_function_nested.leo @@ -12,7 +12,7 @@ circuit Foo { function main() { let a = Foo { x: 1u32 }; - let b = a.call_add_x(1u32); + let b = a.add_x(1u32); console.assert(b == 2u32); } diff --git a/compiler/tests/circuits/member_static_function.leo b/compiler/tests/circuits/member_static_function.leo index ac96c89088..4bf51190f0 100644 --- a/compiler/tests/circuits/member_static_function.leo +++ b/compiler/tests/circuits/member_static_function.leo @@ -1,5 +1,5 @@ circuit Foo { - static function echo(x: u32) -> u32 { + function echo(x: u32) -> u32 { return x } } diff --git a/compiler/tests/circuits/member_static_function_invalid.leo b/compiler/tests/circuits/member_static_function_invalid.leo index b2782bfed4..513d78b67d 100644 --- a/compiler/tests/circuits/member_static_function_invalid.leo +++ b/compiler/tests/circuits/member_static_function_invalid.leo @@ -5,5 +5,5 @@ circuit Foo { } function main() { - let err = Foo::echo(1u32); // echo is a non-static function and must be accessed using `.` + let err = Foo::echo(1u32); // Correct, echo is a static function and must be accessed using `::` } \ No newline at end of file diff --git a/compiler/tests/circuits/member_static_function_nested.leo b/compiler/tests/circuits/member_static_function_nested.leo index 8f717f3f7c..ef536e3f6e 100644 --- a/compiler/tests/circuits/member_static_function_nested.leo +++ b/compiler/tests/circuits/member_static_function_nested.leo @@ -1,11 +1,11 @@ circuit Foo { - static function qux() {} + function qux() {} - static function bar() { + function bar() { Self::qux(); } - static function baz() { + function baz() { Self::bar(); } } diff --git a/compiler/tests/circuits/member_static_function_undefined.leo b/compiler/tests/circuits/member_static_function_undefined.leo index e8e5cb20bc..cf9f98c7b4 100644 --- a/compiler/tests/circuits/member_static_function_undefined.leo +++ b/compiler/tests/circuits/member_static_function_undefined.leo @@ -1,5 +1,5 @@ circuit Foo { - static function echo(x: u32) -> u32 { + function echo(x: u32) -> u32 { return x } } diff --git a/compiler/tests/circuits/member_variable_and_function.leo b/compiler/tests/circuits/member_variable_and_function.leo index 35f413a361..074feab7b8 100644 --- a/compiler/tests/circuits/member_variable_and_function.leo +++ b/compiler/tests/circuits/member_variable_and_function.leo @@ -1,7 +1,7 @@ circuit Foo { foo: u32, - static function bar() -> u32 { + function bar() -> u32 { return 1u32 } } diff --git a/compiler/tests/circuits/mod.rs b/compiler/tests/circuits/mod.rs index c599c29023..848d7a01c7 100644 --- a/compiler/tests/circuits/mod.rs +++ b/compiler/tests/circuits/mod.rs @@ -14,13 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{ - assert_satisfied, - expect_compiler_error, - expect_symbol_table_error, - expect_type_inference_error, - parse_program, -}; +use crate::{assert_satisfied, expect_compiler_error, expect_type_inference_error, parse_program}; // Expressions @@ -125,9 +119,9 @@ fn test_member_static_function_nested() { #[test] fn test_member_static_function_invalid() { let bytes = include_bytes!("member_static_function_invalid.leo"); - let error = parse_program(bytes).err().unwrap(); + let program = parse_program(bytes).unwrap(); - expect_type_inference_error(error) + assert_satisfied(program) } #[test] @@ -225,9 +219,9 @@ fn test_self_member_pass() { #[test] fn test_self_member_invalid() { let bytes = include_bytes!("self_member_invalid.leo"); - let program = parse_program(bytes).unwrap(); + let error = parse_program(bytes).err().unwrap(); - let _err = expect_compiler_error(program); + expect_type_inference_error(error); } #[test] diff --git a/compiler/tests/circuits/mut_self_function_fail.leo b/compiler/tests/circuits/mut_self_function_fail.leo index 18da32c5fb..8c9b99f6ae 100644 --- a/compiler/tests/circuits/mut_self_function_fail.leo +++ b/compiler/tests/circuits/mut_self_function_fail.leo @@ -3,7 +3,7 @@ circuit Foo { function bar() {} - function set_a(new: u8) { + function set_a(mut self, new: u8) { self.bar = new; } } diff --git a/compiler/tests/circuits/mut_self_static_function_fail.leo b/compiler/tests/circuits/mut_self_static_function_fail.leo index de87c5fadf..8c9b99f6ae 100644 --- a/compiler/tests/circuits/mut_self_static_function_fail.leo +++ b/compiler/tests/circuits/mut_self_static_function_fail.leo @@ -1,9 +1,9 @@ circuit Foo { a: u8, - static function bar() {} + function bar() {} - function set_a(new: u8) { + function set_a(mut self, new: u8) { self.bar = new; } } diff --git a/compiler/tests/circuits/mut_self_variable.leo b/compiler/tests/circuits/mut_self_variable.leo index 47b9aeed70..f5a35ec754 100644 --- a/compiler/tests/circuits/mut_self_variable.leo +++ b/compiler/tests/circuits/mut_self_variable.leo @@ -1,7 +1,7 @@ circuit Foo { - mut a: u8, + a: u8, - function set_a(new: u8) { + function set_a(mut self, new: u8) { self.a = new; console.assert(self.a == new); } diff --git a/compiler/tests/circuits/mut_self_variable_fail.leo b/compiler/tests/circuits/mut_self_variable_fail.leo index 551b041c9e..fdbb556bca 100644 --- a/compiler/tests/circuits/mut_self_variable_fail.leo +++ b/compiler/tests/circuits/mut_self_variable_fail.leo @@ -1,7 +1,7 @@ circuit Foo { a: u8, - function set_a(new: u8) { + function set_a(self, new: u8) { self.a = new; } } diff --git a/compiler/tests/circuits/mut_static_function_fail.leo b/compiler/tests/circuits/mut_static_function_fail.leo index f1bccaaf89..ed3092c656 100644 --- a/compiler/tests/circuits/mut_static_function_fail.leo +++ b/compiler/tests/circuits/mut_static_function_fail.leo @@ -1,5 +1,5 @@ circuit Foo { - static function bar() {} + function bar() {} } function main() { diff --git a/compiler/tests/circuits/mut_variable.leo b/compiler/tests/circuits/mut_variable.leo index eaf61ddf02..243d7a2cf2 100644 --- a/compiler/tests/circuits/mut_variable.leo +++ b/compiler/tests/circuits/mut_variable.leo @@ -1,5 +1,5 @@ circuit Foo { - mut a: u8, + a: u8, } function main() { diff --git a/compiler/tests/circuits/mut_variable_fail.leo b/compiler/tests/circuits/mut_variable_fail.leo index bb2e653ee3..4d58150c95 100644 --- a/compiler/tests/circuits/mut_variable_fail.leo +++ b/compiler/tests/circuits/mut_variable_fail.leo @@ -3,7 +3,7 @@ circuit Foo { } function main() { - let mut f = Foo { a: 0u8 }; + let f = Foo { a: 0u8 }; f.a = 1u8; } \ No newline at end of file diff --git a/compiler/tests/circuits/pedersen_mock.leo b/compiler/tests/circuits/pedersen_mock.leo index 2b58019d8d..0b42c64a6e 100644 --- a/compiler/tests/circuits/pedersen_mock.leo +++ b/compiler/tests/circuits/pedersen_mock.leo @@ -1,11 +1,11 @@ circuit PedersenHash { parameters: [u32; 512] - static function new(parameters: [u32; 512]) -> Self { + function new(parameters: [u32; 512]) -> Self { return Self { parameters: parameters } } - function hash(bits: [bool; 512]) -> u32 { + function hash(self, bits: [bool; 512]) -> u32 { let mut digest: u32 = 0; for i in 0..512 { let base = if bits[i] ? self.parameters[i] : 0u32; diff --git a/compiler/tests/circuits/self_member.leo b/compiler/tests/circuits/self_member.leo index a075894af0..1bd978433d 100644 --- a/compiler/tests/circuits/self_member.leo +++ b/compiler/tests/circuits/self_member.leo @@ -1,7 +1,7 @@ circuit Foo { f: u32, - function bar() -> u32 { + function bar(self) -> u32 { return self.f } } diff --git a/compiler/tests/syntax/mod.rs b/compiler/tests/syntax/mod.rs index 55b7292d2a..017d01a707 100644 --- a/compiler/tests/syntax/mod.rs +++ b/compiler/tests/syntax/mod.rs @@ -53,7 +53,7 @@ fn test_undefined() { " 2 | return a", " | ^", " |", - " = cannot find value `a` in this scope", + " = Cannot find value `a` in this scope", ] .join("\n") ); diff --git a/symbol-table/src/types/functions/function.rs b/symbol-table/src/types/functions/function.rs index c03cf3a3ba..194ab7a72e 100644 --- a/symbol-table/src/types/functions/function.rs +++ b/symbol-table/src/types/functions/function.rs @@ -137,6 +137,16 @@ impl FunctionType { pub fn contains_self(&self) -> bool { self.inputs.iter().find(|param| param.is_self()).is_some() } + + /// + /// Returns a vector of [&FunctionInputType] removing `self` and `mut self` inputs. + /// + pub fn filter_self_inputs(&self) -> Vec<&FunctionInputType> { + self.inputs + .iter() + .filter(|input| !input.is_self()) + .collect::>() + } } impl PartialEq for FunctionType { diff --git a/type-inference/src/objects/frame.rs b/type-inference/src/objects/frame.rs index fe3943eca7..822fdf9448 100644 --- a/type-inference/src/objects/frame.rs +++ b/type-inference/src/objects/frame.rs @@ -1083,8 +1083,6 @@ impl Frame { // Case 2: no static call + no self keywords => Error // Case 3: static call + no self keywords => Ok // Case 4: no static call + self keyword => Ok - println!("static {}", is_static); - println!("function contains self {}", function_type.contains_self()); if is_static && function_type.contains_self() { return Err(FrameError::self_not_available(&identifier.span)); } else if !is_static && !function_type.contains_self() { @@ -1112,12 +1110,17 @@ impl Frame { let function_type = self.parse_function_name(expression, span)?; // Check the length of arguments - if function_type.num_inputs() != inputs.len() { - return Err(FrameError::num_inputs(function_type.num_inputs(), inputs.len(), span)); + let num_inputs = function_type.num_inputs(); + + if num_inputs != inputs.len() { + return Err(FrameError::num_inputs(num_inputs, inputs.len(), span)); } + // Filter out `self` and `mut self` keywords. + let expected_inputs = function_type.filter_self_inputs(); + // Assert function inputs are correct types. - for (expected_input, actual_input) in function_type.inputs.iter().zip(inputs) { + for (expected_input, actual_input) in expected_inputs.iter().zip(inputs) { // Parse expected input type. let expected_type = expected_input.type_();