2021-06-14 05:15:05 -05:00
|
|
|
use crate::{Diagnostic, DiagnosticsContext};
|
2021-06-13 12:06:25 -05:00
|
|
|
|
|
|
|
// Diagnostic: mismatched-arg-count
|
|
|
|
//
|
|
|
|
// This diagnostic is triggered if a function is invoked with an incorrect amount of arguments.
|
|
|
|
pub(super) fn mismatched_arg_count(
|
|
|
|
ctx: &DiagnosticsContext<'_>,
|
|
|
|
d: &hir::MismatchedArgCount,
|
|
|
|
) -> Diagnostic {
|
|
|
|
let s = if d.expected == 1 { "" } else { "s" };
|
|
|
|
let message = format!("expected {} argument{}, found {}", d.expected, s, d.found);
|
|
|
|
Diagnostic::new(
|
|
|
|
"mismatched-arg-count",
|
|
|
|
message,
|
|
|
|
ctx.sema.diagnostics_display_range(d.call_expr.clone().map(|it| it.into())).range,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2021-06-14 05:15:05 -05:00
|
|
|
use crate::tests::check_diagnostics;
|
2021-06-13 12:06:25 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn simple_free_fn_zero() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
fn zero() {}
|
|
|
|
fn f() { zero(1); }
|
|
|
|
//^^^^^^^ expected 0 arguments, found 1
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
fn zero() {}
|
|
|
|
fn f() { zero(); }
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn simple_free_fn_one() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
fn one(arg: u8) {}
|
|
|
|
fn f() { one(); }
|
|
|
|
//^^^^^ expected 1 argument, found 0
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
fn one(arg: u8) {}
|
|
|
|
fn f() { one(1); }
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn method_as_fn() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
struct S;
|
|
|
|
impl S { fn method(&self) {} }
|
|
|
|
|
|
|
|
fn f() {
|
|
|
|
S::method();
|
|
|
|
} //^^^^^^^^^^^ expected 1 argument, found 0
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
struct S;
|
|
|
|
impl S { fn method(&self) {} }
|
|
|
|
|
|
|
|
fn f() {
|
|
|
|
S::method(&S);
|
|
|
|
S.method();
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn method_with_arg() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
struct S;
|
|
|
|
impl S { fn method(&self, arg: u8) {} }
|
|
|
|
|
|
|
|
fn f() {
|
|
|
|
S.method();
|
|
|
|
} //^^^^^^^^^^ expected 1 argument, found 0
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
struct S;
|
|
|
|
impl S { fn method(&self, arg: u8) {} }
|
|
|
|
|
|
|
|
fn f() {
|
|
|
|
S::method(&S, 0);
|
|
|
|
S.method(1);
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn method_unknown_receiver() {
|
|
|
|
// note: this is incorrect code, so there might be errors on this in the
|
|
|
|
// future, but we shouldn't emit an argument count diagnostic here
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
trait Foo { fn method(&self, arg: usize) {} }
|
|
|
|
|
|
|
|
fn f() {
|
|
|
|
let x;
|
|
|
|
x.method();
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn tuple_struct() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
struct Tup(u8, u16);
|
|
|
|
fn f() {
|
|
|
|
Tup(0);
|
|
|
|
} //^^^^^^ expected 2 arguments, found 1
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn enum_variant() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
enum En { Variant(u8, u16), }
|
|
|
|
fn f() {
|
|
|
|
En::Variant(0);
|
|
|
|
} //^^^^^^^^^^^^^^ expected 2 arguments, found 1
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn enum_variant_type_macro() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
macro_rules! Type {
|
|
|
|
() => { u32 };
|
|
|
|
}
|
|
|
|
enum Foo {
|
|
|
|
Bar(Type![])
|
|
|
|
}
|
|
|
|
impl Foo {
|
|
|
|
fn new() {
|
|
|
|
Foo::Bar(0);
|
|
|
|
Foo::Bar(0, 1);
|
|
|
|
//^^^^^^^^^^^^^^ expected 1 argument, found 2
|
|
|
|
Foo::Bar();
|
|
|
|
//^^^^^^^^^^ expected 1 argument, found 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn varargs() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
extern "C" {
|
|
|
|
fn fixed(fixed: u8);
|
|
|
|
fn varargs(fixed: u8, ...);
|
|
|
|
fn varargs2(...);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn f() {
|
|
|
|
unsafe {
|
|
|
|
fixed(0);
|
|
|
|
fixed(0, 1);
|
|
|
|
//^^^^^^^^^^^ expected 1 argument, found 2
|
|
|
|
varargs(0);
|
|
|
|
varargs(0, 1);
|
|
|
|
varargs2();
|
|
|
|
varargs2(0);
|
|
|
|
varargs2(0, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn arg_count_lambda() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
fn main() {
|
|
|
|
let f = |()| ();
|
|
|
|
f();
|
|
|
|
//^^^ expected 1 argument, found 0
|
|
|
|
f(());
|
|
|
|
f((), ());
|
|
|
|
//^^^^^^^^^ expected 1 argument, found 2
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn cfgd_out_call_arguments() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
struct C(#[cfg(FALSE)] ());
|
|
|
|
impl C {
|
|
|
|
fn new() -> Self {
|
|
|
|
Self(
|
|
|
|
#[cfg(FALSE)]
|
|
|
|
(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn method(&self) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
C::new().method(#[cfg(FALSE)] 0);
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn cfgd_out_fn_params() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
fn foo(#[cfg(NEVER)] x: ()) {}
|
|
|
|
|
|
|
|
struct S;
|
|
|
|
|
|
|
|
impl S {
|
|
|
|
fn method(#[cfg(NEVER)] self) {}
|
|
|
|
fn method2(#[cfg(NEVER)] self, arg: u8) {}
|
|
|
|
fn method3(self, #[cfg(NEVER)] arg: u8) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
fn fixed(fixed: u8, #[cfg(NEVER)] ...);
|
|
|
|
fn varargs(#[cfg(not(NEVER))] ...);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
foo();
|
|
|
|
S::method();
|
|
|
|
S::method2(0);
|
|
|
|
S::method3(S);
|
|
|
|
S.method3();
|
|
|
|
unsafe {
|
|
|
|
fixed(0);
|
|
|
|
varargs(1, 2, 3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|