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; return true;
} }
let unwrap_fundamental = |ty: Ty| match ty.kind(Interner) { let unwrap_fundamental = |mut ty: Ty| {
TyKind::Ref(_, _, referenced) => referenced.clone(), // 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) => { &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref subs) => {
let struct_data = db.struct_data(s); let struct_data = db.struct_data(s);
if struct_data.flags.contains(StructFlags::IS_FUNDAMENTAL) { if struct_data.flags.contains(StructFlags::IS_FUNDAMENTAL) {
let next = subs.type_parameters(Interner).next(); let next = subs.type_parameters(Interner).next();
match next { match next {
Some(ty) => ty, Some(it) => ty = it,
None => ty, None => break ty,
} }
} else { } else {
ty break ty;
}
}
_ => break ty,
} }
} }
_ => ty,
}; };
// - At least one of the types `T0..=Tn`` must be a local type. Let `Ti`` be the first such type. // - 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| { 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 {}
"#,
);
}
} }