Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion crates/hir-ty/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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> {
Expand Down
32 changes: 32 additions & 0 deletions crates/hir-ty/src/tests/regression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self>: Trait
// + type OprfHash<CS: CipherSuite> = <CS::Assoc as Trait>::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<T: Trait> = <T::Assoc as Trait>::Assoc;

// Trait with where clause referencing the type alias with Self
trait CipherSuite
where
MyHash<Self>: Hash,
{
type Assoc: Trait;
}

fn test<T: CipherSuite>() {
// If we reach here without panic, the cycle handler is working
}
"#,
);
}