Skip to content

Commit

Permalink
Fix error message for arity mismatch on method calls (FuelLabs#3416)
Browse files Browse the repository at this point in the history
close FuelLabs#2949

Co-authored-by: Mohammad Fawaz <[email protected]>
  • Loading branch information
anton-trunov and mohammadfawaz authored Nov 23, 2022
1 parent 395c2ab commit 7fb338f
Show file tree
Hide file tree
Showing 24 changed files with 197 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl ty::TyExpression {
);
// check that the number of parameters and the number of the arguments is the same
check!(
check_function_arguments_arity(arguments.len(), &method, &call_path),
check_function_arguments_arity(arguments.len(), &method, &call_path, false),
return err(warnings, errors),
warnings,
errors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub(crate) fn instantiate_function_application(

// check that the number of parameters and the number of the arguments is the same
check!(
check_function_arguments_arity(arguments.len(), &function_decl, &call_path),
check_function_arguments_arity(arguments.len(), &function_decl, &call_path, false),
return err(warnings, errors),
warnings,
errors
Expand Down Expand Up @@ -118,26 +118,36 @@ pub(crate) fn check_function_arguments_arity(
arguments_len: usize,
function_decl: &ty::TyFunctionDeclaration,
call_path: &CallPath,
is_method_call_syntax_used: bool,
) -> CompileResult<()> {
let warnings = vec![];
let mut errors = vec![];
match arguments_len.cmp(&function_decl.parameters.len()) {
// if is_method_call_syntax_used then we have the guarantee
// that at least the self argument is passed
let (expected, received) = if is_method_call_syntax_used {
(function_decl.parameters.len() - 1, arguments_len - 1)
} else {
(function_decl.parameters.len(), arguments_len)
};
match expected.cmp(&received) {
std::cmp::Ordering::Equal => ok((), warnings, errors),
std::cmp::Ordering::Less => {
errors.push(CompileError::TooFewArgumentsForFunction {
span: call_path.span(),
method_name: function_decl.name.clone(),
expected: function_decl.parameters.len(),
received: arguments_len,
dot_syntax_used: is_method_call_syntax_used,
expected,
received,
});
err(warnings, errors)
}
std::cmp::Ordering::Greater => {
errors.push(CompileError::TooManyArgumentsForFunction {
span: call_path.span(),
method_name: function_decl.name.clone(),
expected: function_decl.parameters.len(),
received: arguments_len,
dot_syntax_used: is_method_call_syntax_used,
expected,
received,
});
err(warnings, errors)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,10 @@ pub(crate) fn type_check_method_application(

// If this function is being called with method call syntax, a.b(c),
// then make sure the first parameter is self, else issue an error.
let mut is_method_call_syntax_used = false;
if !method.is_contract_call {
if let MethodName::FromModule { ref method_name } = method_name_binding.inner {
is_method_call_syntax_used = true;
let is_first_param_self = method
.parameters
.get(0)
Expand Down Expand Up @@ -297,7 +299,12 @@ pub(crate) fn type_check_method_application(

// check that the number of parameters and the number of the arguments is the same
check!(
check_function_arguments_arity(args_buf.len(), &method, &call_path),
check_function_arguments_arity(
args_buf.len(),
&method,
&call_path,
is_method_call_syntax_used
),
return err(warnings, errors),
warnings,
errors
Expand Down
12 changes: 8 additions & 4 deletions sway-error/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,21 +413,25 @@ pub enum CompileError {
TraitNotFound { name: String, span: Span },
#[error("This expression is not valid on the left hand side of a reassignment.")]
InvalidExpressionOnLhs { span: Span },
#[error(
"Function \"{method_name}\" expects {expected} arguments but you provided {received}."
#[error("{} \"{method_name}\" expects {expected} {} but you provided {received}.",
if *dot_syntax_used { "Method" } else { "Function" },
if *expected == 1usize { "argument" } else {"arguments"},
)]
TooManyArgumentsForFunction {
span: Span,
method_name: Ident,
dot_syntax_used: bool,
expected: usize,
received: usize,
},
#[error(
"Function \"{method_name}\" expects {expected} arguments but you provided {received}."
#[error("{} \"{method_name}\" expects {expected} {} but you provided {received}.",
if *dot_syntax_used { "Method" } else { "Function" },
if *expected == 1usize { "argument" } else {"arguments"},
)]
TooFewArgumentsForFunction {
span: Span,
method_name: Ident,
dot_syntax_used: bool,
expected: usize,
received: usize,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[[package]]
name = 'core'
source = 'path+from-root-38536451AF31C078'

[[package]]
name = 'excess_associated_fn_arguments'
source = 'member'
dependencies = ['core']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
license = "Apache-2.0"
name = "excess_associated_fn_arguments"
entry = "main.sw"

[dependencies]
core = { path = "../../../../../../sway-lib-core" }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
script;

struct Data {
value: u64
}

impl Data {
fn add_values(self, other: Data) -> u64 {
self.value + other.value
}
}

fn main() -> u64 {
let data1 = Data {
value: 42u64
};
let data2 = Data {
value: 1u64
};
Data::add_values(data1, data2, data2)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
category = "fail"

# check: $()Function "add_values" expects 2 arguments but you provided 3.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[[package]]
name = 'core'
source = 'path+from-root-5BDABAFA31FD4CEA'

[[package]]
name = 'excess_method_arguments'
source = 'member'
dependencies = ['core']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
license = "Apache-2.0"
name = "excess_method_arguments"
entry = "main.sw"

[dependencies]
core = { path = "../../../../../../sway-lib-core" }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
script;

struct Data {
value: u64
}

impl Data {
fn add_values(self, other: Data) -> u64 {
self.value + other.value
}
}

fn main() -> u64 {
let data1 = Data {
value: 42u64
};
let data2 = Data {
value: 1u64
};
data1.add_values(data2, data2)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
category = "fail"

# check: $()Method "add_values" expects 1 argument but you provided 2.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[[package]]
name = 'core'
source = 'path+from-root-517D1536FEF54B89'

[[package]]
name = 'missing_associated_fn_arguments'
source = 'member'
dependencies = ['core']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
license = "Apache-2.0"
name = "missing_associated_fn_arguments"
entry = "main.sw"

[dependencies]
core = { path = "../../../../../../sway-lib-core" }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
script;

struct Data {
value: u64
}

impl Data {
fn add_values(self, other: Data) -> u64 {
self.value + other.value
}
}

fn main() -> u64 {
let data1 = Data {
value: 42u64
};
let data2 = Data {
value: 1u64
};
Data::add_values(data1)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
category = "fail"

# check: $()Function "add_values" expects 2 arguments but you provided 1.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[[package]]
name = 'core'
source = 'path+from-root-02CB52E4F1733F6E'

[[package]]
name = 'missing_method_arguments'
source = 'member'
dependencies = ['core']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
license = "Apache-2.0"
name = "missing_method_arguments"
entry = "main.sw"

[dependencies]
core = { path = "../../../../../../sway-lib-core" }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
script;

struct Data {
value: u64
}

impl Data {
fn add_values(self, other: Data) -> u64 {
self.value + other.value
}
}

fn main() -> u64 {
let data1 = Data {
value: 42u64
};
let data2 = Data {
value: 1u64
};
data1.add_values()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
category = "fail"

# check: $()Method "add_values" expects 1 argument but you provided 0.

0 comments on commit 7fb338f

Please sign in to comment.