Skip to content

Commit

Permalink
Fixes argument errors not displayed.
Browse files Browse the repository at this point in the history
type_check_method_application does the parsing of arguments in 2 passes,
but when the resolved_method_name failed the argument error would not be displayed.

We now store the arg_handlers and append their errors in case resolve_method_name fails.

Fixes #5660
  • Loading branch information
esdrubal committed Apr 23, 2024
1 parent d092929 commit 5d6ae37
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,40 +47,55 @@ pub(crate) fn type_check_method_application(
.with_help_text("")
.with_type_annotation(type_engine.insert(engines, TypeInfo::Unknown, None));
if index == 0 {
args_opt_buf.push_back(ty::TyExpression::type_check(handler, ctx, arg.clone()).ok());
args_opt_buf.push_back((
ty::TyExpression::type_check(handler, ctx, arg.clone()).ok(),
None,
));
} else {
// Ignore errors in method parameters
// On the second pass we will throw the errors if they persist.
let arg_handler = Handler::default();
let arg_opt = ty::TyExpression::type_check(&arg_handler, ctx, arg.clone()).ok();
if arg_handler.has_errors() {
args_opt_buf.push_back(None);
args_opt_buf.push_back((None, Some(arg_handler)));
} else {
args_opt_buf.push_back(arg_opt);
args_opt_buf.push_back((arg_opt, None));
}
};
}

// resolve the method name to a typed function declaration and type_check
let (original_decl_ref, call_path_typeid) = resolve_method_name(
let method_result = resolve_method_name(
handler,
ctx.by_ref(),
&method_name_binding,
args_opt_buf
.iter()
.map(|arg| match arg {
Some(arg) => arg.return_type,
None => type_engine.insert(engines, TypeInfo::Unknown, None),
(Some(arg), _) => arg.return_type,
(None, _) => type_engine.insert(engines, TypeInfo::Unknown, None),
})
.collect(),
)?;
);

// In case resolve_method_name fails throw argument errors.
let (original_decl_ref, call_path_typeid) = if let Err(e) = method_result {
for (_, arg_handler) in args_opt_buf.iter() {
if let Some(arg_handler) = arg_handler.clone() {
handler.append(arg_handler);
}
}
return Err(e);
} else {
method_result.unwrap()
};

let method = decl_engine.get_function(&original_decl_ref);

// type check the function arguments (2nd pass)
let mut args_buf = VecDeque::new();
for (arg, index, arg_opt) in izip!(arguments.iter(), 0.., args_opt_buf.iter().cloned()) {
if let Some(arg) = arg_opt {
if let (Some(arg), _) = arg_opt {
args_buf.push_back(arg);
} else {
let param_index = if method.is_contract_call {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[[package]]
name = "core"
source = "path+from-root-1C5801B8398D8ED4"

[[package]]
name = "variable_does_not_exist"
source = "member"
dependencies = ["core"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[project]
name = "variable_does_not_exist"
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
implicit-std = false

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

struct S {}

impl S {
fn associated(a: u64, b: u64, c: u64) -> u64 {
a + b + c
}
}

fn function(a: u64, b: u64, c: u64) -> u64 {
a + b + c
}

fn main() {
let _ = S::associated(x, y, z);


let _ = function(x, y, z);


let _ = x + y + z;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
category = "fail"

# check: $()let _ = S::associated(x, y, z);
# nextln:$()Variable "x" does not exist in this scope.

# check: $()let _ = S::associated(x, y, z);
# nextln:$()Variable "y" does not exist in this scope.

# check: $()let _ = S::associated(x, y, z);
# nextln:$()Variable "z" does not exist in this scope.

# check: $()let _ = function(x, y, z);
# nextln:$()Variable "x" does not exist in this scope.

# check: $()let _ = function(x, y, z);
# nextln:$()Variable "y" does not exist in this scope.

# check: $()let _ = function(x, y, z);
# nextln:$()Variable "z" does not exist in this scope.

# check: $()let _ = x + y + z;
# nextln: $()Variable "x" does not exist in this scope.

# check: $()let _ = x + y + z;
# nextln: $()Variable "y" does not exist in this scope.

# check: $()let _ = x + y + z;
# nextln: $()No method named "add" found for type "{unknown}".

# check: $()let _ = x + y + z;
# nextln: $()Variable "z" does not exist in this scope.

0 comments on commit 5d6ae37

Please sign in to comment.