diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index d887013b6f..10b8dd2a3a 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -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| { diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs b/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs index 78a04e1542..35dc9b0fac 100644 --- a/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs +++ b/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs @@ -104,4 +104,17 @@ impl foo::Foo 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 {} + "#, + ); + } }