Skip to content

Commit 7cabe02

Browse files
committed
fix: Infinite loop while elaborting predicates
1 parent db0420c commit 7cabe02

File tree

5 files changed

+68
-3
lines changed

5 files changed

+68
-3
lines changed

crates/hir-ty/src/dyn_compatibility.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b
138138

139139
let interner = DbInterner::new_with(db, Some(krate), None);
140140
let predicates = db.generic_predicates_ns(def);
141+
// FIXME: We should use `explicit_predicates_of` here, which hasn't been implemented to
142+
// rust-analyzer yet
143+
// https://github.com/rust-lang/rust/blob/ddaf12390d3ffb7d5ba74491a48f3cd528e5d777/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L490
141144
elaborate::elaborate(interner, predicates.iter().copied()).any(|pred| {
142145
match pred.kind().skip_binder() {
143146
ClauseKind::Trait(trait_pred) => {

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,8 @@ trait Bar<T> {
253253
trait Baz : Bar<Self> {
254254
}
255255
"#,
256-
[("Bar", vec![]), ("Baz", vec![SizedSelf, SelfReferential])],
256+
// FIXME: We should also report `SizedSelf` here
257+
[("Bar", vec![]), ("Baz", vec![SelfReferential])],
257258
);
258259
}
259260

crates/hir-ty/src/lower_nextsolver.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,9 @@ where
13581358
}
13591359
}
13601360

1361+
// FIXME: rustc gathers more predicates by recursing through resulting trait predicates.
1362+
// See https://github.com/rust-lang/rust/blob/76c5ed2847cdb26ef2822a3a165d710f6b772217/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L689-L715
1363+
13611364
(
13621365
GenericPredicates(predicates.is_empty().not().then(|| predicates.into())),
13631366
create_diagnostics(ctx.diagnostics),

crates/hir-ty/src/next_solver/interner.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use base_db::Crate;
55
use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variances};
66
use hir_def::lang_item::LangItem;
77
use hir_def::signatures::{FieldData, FnFlags, ImplFlags, StructFlags, TraitFlags};
8-
use hir_def::{AdtId, BlockId, TypeAliasId, VariantId};
8+
use hir_def::{AdtId, BlockId, GenericDefId, TypeAliasId, VariantId};
99
use hir_def::{AttrDefId, Lookup};
1010
use hir_def::{CallableDefId, EnumVariantId, ItemContainerId, StructId, UnionId};
1111
use intern::sym::non_exhaustive;
@@ -1334,6 +1334,15 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
13341334
.db()
13351335
.generic_predicates_ns(def_id.0.into())
13361336
.iter()
1337+
.filter(|p| match p.kind().skip_binder() {
1338+
rustc_type_ir::ClauseKind::Trait(tr) => match tr.self_ty().kind() {
1339+
rustc_type_ir::TyKind::Param(param) => {
1340+
param.id.parent() == def_id.0.into() && param.index == 0
1341+
}
1342+
_ => false,
1343+
},
1344+
_ => true,
1345+
})
13371346
.cloned()
13381347
.map(|p| (p, Span::dummy()))
13391348
.collect();
@@ -1345,10 +1354,28 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
13451354
self,
13461355
def_id: Self::DefId,
13471356
) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
1357+
fn is_self_or_assoc(def_id: GenericDefId, ty: Ty<'_>) -> bool {
1358+
match ty.kind() {
1359+
rustc_type_ir::TyKind::Param(param) => {
1360+
param.index == 0 && param.id.parent() == def_id
1361+
}
1362+
rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Projection, alias) => {
1363+
is_self_or_assoc(def_id, alias.self_ty())
1364+
}
1365+
_ => false,
1366+
}
1367+
}
1368+
1369+
let def_id = def_id.try_into().unwrap();
1370+
13481371
let predicates: Vec<(Clause<'db>, Span)> = self
13491372
.db()
1350-
.generic_predicates_ns(def_id.try_into().unwrap())
1373+
.generic_predicates_ns(def_id)
13511374
.iter()
1375+
.filter(|p| match p.kind().skip_binder() {
1376+
rustc_type_ir::ClauseKind::Trait(tr) => is_self_or_assoc(def_id, tr.self_ty()),
1377+
_ => true,
1378+
})
13521379
.cloned()
13531380
.map(|p| (p, Span::dummy()))
13541381
.collect();

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,34 @@ fn main() {
116116
"#]],
117117
);
118118
}
119+
120+
#[test]
121+
fn no_infinite_loop_on_super_predicates_elaboration() {
122+
check_infer(
123+
r#"
124+
//- minicore: sized
125+
trait DimMax<Other: Dimension> {
126+
type Output: Dimension;
127+
}
128+
129+
trait Dimension: DimMax<<Self as Dimension>:: Smaller, Output = Self> {
130+
type Smaller: Dimension;
131+
}
132+
133+
fn test<T, U>(t: T)
134+
where
135+
T: DimMax<U>,
136+
U: Dimension,
137+
{
138+
let t: <T as DimMax<U>>::Output = loop {};
139+
}
140+
"#,
141+
expect![[r#"
142+
182..183 't': T
143+
230..280 '{ ... {}; }': ()
144+
240..241 't': <T as DimMax<U>>::Output
145+
270..277 'loop {}': !
146+
275..277 '{}': ()
147+
"#]],
148+
)
149+
}

0 commit comments

Comments
 (0)