ide_diagnostics/handlers/
incorrect_generics_order.rs

1use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
2use hir::GenericArgKind;
3use syntax::SyntaxKind;
4
5// Diagnostic: incorrect-generics-order
6//
7// This diagnostic is triggered the order of provided generic arguments does not match their declaration.
8pub(crate) fn incorrect_generics_order(
9    ctx: &DiagnosticsContext<'_>,
10    d: &hir::IncorrectGenericsOrder,
11) -> Diagnostic {
12    let provided_description = match d.provided_arg.value.kind() {
13        SyntaxKind::CONST_ARG => "constant",
14        SyntaxKind::LIFETIME_ARG => "lifetime",
15        SyntaxKind::TYPE_ARG => "type",
16        _ => panic!("non-generic-arg passed to `incorrect_generics_order()`"),
17    };
18    let expected_description = match d.expected_kind {
19        GenericArgKind::Lifetime => "lifetime",
20        GenericArgKind::Type => "type",
21        GenericArgKind::Const => "constant",
22    };
23    let message =
24        format!("{provided_description} provided when a {expected_description} was expected");
25    Diagnostic::new_with_syntax_node_ptr(
26        ctx,
27        DiagnosticCode::RustcHardError("E0747"),
28        message,
29        d.provided_arg.map(Into::into),
30    )
31    .stable()
32}
33
34#[cfg(test)]
35mod tests {
36    use crate::tests::check_diagnostics;
37
38    #[test]
39    fn lifetime_out_of_order() {
40        check_diagnostics(
41            r#"
42struct Foo<'a, T>(&'a T);
43
44fn bar(_v: Foo<(), 'static>) {}
45            // ^^ error: type provided when a lifetime was expected
46        "#,
47        );
48    }
49
50    #[test]
51    fn types_and_consts() {
52        check_diagnostics(
53            r#"
54struct Foo<T>(T);
55fn foo1(_v: Foo<1>) {}
56             // ^ error: constant provided when a type was expected
57fn foo2(_v: Foo<{ (1, 2) }>) {}
58             // ^^^^^^^^^^ error: constant provided when a type was expected
59
60struct Bar<const N: usize>;
61fn bar(_v: Bar<()>) {}
62            // ^^ error: type provided when a constant was expected
63
64struct Baz<T, const N: usize>(T);
65fn baz(_v: Baz<1, ()>) {}
66            // ^ error: constant provided when a type was expected
67        "#,
68        );
69    }
70
71    #[test]
72    fn no_error_when_num_incorrect() {
73        check_diagnostics(
74            r#"
75struct Baz<T, U>(T, U);
76fn baz(_v: Baz<1>) {}
77           // ^^^ error: this struct takes 2 generic arguments but 1 generic argument was supplied
78        "#,
79        );
80    }
81}