ide_diagnostics/handlers/
generic_args_prohibited.rs

1use 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
10// Diagnostic: generic-args-prohibited
11//
12// This diagnostic is shown when generic arguments are provided for a type that does not accept
13// generic arguments.
14pub(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    // This diagnostic was the first to be emitted in ty lowering, so the tests here also test
76    // diagnostics in ty lowering in general (which is why there are so many of them).
77
78    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}