Skip to content

Commit 1cd2211

Browse files
committed
Fix lowering with supertrait predicates
Previously both valid and invalid Rust code could crash r-a due to a cyclic query during lowering.
1 parent 4ff04e5 commit 1cd2211

File tree

2 files changed

+82
-8
lines changed

2 files changed

+82
-8
lines changed

crates/hir-ty/src/lower.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use tracing::debug;
5353
use triomphe::{Arc, ThinArc};
5454

5555
use crate::{
56-
FnAbi, ImplTraitId, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
56+
FnAbi, ImplTraitId, TyLoweringDiagnostic, TyLoweringDiagnosticKind, all_super_traits,
5757
consteval::intern_const_ref,
5858
db::{HirDatabase, InternedOpaqueTyId},
5959
generics::{Generics, generics, trait_self_param_idx},
@@ -1619,11 +1619,16 @@ pub(crate) fn field_types_with_diagnostics_query<'db>(
16191619
(res, create_diagnostics(ctx.diagnostics))
16201620
}
16211621

1622+
/// Predicates for `param_id` of the form `P: SomeTrait`. If
1623+
/// `assoc_name` is provided, only return predicates referencing traits
1624+
/// that have an associated type of that name.
1625+
///
16221626
/// This query exists only to be used when resolving short-hand associated types
16231627
/// like `T::Item`.
16241628
///
16251629
/// See the analogous query in rustc and its comment:
16261630
/// <https://github.com/rust-lang/rust/blob/9150f844e2624eb013ec78ca08c1d416e6644026/src/librustc_typeck/astconv.rs#L46>
1631+
///
16271632
/// This is a query mostly to handle cycles somewhat gracefully; e.g. the
16281633
/// following bounds are disallowed: `T: Foo<U::Item>, U: Foo<T::Item>`, but
16291634
/// these are fine: `T: Foo<U::Item>, U: Foo<()>`.
@@ -1647,7 +1652,7 @@ pub(crate) fn generic_predicates_for_param<'db>(
16471652
);
16481653

16491654
// we have to filter out all other predicates *first*, before attempting to lower them
1650-
let predicate = |pred: &_, ctx: &mut TyLoweringContext<'_, '_>| match pred {
1655+
let has_relevant_bound = |pred: &_, ctx: &mut TyLoweringContext<'_, '_>| match pred {
16511656
WherePredicate::ForLifetime { target, bound, .. }
16521657
| WherePredicate::TypeBound { target, bound, .. } => {
16531658
let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) };
@@ -1695,11 +1700,7 @@ pub(crate) fn generic_predicates_for_param<'db>(
16951700
return false;
16961701
};
16971702

1698-
rustc_type_ir::elaborate::supertrait_def_ids(interner, tr.into()).any(|tr| {
1699-
tr.0.trait_items(db).items.iter().any(|(name, item)| {
1700-
matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name
1701-
})
1702-
})
1703+
trait_or_supertrait_has_assoc_type(db, tr, assoc_name)
17031704
}
17041705
TypeBound::Use(_) | TypeBound::Lifetime(_) | TypeBound::Error => false,
17051706
}
@@ -1712,7 +1713,7 @@ pub(crate) fn generic_predicates_for_param<'db>(
17121713
{
17131714
ctx.store = maybe_parent_generics.store();
17141715
for pred in maybe_parent_generics.where_predicates() {
1715-
if predicate(pred, &mut ctx) {
1716+
if has_relevant_bound(pred, &mut ctx) {
17161717
predicates.extend(
17171718
ctx.lower_where_predicate(
17181719
pred,
@@ -1752,6 +1753,31 @@ pub(crate) fn generic_predicates_for_param_cycle_result(
17521753
StoredEarlyBinder::bind(Clauses::empty(DbInterner::new_no_crate(db)).store())
17531754
}
17541755

1756+
/// Check if this trait or any of its supertraits define an associated
1757+
/// type with the given name.
1758+
fn trait_or_supertrait_has_assoc_type(
1759+
db: &dyn HirDatabase,
1760+
tr: TraitId,
1761+
assoc_name: &Name,
1762+
) -> bool {
1763+
let mut trait_and_supertraits = vec![tr];
1764+
trait_and_supertraits.extend(&all_super_traits(db, tr));
1765+
1766+
for trait_id in trait_and_supertraits {
1767+
// Check if this trait has the associated type.
1768+
if trait_id
1769+
.trait_items(db)
1770+
.items
1771+
.iter()
1772+
.any(|(name, item)| matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name)
1773+
{
1774+
return true;
1775+
}
1776+
}
1777+
1778+
false
1779+
}
1780+
17551781
#[inline]
17561782
pub(crate) fn type_alias_bounds<'db>(
17571783
db: &'db dyn HirDatabase,

crates/hir-ty/src/tests/regression.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2563,3 +2563,51 @@ fn main() {
25632563
"#,
25642564
);
25652565
}
2566+
2567+
#[test]
2568+
fn issue_21006_generic_predicates_for_param_supertrait_cycle() {
2569+
check_no_mismatches(
2570+
r#"
2571+
trait VCipherSuite {}
2572+
2573+
trait CipherSuite
2574+
where
2575+
OprfHash<Self>: Hash,
2576+
{
2577+
}
2578+
2579+
type Bar<CS: CipherSuite> = <CS::Baz as VCipherSuite>::Hash;
2580+
2581+
type OprfHash<CS: CipherSuite> = <CS::Baz as VCipherSuite>::Hash;
2582+
2583+
impl<CS: CipherSuite> Foo<CS> {
2584+
fn seal() {}
2585+
}
2586+
"#,
2587+
);
2588+
}
2589+
2590+
#[test]
2591+
fn issue_21006_self_assoc_trait() {
2592+
check_types(
2593+
r#"
2594+
trait Baz {
2595+
fn baz(&self);
2596+
}
2597+
2598+
trait Foo {
2599+
type Assoc;
2600+
}
2601+
2602+
trait Bar: Foo
2603+
where
2604+
Self::Assoc: Baz,
2605+
{
2606+
fn bar(v: Self::Assoc) {
2607+
let _ = v.baz();
2608+
// ^ ()
2609+
}
2610+
}
2611+
"#,
2612+
);
2613+
}

0 commit comments

Comments
 (0)