Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir/src/lib.rs42
-rw-r--r--crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs18
2 files changed, 60 insertions, 0 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index ef35694774..78be5a7e8f 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -920,6 +920,48 @@ impl Module {
}
}
+ // HACK: When specialization is enabled in the current crate, and there exists
+ // *any* blanket impl that provides a default implementation for the missing item,
+ // suppress the missing associated item diagnostic.
+ // This can lead to false negatives when the impl in question does not actually
+ // specialize that blanket impl, but determining the exact specialization
+ // relationship here would be significantly more expensive.
+ if !missing.is_empty() {
+ let krate = self.krate(db).id;
+ let def_map = crate_def_map(db, krate);
+ if def_map.is_unstable_feature_enabled(&sym::specialization)
+ || def_map.is_unstable_feature_enabled(&sym::min_specialization)
+ {
+ missing.retain(|(assoc_name, assoc_item)| {
+ let AssocItem::Function(_) = assoc_item else {
+ return true;
+ };
+
+ for &impl_ in TraitImpls::for_crate(db, krate).blanket_impls(trait_.id)
+ {
+ if impl_ == impl_id {
+ continue;
+ }
+
+ for (name, item) in &impl_.impl_items(db).items {
+ let AssocItemId::FunctionId(fn_) = item else {
+ continue;
+ };
+ if name != assoc_name {
+ continue;
+ }
+
+ if db.function_signature(*fn_).is_default() {
+ return false;
+ }
+ }
+ }
+
+ true
+ });
+ }
+ }
+
if !missing.is_empty() {
acc.push(
TraitImplMissingAssocItems {
diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs b/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
index 0e18ce9674..2c05544701 100644
--- a/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
+++ b/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
@@ -156,4 +156,22 @@ impl Trait for dyn OtherTrait {}
"#,
)
}
+
+ #[test]
+ fn no_false_positive_on_specialization() {
+ check_diagnostics(
+ r#"
+#![feature(specialization)]
+
+pub trait Foo {
+ fn foo();
+}
+
+impl<T> Foo for T {
+ default fn foo() {}
+}
+impl Foo for bool {}
+"#,
+ );
+ }
}