Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs')
-rw-r--r--crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs442
1 files changed, 442 insertions, 0 deletions
diff --git a/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs b/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs
new file mode 100644
index 0000000000..a319a0bcf6
--- /dev/null
+++ b/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs
@@ -0,0 +1,442 @@
+use either::Either;
+use hir::GenericArgsProhibitedReason;
+use ide_db::assists::Assist;
+use ide_db::source_change::SourceChange;
+use ide_db::text_edit::TextEdit;
+use syntax::{ast, AstNode, TextRange};
+
+use crate::{fix, Diagnostic, DiagnosticCode, DiagnosticsContext};
+
+// Diagnostic: generic-args-prohibited
+//
+// This diagnostic is shown when generic arguments are provided for a type that does not accept
+// generic arguments.
+pub(crate) fn generic_args_prohibited(
+ ctx: &DiagnosticsContext<'_>,
+ d: &hir::GenericArgsProhibited,
+) -> Diagnostic {
+ Diagnostic::new_with_syntax_node_ptr(
+ ctx,
+ DiagnosticCode::RustcHardError("E0109"),
+ describe_reason(d.reason),
+ d.args.map(Into::into),
+ )
+ .with_fixes(fixes(ctx, d))
+}
+
+fn describe_reason(reason: GenericArgsProhibitedReason) -> String {
+ let kind = match reason {
+ GenericArgsProhibitedReason::Module => "modules",
+ GenericArgsProhibitedReason::TyParam => "type parameters",
+ GenericArgsProhibitedReason::SelfTy => "`Self`",
+ GenericArgsProhibitedReason::PrimitiveTy => "builtin types",
+ GenericArgsProhibitedReason::EnumVariant => {
+ return "you can specify generic arguments on either the enum or the variant, but not both"
+ .to_owned();
+ }
+ };
+ format!("generic arguments are not allowed on {kind}")
+}
+
+fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::GenericArgsProhibited) -> Option<Vec<Assist>> {
+ let file_id = d.args.file_id.file_id()?;
+ let syntax = d.args.to_node(ctx.sema.db);
+ let range = match &syntax {
+ Either::Left(_) => syntax.syntax().text_range(),
+ Either::Right(param_list) => {
+ let path_segment = ast::PathSegment::cast(param_list.syntax().parent()?)?;
+ let start = if let Some(coloncolon) = path_segment.coloncolon_token() {
+ coloncolon.text_range().start()
+ } else {
+ param_list.syntax().text_range().start()
+ };
+ let end = if let Some(ret_type) = path_segment.ret_type() {
+ ret_type.syntax().text_range().end()
+ } else {
+ param_list.syntax().text_range().end()
+ };
+ TextRange::new(start, end)
+ }
+ };
+ Some(vec![fix(
+ "remove_generic_args",
+ "Remove these generics",
+ SourceChange::from_text_edit(file_id, TextEdit::delete(range)),
+ syntax.syntax().text_range(),
+ )])
+}
+
+#[cfg(test)]
+mod tests {
+ // This diagnostic was the first to be emitted in ty lowering, so the tests here also test
+ // diagnostics in ty lowering in general (which is why there are so many of them).
+
+ use crate::tests::{check_diagnostics, check_fix};
+
+ #[test]
+ fn primitives() {
+ check_diagnostics(
+ r#"
+//- /core.rs crate:core library
+#![rustc_coherence_is_core]
+impl str {
+ pub fn trim() {}
+}
+
+//- /lib.rs crate:foo deps:core
+fn bar<T>() {}
+
+fn foo() {
+ let _: (bool<()>, ());
+ // ^^^^ 💡 error: generic arguments are not allowed on builtin types
+ let _ = <str<'_>>::trim;
+ // ^^^^ 💡 error: generic arguments are not allowed on builtin types
+ bar::<u32<{ const { 1 + 1 } }>>();
+ // ^^^^^^^^^^^^^^^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+ "#,
+ );
+ }
+
+ #[test]
+ fn modules() {
+ check_diagnostics(
+ r#"
+pub mod foo {
+ pub mod bar {
+ pub struct Baz;
+
+ impl Baz {
+ pub fn qux() {}
+ }
+ }
+}
+
+fn foo() {
+ let _: foo::<'_>::bar::Baz;
+ // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+ let _ = <foo::bar<()>::Baz>::qux;
+ // ^^^^ 💡 error: generic arguments are not allowed on modules
+}
+ "#,
+ );
+ }
+
+ #[test]
+ fn type_parameters() {
+ check_diagnostics(
+ r#"
+fn foo<T, U>() {
+ let _: T<'a>;
+ // ^^^^ 💡 error: generic arguments are not allowed on type parameters
+ let _: U::<{ 1 + 2 }>;
+ // ^^^^^^^^^^^^^ 💡 error: generic arguments are not allowed on type parameters
+}
+ "#,
+ );
+ }
+
+ #[test]
+ fn fn_like_generic_args() {
+ check_diagnostics(
+ r#"
+fn foo() {
+ let _: bool(bool, i32) -> ();
+ // ^^^^^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+ "#,
+ );
+ }
+
+ #[test]
+ fn fn_signature() {
+ check_diagnostics(
+ r#"
+fn foo(
+ _a: bool<'_>,
+ // ^^^^ 💡 error: generic arguments are not allowed on builtin types
+ _b: i32::<i64>,
+ // ^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ _c: &(&str<1>)
+ // ^^^ 💡 error: generic arguments are not allowed on builtin types
+) -> ((), i32<bool>) {
+ // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ ((), 0)
+}
+ "#,
+ );
+ }
+
+ #[test]
+ fn const_static_type() {
+ check_diagnostics(
+ r#"
+const A: i32<bool> = 0;
+ // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+static A: i32::<{ 1 + 3 }> = 0;
+ // ^^^^^^^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ "#,
+ );
+ }
+
+ #[test]
+ fn fix() {
+ check_fix(
+ r#"
+fn foo() {
+ let _: bool<'_, (), { 1 + 1 }>$0;
+}"#,
+ r#"
+fn foo() {
+ let _: bool;
+}"#,
+ );
+ check_fix(
+ r#"
+fn foo() {
+ let _: bool::$0<'_, (), { 1 + 1 }>;
+}"#,
+ r#"
+fn foo() {
+ let _: bool;
+}"#,
+ );
+ check_fix(
+ r#"
+fn foo() {
+ let _: bool(i$032);
+}"#,
+ r#"
+fn foo() {
+ let _: bool;
+}"#,
+ );
+ check_fix(
+ r#"
+fn foo() {
+ let _: bool$0(i32) -> i64;
+}"#,
+ r#"
+fn foo() {
+ let _: bool;
+}"#,
+ );
+ check_fix(
+ r#"
+fn foo() {
+ let _: bool::(i$032) -> i64;
+}"#,
+ r#"
+fn foo() {
+ let _: bool;
+}"#,
+ );
+ check_fix(
+ r#"
+fn foo() {
+ let _: bool::(i32)$0;
+}"#,
+ r#"
+fn foo() {
+ let _: bool;
+}"#,
+ );
+ }
+
+ #[test]
+ fn in_fields() {
+ check_diagnostics(
+ r#"
+struct A(bool<i32>);
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+struct B { v: bool<(), 1> }
+ // ^^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+union C {
+ a: bool<i32>,
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ b: i32<bool>,
+ // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ }
+enum D {
+ A(bool<i32>),
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ B { v: i32<bool> },
+ // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+ "#,
+ );
+ }
+
+ #[test]
+ fn in_generics() {
+ check_diagnostics(
+ r#"
+mod foo {
+ pub trait Trait {}
+}
+
+struct A<A: foo::<()>::Trait>(A)
+ // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+ where bool<i32>: foo::Trait;
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+union B<A: foo::<()>::Trait>
+ // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+ where bool<i32>: foo::Trait
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+{ a: A }
+enum C<A: foo::<()>::Trait>
+ // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+ where bool<i32>: foo::Trait
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+{}
+
+fn f<A: foo::<()>::Trait>()
+ // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+ where bool<i32>: foo::Trait
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+{}
+
+type D<A: foo::<()>::Trait> = A
+ // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+ where bool<i32>: foo::Trait;
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+
+trait E<A: foo::<()>::Trait>
+ // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+ where bool<i32>: foo::Trait
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+{
+ fn f<B: foo::<()>::Trait>()
+ // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+ where bool<i32>: foo::Trait
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ {}
+
+ type D<B: foo::<()>::Trait> = A
+ // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+ where bool<i32>: foo::Trait;
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+
+impl<A: foo::<()>::Trait> E for ()
+ // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+ where bool<i32>: foo::Trait
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+{
+ fn f<B: foo::<()>::Trait>()
+ // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+ where bool<i32>: foo::Trait
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ {}
+
+ type D<B: foo::<()>::Trait> = A
+ // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+ where bool<i32>: foo::Trait;
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+ "#,
+ );
+ }
+
+ #[test]
+ fn assoc_items() {
+ check_diagnostics(
+ r#"
+struct Foo;
+
+trait Trait {
+ fn f() -> bool<i32> { true }
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ type T = i32<bool>;
+ // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+
+impl Trait for Foo {
+ fn f() -> bool<i32> { true }
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ type T = i32<bool>;
+ // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+
+impl Foo {
+ fn f() -> bool<i32> { true }
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ type T = i32<bool>;
+ // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+ "#,
+ );
+ }
+
+ #[test]
+ fn const_param_ty() {
+ check_diagnostics(
+ r#"
+fn foo<
+ const A: bool<i32>,
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ B,
+ C,
+ const D: bool<i32>,
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ const E: bool<i32>,
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+>() {}
+ "#,
+ );
+ }
+
+ #[test]
+ fn generic_defaults() {
+ check_diagnostics(
+ r#"
+struct Foo<A = bool<i32>>(A);
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ "#,
+ );
+ }
+
+ #[test]
+ fn impl_self_ty() {
+ check_diagnostics(
+ r#"
+struct Foo<A>(A);
+trait Trait {}
+impl Foo<bool<i32>> {}
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+impl Trait for Foo<bool<i32>> {}
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+ "#,
+ );
+ }
+
+ #[test]
+ fn impl_trait() {
+ check_diagnostics(
+ r#"
+mod foo {
+ pub trait Trait {}
+}
+impl foo::<()>::Trait for () {}
+ // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+ "#,
+ );
+ }
+
+ #[test]
+ fn type_alias() {
+ check_diagnostics(
+ r#"
+pub trait Trait {
+ type Assoc;
+}
+type T = bool<i32>;
+ // ^^^^^ 💡 error: generic arguments are not allowed on builtin types
+impl Trait for () {
+ type Assoc = i32<bool>;
+ // ^^^^^^ 💡 error: generic arguments are not allowed on builtin types
+}
+ "#,
+ );
+ }
+}