ide_diagnostics/handlers/
incorrect_generics_len.rs1use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
2use hir::IncorrectGenericsLenKind;
3
4pub(crate) fn incorrect_generics_len(
8 ctx: &DiagnosticsContext<'_>,
9 d: &hir::IncorrectGenericsLen,
10) -> Diagnostic {
11 let owner_description = d.def.description();
12 let expected = d.expected;
13 let provided = d.provided;
14 let kind_description = match d.kind {
15 IncorrectGenericsLenKind::Lifetimes => "lifetime",
16 IncorrectGenericsLenKind::TypesAndConsts => "generic",
17 };
18 let message = format!(
19 "this {owner_description} takes {expected} {kind_description} argument{} \
20 but {provided} {kind_description} argument{} {} supplied",
21 if expected == 1 { "" } else { "s" },
22 if provided == 1 { "" } else { "s" },
23 if provided == 1 { "was" } else { "were" },
24 );
25 Diagnostic::new_with_syntax_node_ptr(
26 ctx,
27 DiagnosticCode::RustcHardError("E0107"),
28 message,
29 d.generics_or_segment.map(Into::into),
30 )
31}
32
33#[cfg(test)]
34mod tests {
35 use crate::tests::check_diagnostics;
36
37 #[test]
38 fn partially_specified_generics() {
39 check_diagnostics(
40 r#"
41struct Bar<T, U>(T, U);
42
43fn foo() {
44 let _ = Bar::<()>;
45 // ^^^^^^ error: this struct takes 2 generic arguments but 1 generic argument was supplied
46}
47
48 "#,
49 );
50 }
51
52 #[test]
53 fn enum_variant() {
54 check_diagnostics(
55 r#"
56enum Enum<T, U> {
57 Variant(T, U),
58}
59
60fn foo() {
61 let _ = Enum::<()>::Variant;
62 // ^^^^^^ error: this enum takes 2 generic arguments but 1 generic argument was supplied
63 let _ = Enum::Variant::<()>;
64 // ^^^^^^ error: this enum takes 2 generic arguments but 1 generic argument was supplied
65}
66
67 "#,
68 );
69 }
70
71 #[test]
72 fn lifetimes() {
73 check_diagnostics(
74 r#"
75struct Foo<'a, 'b>(&'a &'b ());
76
77fn foo(Foo(_): Foo) -> Foo {
78 let _: Foo = Foo(&&());
79 let _: Foo::<> = Foo::<>(&&());
80 let _: Foo::<'static>
81 // ^^^^^^^^^^^ error: this struct takes 2 lifetime arguments but 1 lifetime argument was supplied
82 = Foo::<'static>(&&());
83 // ^^^^^^^^^^^ error: this struct takes 2 lifetime arguments but 1 lifetime argument was supplied
84 |_: Foo| -> Foo {loop{}};
85
86 loop {}
87}
88
89 "#,
90 );
91 }
92
93 #[test]
94 fn no_error_for_elided_lifetimes() {
95 check_diagnostics(
96 r#"
97struct Foo<'a>(&'a ());
98
99fn foo(_v: &()) -> Foo { loop {} }
100 "#,
101 );
102 }
103
104 #[test]
105 fn errs_for_elided_lifetimes_if_lifetimes_are_explicitly_provided() {
106 check_diagnostics(
107 r#"
108struct Foo<'a, 'b>(&'a &'b ());
109
110fn foo(_v: Foo<'_>
111 // ^^^^ error: this struct takes 2 lifetime arguments but 1 lifetime argument was supplied
112) -> Foo<'static> { loop {} }
113 // ^^^^^^^^^ error: this struct takes 2 lifetime arguments but 1 lifetime argument was supplied
114 "#,
115 );
116 }
117
118 #[test]
119 fn types_and_consts() {
120 check_diagnostics(
121 r#"
122struct Foo<'a, T>(&'a T);
123fn foo(_v: Foo) {}
124 // ^^^ error: this struct takes 1 generic argument but 0 generic arguments were supplied
125
126struct Bar<T, const N: usize>(T);
127fn bar() {
128 let _ = Bar::<()>;
129 // ^^^^^^ error: this struct takes 2 generic arguments but 1 generic argument was supplied
130}
131 "#,
132 );
133 }
134
135 #[test]
136 fn respects_defaults() {
137 check_diagnostics(
138 r#"
139struct Foo<T = (), const N: usize = 0>(T);
140fn foo(_v: Foo) {}
141
142struct Bar<T, const N: usize = 0>(T);
143fn bar(_v: Bar<()>) {}
144 "#,
145 );
146 }
147
148 #[test]
149 fn constant() {
150 check_diagnostics(
151 r#"
152const CONST: i32 = 0;
153fn baz() {
154 let _ = CONST::<()>;
155 // ^^^^^^ error: this constant takes 0 generic arguments but 1 generic argument was supplied
156}
157 "#,
158 );
159 }
160
161 #[test]
162 fn assoc_type() {
163 check_diagnostics(
164 r#"
165trait Trait {
166 type Assoc;
167}
168
169fn foo<T: Trait<Assoc<i32> = bool>>() {}
170 // ^^^^^ error: this type alias takes 0 generic arguments but 1 generic argument was supplied
171 "#,
172 );
173 }
174
175 #[test]
176 fn regression_19669() {
177 check_diagnostics(
178 r#"
179//- minicore: from
180fn main() {
181 let _: i32 = Into::into(0);
182}
183"#,
184 );
185 }
186
187 #[test]
188 fn generic_assoc_type_infer_lifetime_in_expr_position() {
189 check_diagnostics(
190 r#"
191//- minicore: sized
192struct Player;
193
194struct Foo<'c, C> {
195 _v: &'c C,
196}
197trait WithSignals: Sized {
198 type SignalCollection<'c, C>;
199 fn __signals_from_external(&self) -> Self::SignalCollection<'_, Self>;
200}
201impl WithSignals for Player {
202 type SignalCollection<'c, C> = Foo<'c, C>;
203 fn __signals_from_external(&self) -> Self::SignalCollection<'_, Self> {
204 Self::SignalCollection { _v: self }
205 }
206}
207 "#,
208 );
209 }
210
211 #[test]
212 fn enum_type_alias_default_param() {
213 check_diagnostics(
214 r#"
215//- minicore: result
216
217struct Error;
218
219type Result<T, E = Error> = core::result::Result<T, E>;
220
221fn main() {
222 let _ = Result::<()>::Ok(());
223}
224 "#,
225 );
226 }
227}