diff options
| author | David Barsky <me@davidbarsky.com> | 2025-03-28 02:53:14 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-28 02:53:14 +0000 |
| commit | c2ce9a9d7d693f322299c6775d5eecfb87d7bae0 (patch) | |
| tree | 142958b9a56151a72a5d8843102cca9d082fc0dc | |
| parent | 5aeb82f6677dca53318d9a633cecb590c024aa4a (diff) | |
| parent | 14410b6369e7fbe221f37421b1840c51c663c6ca (diff) | |
| download | rust-c2ce9a9d7d693f322299c6775d5eecfb87d7bae0.tar.gz rust-c2ce9a9d7d693f322299c6775d5eecfb87d7bae0.zip | |
Merge pull request #19466 from ChayimFriedman2/bug-coherence
fix: Fix a bug in orphan rules calculation
| -rw-r--r-- | src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs | 29 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs | 13 |
2 files changed, 30 insertions, 12 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index d887013b6ff..10b8dd2a3a6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs index 78a04e15424..35dc9b0fac8 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs +++ b/src/tools/rust-analyzer/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 {} + "#, + ); + } } |
