fix: Suppress false positive missing assoc item diag on specialization
This commit is contained in:
parent
bfe82cbbc1
commit
7dbe12ec72
2 changed files with 60 additions and 0 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue