ide_diagnostics/handlers/
generic_args_prohibited.rs1use either::Either;
2use hir::GenericArgsProhibitedReason;
3use ide_db::assists::Assist;
4use ide_db::source_change::SourceChange;
5use ide_db::text_edit::TextEdit;
6use syntax::{AstNode, TextRange, ast};
7
8use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, fix};
9
10pub(crate) fn generic_args_prohibited(
15 ctx: &DiagnosticsContext<'_>,
16 d: &hir::GenericArgsProhibited,
17) -> Diagnostic {
18 Diagnostic::new_with_syntax_node_ptr(
19 ctx,
20 DiagnosticCode::RustcHardError("E0109"),
21 describe_reason(d.reason),
22 d.args.map(Into::into),
23 )
24 .stable()
25 .with_fixes(fixes(ctx, d))
26}
27
28fn describe_reason(reason: GenericArgsProhibitedReason) -> String {
29 let kind = match reason {
30 GenericArgsProhibitedReason::Module => "modules",
31 GenericArgsProhibitedReason::TyParam => "type parameters",
32 GenericArgsProhibitedReason::SelfTy => "`Self`",
33 GenericArgsProhibitedReason::PrimitiveTy => "builtin types",
34 GenericArgsProhibitedReason::EnumVariant => {
35 return "you can specify generic arguments on either the enum or the variant, but not both"
36 .to_owned();
37 }
38 GenericArgsProhibitedReason::Const => "constants",
39 GenericArgsProhibitedReason::Static => "statics",
40 GenericArgsProhibitedReason::LocalVariable => "local variables",
41 };
42 format!("generic arguments are not allowed on {kind}")
43}
44
45fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::GenericArgsProhibited) -> Option<Vec<Assist>> {
46 let file_id = d.args.file_id.file_id()?;
47 let syntax = d.args.to_node(ctx.sema.db);
48 let range = match &syntax {
49 Either::Left(_) => syntax.syntax().text_range(),
50 Either::Right(param_list) => {
51 let path_segment = ast::PathSegment::cast(param_list.syntax().parent()?)?;
52 let start = if let Some(coloncolon) = path_segment.coloncolon_token() {
53 coloncolon.text_range().start()
54 } else {
55 param_list.syntax().text_range().start()
56 };
57 let end = if let Some(ret_type) = path_segment.ret_type() {
58 ret_type.syntax().text_range().end()
59 } else {
60 param_list.syntax().text_range().end()
61 };
62 TextRange::new(start, end)
63 }
64 };
65 Some(vec![fix(
66 "remove_generic_args",
67 "Remove these generics",
68 SourceChange::from_text_edit(file_id.file_id(ctx.sema.db), TextEdit::delete(range)),
69 syntax.syntax().text_range(),
70 )])
71}
72
73#[cfg(test)]
74mod tests {
75 use crate::tests::{check_diagnostics, check_fix};
79
80 #[test]
81 fn primitives() {
82 check_diagnostics(
83 r#"
84//- /core.rs crate:core library
85#![rustc_coherence_is_core]
86impl str {
87 pub fn trim() {}
88}
89
90//- /lib.rs crate:foo deps:core
91fn bar<T>() {}
92
93fn foo() {
94 let _: (bool<()>, ());
95 // ^^^^ 💡 error: generic arguments are not allowed on builtin types
96 let _ = <str<'_>>::trim;
97 // ^^^^ 💡 error: generic arguments are not allowed on builtin types
98 bar::<u32<{ const { 1 + 1 } }>>();
99 // ^^^^^^^^^^^^^^^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
100}
101 "#,
102 );
103 }
104
105 #[test]
106 fn modules() {
107 check_diagnostics(
108 r#"
109pub mod foo {
110 pub mod bar {
111 pub struct Baz;
112
113 impl Baz {
114 pub fn qux() {}
115 }
116 }
117}
118
119fn foo() {
120 let _: foo::<'_>::bar::Baz;
121 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
122 let _ = <foo::bar<()>::Baz>::qux;
123 // ^^^^ 💡 error: generic arguments are not allowed on modules
124}
125 "#,
126 );
127 }
128
129 #[test]
130 fn type_parameters() {
131 check_diagnostics(
132 r#"
133fn foo<T, U>() {
134 let _: T<'a>;
135 // ^^^^ 💡 error: generic arguments are not allowed on type parameters
136 let _: U::<{ 1 + 2 }>;
137 // ^^^^^^^^^^^^^ 💡 error: generic arguments are not allowed on type parameters
138}
139 "#,
140 );
141 }
142
143 #[test]
144 fn fn_like_generic_args() {
145 check_diagnostics(
146 r#"
147fn foo() {
148 let _: bool(bool, i32) -> ();
149 // ^^^^^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
150}
151 "#,
152 );
153 }
154
155 #[test]
156 fn fn_signature() {
157 check_diagnostics(
158 r#"
159fn foo(
160 _a: bool<'_>,
161 // ^^^^ 💡 error: generic arguments are not allowed on builtin types
162 _b: i32::<i64>,
163 // ^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
164 _c: &(&str<1>)
165 // ^^^ 💡 error: generic arguments are not allowed on builtin types
166) -> ((), i32<bool>) {
167 // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
168 ((), 0)
169}
170 "#,
171 );
172 }
173
174 #[test]
175 fn const_static_type() {
176 check_diagnostics(
177 r#"
178const A: i32<bool> = 0;
179 // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
180static A: i32::<{ 1 + 3 }> = 0;
181 // ^^^^^^^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
182 "#,
183 );
184 }
185
186 #[test]
187 fn fix() {
188 check_fix(
189 r#"
190fn foo() {
191 let _: bool<'_, (), { 1 + 1 }>$0;
192}"#,
193 r#"
194fn foo() {
195 let _: bool;
196}"#,
197 );
198 check_fix(
199 r#"
200fn foo() {
201 let _: bool::$0<'_, (), { 1 + 1 }>;
202}"#,
203 r#"
204fn foo() {
205 let _: bool;
206}"#,
207 );
208 check_fix(
209 r#"
210fn foo() {
211 let _: bool(i$032);
212}"#,
213 r#"
214fn foo() {
215 let _: bool;
216}"#,
217 );
218 check_fix(
219 r#"
220fn foo() {
221 let _: bool$0(i32) -> i64;
222}"#,
223 r#"
224fn foo() {
225 let _: bool;
226}"#,
227 );
228 check_fix(
229 r#"
230fn foo() {
231 let _: bool::(i$032) -> i64;
232}"#,
233 r#"
234fn foo() {
235 let _: bool;
236}"#,
237 );
238 check_fix(
239 r#"
240fn foo() {
241 let _: bool::(i32)$0;
242}"#,
243 r#"
244fn foo() {
245 let _: bool;
246}"#,
247 );
248 }
249
250 #[test]
251 fn in_fields() {
252 check_diagnostics(
253 r#"
254struct A(bool<i32>);
255 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
256struct B { v: bool<(), 1> }
257 // ^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
258union C {
259 a: bool<i32>,
260 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
261 b: i32<bool>,
262 // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
263 }
264enum D {
265 A(bool<i32>),
266 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
267 B { v: i32<bool> },
268 // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
269}
270 "#,
271 );
272 }
273
274 #[test]
275 fn in_generics() {
276 check_diagnostics(
277 r#"
278mod foo {
279 pub trait Trait {}
280}
281
282struct A<A: foo::<()>::Trait>(A)
283 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
284 where bool<i32>: foo::Trait;
285 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
286union B<A: foo::<()>::Trait>
287 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
288 where bool<i32>: foo::Trait
289 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
290{ a: A }
291enum C<A: foo::<()>::Trait>
292 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
293 where bool<i32>: foo::Trait
294 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
295{}
296
297fn f<A: foo::<()>::Trait>()
298 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
299 where bool<i32>: foo::Trait
300 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
301{}
302
303type D<A: foo::<()>::Trait> = A
304 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
305 where bool<i32>: foo::Trait;
306 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
307
308trait E<A: foo::<()>::Trait>
309 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
310 where bool<i32>: foo::Trait
311 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
312{
313 fn f<B: foo::<()>::Trait>()
314 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
315 where bool<i32>: foo::Trait
316 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
317 {}
318
319 type D<B: foo::<()>::Trait> = A
320 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
321 where bool<i32>: foo::Trait;
322 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
323}
324
325impl<A: foo::<()>::Trait> E<()> for ()
326 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
327 where bool<i32>: foo::Trait
328 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
329{
330 fn f<B: foo::<()>::Trait>()
331 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
332 where bool<i32>: foo::Trait
333 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
334 {}
335
336 type D<B: foo::<()>::Trait> = A
337 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
338 where bool<i32>: foo::Trait;
339 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
340}
341 "#,
342 );
343 }
344
345 #[test]
346 fn assoc_items() {
347 check_diagnostics(
348 r#"
349struct Foo;
350
351trait Trait {
352 fn f() -> bool<i32> { true }
353 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
354 type T = i32<bool>;
355 // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
356}
357
358impl Trait for Foo {
359 fn f() -> bool<i32> { true }
360 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
361 type T = i32<bool>;
362 // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
363}
364
365impl Foo {
366 fn f() -> bool<i32> { true }
367 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
368 type T = i32<bool>;
369 // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
370}
371 "#,
372 );
373 }
374
375 #[test]
376 fn const_param_ty() {
377 check_diagnostics(
378 r#"
379fn foo<
380 const A: bool<i32>,
381 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
382 B,
383 C,
384 const D: bool<i32>,
385 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
386 const E: bool<i32>,
387 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
388>() {}
389 "#,
390 );
391 }
392
393 #[test]
394 fn generic_defaults() {
395 check_diagnostics(
396 r#"
397struct Foo<A = bool<i32>>(A);
398 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
399 "#,
400 );
401 }
402
403 #[test]
404 fn impl_self_ty() {
405 check_diagnostics(
406 r#"
407struct Foo<A>(A);
408trait Trait {}
409impl Foo<bool<i32>> {}
410 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
411impl Trait for Foo<bool<i32>> {}
412 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
413 "#,
414 );
415 }
416
417 #[test]
418 fn impl_trait() {
419 check_diagnostics(
420 r#"
421mod foo {
422 pub trait Trait {}
423}
424impl foo::<()>::Trait for () {}
425 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
426 "#,
427 );
428 }
429
430 #[test]
431 fn type_alias() {
432 check_diagnostics(
433 r#"
434pub trait Trait {
435 type Assoc;
436}
437type T = bool<i32>;
438 // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
439impl Trait for () {
440 type Assoc = i32<bool>;
441 // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
442}
443 "#,
444 );
445 }
446
447 #[test]
448 fn in_record_expr() {
449 check_diagnostics(
450 r#"
451mod foo {
452 pub struct Bar { pub field: i32 }
453}
454fn baz() {
455 let _ = foo::<()>::Bar { field: 0 };
456 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
457}
458 "#,
459 );
460 }
461
462 #[test]
463 fn in_record_pat() {
464 check_diagnostics(
465 r#"
466mod foo {
467 pub struct Bar { field: i32 }
468}
469fn baz(v: foo::Bar) {
470 let foo::<()>::Bar { .. } = v;
471 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
472}
473 "#,
474 );
475 }
476
477 #[test]
478 fn in_tuple_struct_pat() {
479 check_diagnostics(
480 r#"
481mod foo {
482 pub struct Bar(i32);
483}
484fn baz(v: foo::Bar) {
485 let foo::<()>::Bar(..) = v;
486 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
487}
488 "#,
489 );
490 }
491
492 #[test]
493 fn in_path_pat() {
494 check_diagnostics(
495 r#"
496mod foo {
497 pub struct Bar;
498}
499fn baz(v: foo::Bar) {
500 let foo::<()>::Bar = v;
501 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
502}
503 "#,
504 );
505 }
506
507 #[test]
508 fn in_path_expr() {
509 check_diagnostics(
510 r#"
511mod foo {
512 pub struct Bar;
513}
514fn baz() {
515 let _ = foo::<()>::Bar;
516 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
517}
518 "#,
519 );
520 }
521
522 #[test]
523 fn const_param_and_static() {
524 check_diagnostics(
525 r#"
526const CONST: i32 = 0;
527static STATIC: i32 = 0;
528fn baz<const CONST_PARAM: usize>() {
529 let _ = CONST_PARAM::<()>;
530 // ^^^^^^ 💡 error: generic arguments are not allowed on constants
531 let _ = STATIC::<()>;
532 // ^^^^^^ 💡 error: generic arguments are not allowed on statics
533}
534 "#,
535 );
536 }
537
538 #[test]
539 fn local_variable() {
540 check_diagnostics(
541 r#"
542fn baz() {
543 let x = 1;
544 let _ = x::<()>;
545 // ^^^^^^ 💡 error: generic arguments are not allowed on local variables
546}
547 "#,
548 );
549 }
550
551 #[test]
552 fn enum_variant() {
553 check_diagnostics(
554 r#"
555enum Enum<A> {
556 Variant(A),
557}
558mod enum_ {
559 pub(super) use super::Enum::Variant as V;
560}
561fn baz() {
562 let v = Enum::<()>::Variant::<()>(());
563 // ^^^^^^ 💡 error: you can specify generic arguments on either the enum or the variant, but not both
564 let Enum::<()>::Variant::<()>(..) = v;
565 // ^^^^^^ 💡 error: you can specify generic arguments on either the enum or the variant, but not both
566 let _ = Enum::<()>::Variant(());
567 let _ = Enum::Variant::<()>(());
568}
569fn foo() {
570 use Enum::Variant;
571 let _ = Variant::<()>(());
572 let _ = enum_::V::<()>(());
573 let _ = enum_::<()>::V::<()>(());
574 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
575}
576 "#,
577 );
578 }
579
580 #[test]
581 fn dyn_trait() {
582 check_diagnostics(
583 r#"
584mod foo {
585 pub trait Trait {}
586}
587
588fn bar() {
589 let _: &dyn foo::<()>::Trait;
590 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
591 let _: &foo::<()>::Trait;
592 // ^^^^^^ 💡 error: generic arguments are not allowed on modules
593}
594 "#,
595 );
596 }
597
598 #[test]
599 fn regression_18768() {
600 check_diagnostics(
601 r#"
602//- minicore: result
603//- /foo.rs crate:foo edition:2018
604pub mod lib {
605 mod core {
606 pub use core::*;
607 }
608 pub use self::core::result;
609}
610
611pub mod __private {
612 pub use crate::lib::result::Result::{self, Err, Ok};
613}
614
615//- /bar.rs crate:bar deps:foo edition:2018
616fn bar() {
617 _ = foo::__private::Result::<(), ()>::Ok;
618}
619 "#,
620 );
621 }
622
623 #[test]
624 fn enum_variant_type_ns() {
625 check_diagnostics(
626 r#"
627enum KvnDeserializerErr<I> {
628 UnexpectedKeyword { found: I, expected: I },
629}
630
631fn foo() {
632 let _x: KvnDeserializerErr<()> =
633 KvnDeserializerErr::<()>::UnexpectedKeyword { found: (), expected: () };
634 let _x: KvnDeserializerErr<()> =
635 KvnDeserializerErr::<()>::UnexpectedKeyword::<()> { found: (), expected: () };
636 // ^^^^^^ 💡 error: you can specify generic arguments on either the enum or the variant, but not both
637}
638 "#,
639 );
640 }
641}