Fix a bug in orphan rules calculation

Where a fundamental type applied twice wasn't considered local.
This commit is contained in:
Chayim Refael Friedman 2025-03-27 23:55:48 +02:00
parent 5bbf2ce419
commit 246d678d77
2 changed files with 30 additions and 12 deletions

View File

@ -874,21 +874,26 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool {
return true;
}
let unwrap_fundamental = |ty: Ty| match ty.kind(Interner) {
TyKind::Ref(_, _, referenced) => referenced.clone(),
&TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref subs) => {
let struct_data = db.struct_data(s);
if struct_data.flags.contains(StructFlags::IS_FUNDAMENTAL) {
let next = subs.type_parameters(Interner).next();
match next {
Some(ty) => ty,
None => ty,
let unwrap_fundamental = |mut ty: Ty| {
// Unwrap all layers of fundamental types with a loop.
loop {
match ty.kind(Interner) {
TyKind::Ref(_, _, referenced) => ty = referenced.clone(),
&TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref subs) => {
let struct_data = db.struct_data(s);
if struct_data.flags.contains(StructFlags::IS_FUNDAMENTAL) {
let next = subs.type_parameters(Interner).next();
match next {
Some(it) => ty = it,
None => break ty,
}
} else {
break ty;
}
}
} else {
ty
_ => break ty,
}
}
_ => ty,
};
// - At least one of the types `T0..=Tn`` must be a local type. Let `Ti`` be the first such type.
let is_not_orphan = trait_ref.substitution.type_parameters(Interner).any(|ty| {

View File

@ -104,4 +104,17 @@ impl<T> foo::Foo<dyn LocalTrait> for Bar {}
"#,
);
}
#[test]
fn twice_fundamental() {
check_diagnostics(
r#"
//- /foo.rs crate:foo
pub trait Trait {}
//- /bar.rs crate:bar deps:foo
struct Foo;
impl foo::Trait for &&Foo {}
"#,
);
}
}