Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/method_resolution.rs29
-rw-r--r--crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs13
2 files changed, 30 insertions, 12 deletions
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<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 {}
+ "#,
+ );
+ }
}