about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/diagnostics.rs12
-rw-r--r--crates/hir/src/lib.rs22
-rw-r--r--crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs72
-rw-r--r--crates/ide-diagnostics/src/handlers/trait_impl_reduntant_assoc_item.rs56
-rw-r--r--crates/ide-diagnostics/src/lib.rs4
5 files changed, 91 insertions, 75 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 74c1b97a2e3..52c1c27a7fa 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -12,7 +12,7 @@ use hir_def::path::ModPath;
 use hir_expand::{name::Name, HirFileId, InFile};
 use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange};
 
-use crate::{AssocItem, Field, Local, MacroKind, Type};
+use crate::{AssocItem, Field, Local, MacroKind, Trait, Type};
 
 macro_rules! diagnostics {
     ($($diag:ident,)*) => {
@@ -55,7 +55,7 @@ diagnostics![
     ReplaceFilterMapNextWithFindMap,
     TraitImplIncorrectSafety,
     TraitImplMissingAssocItems,
-    TraitImplReduntantAssocItems,
+    TraitImplRedundantAssocItems,
     TraitImplOrphan,
     TypedHole,
     TypeMismatch,
@@ -313,8 +313,8 @@ pub struct TraitImplMissingAssocItems {
 }
 
 #[derive(Debug, PartialEq, Eq)]
-pub struct TraitImplReduntantAssocItems {
+pub struct TraitImplRedundantAssocItems {
     pub file_id: HirFileId,
-    pub impl_: AstPtr<ast::Impl>,
-    pub reduntant: Vec<(Name, AssocItem)>,
-}
\ No newline at end of file
+    pub trait_: Trait,
+    pub assoc_item: (Name, AssocItem),
+}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 5e6f3c7a99f..4db1a02c0cd 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -693,20 +693,20 @@ 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
+                let redundant = impl_assoc_items_scratch
+                    .iter()
+                    .filter(|(id, name)| {
+                        !items.iter().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() {
+                    .map(|(item, name)| (name.clone(), AssocItem::from(*item)));
+                for (name, assoc_item) in redundant {
                     acc.push(
-                        TraitImplReduntantAssocItems {
-                            impl_: ast_id_map.get(node.ast_id()),
+                        TraitImplRedundantAssocItems {
+                            trait_,
                             file_id,
-                            reduntant,
+                            assoc_item: (name, assoc_item),
                         }
                         .into(),
                     )
diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
new file mode 100644
index 00000000000..6aded11382c
--- /dev/null
+++ b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
@@ -0,0 +1,72 @@
+use hir::{db::ExpandDatabase, Const, Function, HasSource, TypeAlias};
+
+use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
+
+// Diagnostic: trait-impl-redundant-assoc_item
+//
+// Diagnoses redundant trait items in a trait impl.
+pub(crate) fn trait_impl_redundant_assoc_item(
+    ctx: &DiagnosticsContext<'_>,
+    d: &hir::TraitImplRedundantAssocItems,
+) -> Diagnostic {
+    let name = d.assoc_item.0.clone();
+    let assoc_item = d.assoc_item.1;
+    let db = ctx.sema.db;
+
+    let range = db.parse_or_expand(d.file_id).text_range();
+    let trait_name = d.trait_.name(db).to_smol_str();
+
+    let (redundant_item_name, diagnostic_range) = match assoc_item {
+        hir::AssocItem::Function(id) => (
+            format!("`fn {}`", name.display(db)),
+            Function::from(id).source(db).map(|it| it.syntax().value.text_range()).unwrap_or(range),
+        ),
+        hir::AssocItem::Const(id) => (
+            format!("`const {}`", name.display(db)),
+            Const::from(id).source(db).map(|it| it.syntax().value.text_range()).unwrap_or(range),
+        ),
+        hir::AssocItem::TypeAlias(id) => (
+            format!("`type {}`", name.display(db)),
+            TypeAlias::from(id)
+                .source(db)
+                .map(|it| it.syntax().value.text_range())
+                .unwrap_or(range),
+        ),
+    };
+
+    Diagnostic::new(
+        DiagnosticCode::RustcHardError("E0407"),
+        format!("{redundant_item_name} is not a member of trait `{trait_name}`"),
+        diagnostic_range,
+    )
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::tests::check_diagnostics;
+
+    #[test]
+    fn trait_with_default_value() {
+        check_diagnostics(
+            r#"
+trait Marker {
+    const FLAG: bool = false;
+    fn boo();
+    fn foo () {}
+}
+struct Foo;
+impl Marker for Foo {
+    type T = i32;
+  //^^^^^^^^^^^^^ error: `type T` is not a member of trait `Marker`
+
+    const FLAG: bool = true;
+
+    fn bar() {}
+  //^^^^^^^^^^^ error: `fn bar` is not a member of trait `Marker`
+
+    fn boo() {}
+}
+            "#,
+        )
+    }
+}
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
deleted file mode 100644
index 446ce7d9fe1..00000000000
--- a/crates/ide-diagnostics/src/handlers/trait_impl_reduntant_assoc_item.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-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 c39e572b42d..6cfd5f18320 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -47,7 +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 trait_impl_redundant_assoc_item;
     pub(crate) mod typed_hole;
     pub(crate) mod type_mismatch;
     pub(crate) mod unimplemented_builtin_macro;
@@ -365,7 +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::TraitImplRedundantAssocItems(d) => handlers::trait_impl_redundant_assoc_item::trait_impl_redundant_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),