mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-29 02:52:11 +00:00
626 lines
16 KiB
Rust
626 lines
16 KiB
Rust
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();
|
|
}
|
|
GenericArgsProhibitedReason::Const => "constants",
|
|
GenericArgsProhibitedReason::Static => "statics",
|
|
};
|
|
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
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn in_record_expr() {
|
|
check_diagnostics(
|
|
r#"
|
|
mod foo {
|
|
pub struct Bar { pub field: i32 }
|
|
}
|
|
fn baz() {
|
|
let _ = foo::<()>::Bar { field: 0 };
|
|
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn in_record_pat() {
|
|
check_diagnostics(
|
|
r#"
|
|
mod foo {
|
|
pub struct Bar { field: i32 }
|
|
}
|
|
fn baz(v: foo::Bar) {
|
|
let foo::<()>::Bar { .. } = v;
|
|
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn in_tuple_struct_pat() {
|
|
check_diagnostics(
|
|
r#"
|
|
mod foo {
|
|
pub struct Bar(i32);
|
|
}
|
|
fn baz(v: foo::Bar) {
|
|
let foo::<()>::Bar(..) = v;
|
|
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn in_path_pat() {
|
|
check_diagnostics(
|
|
r#"
|
|
mod foo {
|
|
pub struct Bar;
|
|
}
|
|
fn baz(v: foo::Bar) {
|
|
let foo::<()>::Bar = v;
|
|
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn in_path_expr() {
|
|
check_diagnostics(
|
|
r#"
|
|
mod foo {
|
|
pub struct Bar;
|
|
}
|
|
fn baz() {
|
|
let _ = foo::<()>::Bar;
|
|
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn const_and_static() {
|
|
check_diagnostics(
|
|
r#"
|
|
const CONST: i32 = 0;
|
|
static STATIC: i32 = 0;
|
|
fn baz() {
|
|
let _ = CONST::<()>;
|
|
// ^^^^^^ 💡 error: generic arguments are not allowed on constants
|
|
let _ = STATIC::<()>;
|
|
// ^^^^^^ 💡 error: generic arguments are not allowed on statics
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn enum_variant() {
|
|
check_diagnostics(
|
|
r#"
|
|
enum Enum<A> {
|
|
Variant(A),
|
|
}
|
|
mod enum_ {
|
|
pub(super) use super::Enum::Variant as V;
|
|
}
|
|
fn baz() {
|
|
let v = Enum::<()>::Variant::<()>(());
|
|
// ^^^^^^ 💡 error: you can specify generic arguments on either the enum or the variant, but not both
|
|
let Enum::<()>::Variant::<()>(..) = v;
|
|
// ^^^^^^ 💡 error: you can specify generic arguments on either the enum or the variant, but not both
|
|
let _ = Enum::<()>::Variant(());
|
|
let _ = Enum::Variant::<()>(());
|
|
}
|
|
fn foo() {
|
|
use Enum::Variant;
|
|
let _ = Variant::<()>(());
|
|
let _ = enum_::V::<()>(());
|
|
let _ = enum_::<()>::V::<()>(());
|
|
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn dyn_trait() {
|
|
check_diagnostics(
|
|
r#"
|
|
mod foo {
|
|
pub trait Trait {}
|
|
}
|
|
|
|
fn bar() {
|
|
let _: &dyn foo::<()>::Trait;
|
|
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
|
|
let _: &foo::<()>::Trait;
|
|
// ^^^^^^ 💡 error: generic arguments are not allowed on modules
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn regression_18768() {
|
|
check_diagnostics(
|
|
r#"
|
|
//- minicore: result
|
|
//- /foo.rs crate:foo edition:2018
|
|
pub mod lib {
|
|
mod core {
|
|
pub use core::*;
|
|
}
|
|
pub use self::core::result;
|
|
}
|
|
|
|
pub mod __private {
|
|
pub use crate::lib::result::Result::{self, Err, Ok};
|
|
}
|
|
|
|
//- /bar.rs crate:bar deps:foo edition:2018
|
|
fn bar() {
|
|
_ = foo::__private::Result::<(), ()>::Ok;
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn enum_variant_type_ns() {
|
|
check_diagnostics(
|
|
r#"
|
|
enum KvnDeserializerErr<I> {
|
|
UnexpectedKeyword { found: I, expected: I },
|
|
}
|
|
|
|
fn foo() {
|
|
let _x: KvnDeserializerErr<()> =
|
|
KvnDeserializerErr::<()>::UnexpectedKeyword { found: (), expected: () };
|
|
let _x: KvnDeserializerErr<()> =
|
|
KvnDeserializerErr::<()>::UnexpectedKeyword::<()> { found: (), expected: () };
|
|
// ^^^^^^ 💡 error: you can specify generic arguments on either the enum or the variant, but not both
|
|
}
|
|
"#,
|
|
);
|
|
}
|
|
}
|