Unnamed repository; edit this file 'description' to name the repository.
feat: add trait_impl_reduntant_assoc_item diagnostic
Young-Flash 2023-12-06
parent 77e362c · commit 5d84edd
-rw-r--r--crates/hir/src/diagnostics.rs8
-rw-r--r--crates/hir/src/lib.rs19
-rw-r--r--crates/ide-diagnostics/src/handlers/trait_impl_reduntant_assoc_item.rs56
-rw-r--r--crates/ide-diagnostics/src/lib.rs2
4 files changed, 85 insertions, 0 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index cf9a2b73d9..74c1b97a2e 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -55,6 +55,7 @@ diagnostics![
ReplaceFilterMapNextWithFindMap,
TraitImplIncorrectSafety,
TraitImplMissingAssocItems,
+ TraitImplReduntantAssocItems,
TraitImplOrphan,
TypedHole,
TypeMismatch,
@@ -310,3 +311,10 @@ pub struct TraitImplMissingAssocItems {
pub impl_: AstPtr<ast::Impl>,
pub missing: Vec<(Name, AssocItem)>,
}
+
+#[derive(Debug, PartialEq, Eq)]
+pub struct TraitImplReduntantAssocItems {
+ pub file_id: HirFileId,
+ pub impl_: AstPtr<ast::Impl>,
+ pub reduntant: Vec<(Name, AssocItem)>,
+} \ No newline at end of file
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 4a0c384e8a..5e6f3c7a99 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -693,6 +693,25 @@ impl Module {
},
));
+ let reduntant: Vec<_> = impl_assoc_items_scratch.iter()
+ .filter(|(id, name)| {
+ !required_items.clone().any(|(impl_name, impl_item)| {
+ discriminant(impl_item) == discriminant(id) && impl_name == name
+ })
+ })
+ .map(|(item, name)| (name.clone(), AssocItem::from(*item)))
+ .collect();
+ if !reduntant.is_empty() {
+ acc.push(
+ TraitImplReduntantAssocItems {
+ impl_: ast_id_map.get(node.ast_id()),
+ file_id,
+ reduntant,
+ }
+ .into(),
+ )
+ }
+
let missing: Vec<_> = required_items
.filter(|(name, id)| {
!impl_assoc_items_scratch.iter().any(|(impl_item, impl_name)| {
diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_reduntant_assoc_item.rs b/crates/ide-diagnostics/src/handlers/trait_impl_reduntant_assoc_item.rs
new file mode 100644
index 0000000000..446ce7d9fe
--- /dev/null
+++ b/crates/ide-diagnostics/src/handlers/trait_impl_reduntant_assoc_item.rs
@@ -0,0 +1,56 @@
+use hir::InFile;
+use itertools::Itertools;
+use syntax::{ast, AstNode};
+
+use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext};
+
+// Diagnostic: trait-impl-reduntant-assoc_item
+//
+// Diagnoses reduntant trait items in a trait impl.
+pub(crate) fn trait_impl_reduntant_assoc_item(
+ ctx: &DiagnosticsContext<'_>,
+ d: &hir::TraitImplReduntantAssocItems,
+) -> Diagnostic {
+ let reduntant = d.reduntant.iter().format_with(", ", |(name, item), f| {
+ f(&match *item {
+ hir::AssocItem::Function(_) => "`fn ",
+ hir::AssocItem::Const(_) => "`const ",
+ hir::AssocItem::TypeAlias(_) => "`type ",
+ })?;
+ f(&name.display(ctx.sema.db))?;
+ f(&"`")
+ });
+ Diagnostic::new(
+ DiagnosticCode::RustcHardError("E0407"),
+ format!("{reduntant} is not a member of trait"),
+ adjusted_display_range::<ast::Impl>(
+ ctx,
+ InFile { file_id: d.file_id, value: d.impl_.syntax_node_ptr() },
+ &|impl_| impl_.trait_().map(|t| t.syntax().text_range()),
+ ),
+ )
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::check_diagnostics;
+
+ #[test]
+ fn trait_with_default_value() {
+ check_diagnostics(
+ r#"
+trait Marker {
+ fn boo();
+}
+struct Foo;
+impl Marker for Foo {
+ //^^^^^^ error: `type T`, `const FLAG`, `fn bar` is not a member of trait
+ type T = i32;
+ const FLAG: bool = false;
+ fn bar() {}
+ fn boo() {}
+}
+ "#,
+ )
+ }
+}
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index 35272e8726..c39e572b42 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -47,6 +47,7 @@ mod handlers {
pub(crate) mod trait_impl_orphan;
pub(crate) mod trait_impl_incorrect_safety;
pub(crate) mod trait_impl_missing_assoc_item;
+ pub(crate) mod trait_impl_reduntant_assoc_item;
pub(crate) mod typed_hole;
pub(crate) mod type_mismatch;
pub(crate) mod unimplemented_builtin_macro;
@@ -364,6 +365,7 @@ pub fn diagnostics(
AnyDiagnostic::ReplaceFilterMapNextWithFindMap(d) => handlers::replace_filter_map_next_with_find_map::replace_filter_map_next_with_find_map(&ctx, &d),
AnyDiagnostic::TraitImplIncorrectSafety(d) => handlers::trait_impl_incorrect_safety::trait_impl_incorrect_safety(&ctx, &d),
AnyDiagnostic::TraitImplMissingAssocItems(d) => handlers::trait_impl_missing_assoc_item::trait_impl_missing_assoc_item(&ctx, &d),
+ AnyDiagnostic::TraitImplReduntantAssocItems(d) => handlers::trait_impl_reduntant_assoc_item::trait_impl_reduntant_assoc_item(&ctx, &d),
AnyDiagnostic::TraitImplOrphan(d) => handlers::trait_impl_orphan::trait_impl_orphan(&ctx, &d),
AnyDiagnostic::TypedHole(d) => handlers::typed_hole::typed_hole(&ctx, &d),
AnyDiagnostic::TypeMismatch(d) => handlers::type_mismatch::type_mismatch(&ctx, &d),