diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index a20c299d0cbb..05a9b4ba342a 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -1551,7 +1551,7 @@ impl<'db> GenericPredicates<'db> { /// Resolve the where clause(s) of an item with generics. /// /// Diagnostics are computed only for this item's predicates, not for parents. - #[salsa::tracked(returns(ref), unsafe(non_update_return_type))] + #[salsa::tracked(returns(ref), unsafe(non_update_return_type), cycle_result = generic_predicates_query_with_diagnostics_cycle_result)] pub fn query_with_diagnostics( db: &'db dyn HirDatabase, def: GenericDefId, @@ -1560,6 +1560,21 @@ impl<'db> GenericPredicates<'db> { } } +pub(crate) fn generic_predicates_query_with_diagnostics_cycle_result<'db>( + _db: &'db dyn HirDatabase, + _def: GenericDefId, +) -> (GenericPredicates<'db>, Diagnostics) { + ( + GenericPredicates { + predicates: EarlyBinder::bind(Box::new([])), + own_predicates_start: 0, + is_trait: false, + parent_is_trait: false, + }, + None, + ) +} + impl<'db> GenericPredicates<'db> { #[inline] pub fn query(db: &'db dyn HirDatabase, def: GenericDefId) -> &'db GenericPredicates<'db> { diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index f03f8d754f2a..67d107093671 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -2562,3 +2562,35 @@ fn main() { "#, ); } + +#[test] +fn issue_21006_cyclic_type_alias_in_trait_bounds() { + // Test for cyclic dependency in generic predicates when a trait's where clause + // references a type alias that depends on the trait itself. + // Pattern from opaque-ke: trait CipherSuite where OprfHash: Trait + // + type OprfHash = ::Type + // This should not panic rust-analyzer due to cyclic predicates. + check_no_mismatches( + r#" +trait Hash {} +trait Trait { + type Assoc: Trait; +} + +// Type alias that projects an associated type from a trait bound +type MyHash = ::Assoc; + +// Trait with where clause referencing the type alias with Self +trait CipherSuite +where + MyHash: Hash, +{ + type Assoc: Trait; +} + +fn test() { + // If we reach here without panic, the cycle handler is working +} + "#, + ); +}