about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChayim Refael Friedman <chayimfr@gmail.com>2025-09-14 11:20:04 +0000
committerGitHub <noreply@github.com>2025-09-14 11:20:04 +0000
commitd6d3c4b2ea2c35c92ab773209ba1a617dcdd56a2 (patch)
treef1b987782ad476d10ce9b10d6f56425e2763c88b
parentc2e1012fd88ae0d308068feeee9baca52ac7cd12 (diff)
parent9f850ceb33b2f55084362dddd2396db8469779bd (diff)
downloadrust-d6d3c4b2ea2c35c92ab773209ba1a617dcdd56a2.tar.gz
rust-d6d3c4b2ea2c35c92ab773209ba1a617dcdd56a2.zip
Merge pull request #20654 from ShoyuVanilla/predicates
fix: Infinite loop while elaborting predicates
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs23
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs31
5 files changed, 61 insertions, 2 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
index d4b3751cf56..b87c9982177 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
@@ -138,6 +138,9 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b
 
     let interner = DbInterner::new_with(db, Some(krate), None);
     let predicates = db.generic_predicates_ns(def);
+    // FIXME: We should use `explicit_predicates_of` here, which hasn't been implemented to
+    // rust-analyzer yet
+    // https://github.com/rust-lang/rust/blob/ddaf12390d3ffb7d5ba74491a48f3cd528e5d777/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L490
     elaborate::elaborate(interner, predicates.iter().copied()).any(|pred| {
         match pred.kind().skip_binder() {
             ClauseKind::Trait(trait_pred) => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs
index 4ffa4550849..04a9ba79921 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs
@@ -253,7 +253,8 @@ trait Bar<T> {
 trait Baz : Bar<Self> {
 }
 "#,
-        [("Bar", vec![]), ("Baz", vec![SizedSelf, SelfReferential])],
+        // FIXME: We should also report `SizedSelf` here
+        [("Bar", vec![]), ("Baz", vec![SelfReferential])],
     );
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs
index c6a8fa81edf..5c29befe123 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs
@@ -1358,6 +1358,9 @@ where
         }
     }
 
+    // FIXME: rustc gathers more predicates by recursing through resulting trait predicates.
+    // See https://github.com/rust-lang/rust/blob/76c5ed2847cdb26ef2822a3a165d710f6b772217/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L689-L715
+
     (
         GenericPredicates(predicates.is_empty().not().then(|| predicates.into())),
         create_diagnostics(ctx.diagnostics),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs
index 0f512fdaf86..7b6e8a1073d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs
@@ -5,7 +5,7 @@ use base_db::Crate;
 use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variances};
 use hir_def::lang_item::LangItem;
 use hir_def::signatures::{FieldData, FnFlags, ImplFlags, StructFlags, TraitFlags};
-use hir_def::{AdtId, BlockId, TypeAliasId, VariantId};
+use hir_def::{AdtId, BlockId, GenericDefId, TypeAliasId, VariantId};
 use hir_def::{AttrDefId, Lookup};
 use hir_def::{CallableDefId, EnumVariantId, ItemContainerId, StructId, UnionId};
 use intern::sym::non_exhaustive;
@@ -1334,6 +1334,13 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
             .db()
             .generic_predicates_ns(def_id.0.into())
             .iter()
+            .filter(|p| match p.kind().skip_binder() {
+                rustc_type_ir::ClauseKind::Trait(tr) => match tr.self_ty().kind() {
+                    rustc_type_ir::TyKind::Param(param) => param.index == 0,
+                    _ => false,
+                },
+                _ => true,
+            })
             .cloned()
             .map(|p| (p, Span::dummy()))
             .collect();
@@ -1345,10 +1352,24 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
         self,
         def_id: Self::DefId,
     ) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
+        fn is_self_or_assoc(ty: Ty<'_>) -> bool {
+            match ty.kind() {
+                rustc_type_ir::TyKind::Param(param) => param.index == 0,
+                rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Projection, alias) => {
+                    is_self_or_assoc(alias.self_ty())
+                }
+                _ => false,
+            }
+        }
+
         let predicates: Vec<(Clause<'db>, Span)> = self
             .db()
             .generic_predicates_ns(def_id.try_into().unwrap())
             .iter()
+            .filter(|p| match p.kind().skip_binder() {
+                rustc_type_ir::ClauseKind::Trait(tr) => is_self_or_assoc(tr.self_ty()),
+                _ => true,
+            })
             .cloned()
             .map(|p| (p, Span::dummy()))
             .collect();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs
index 4df788638a3..595f285bd93 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs
@@ -116,3 +116,34 @@ fn main() {
         "#]],
     );
 }
+
+#[test]
+fn no_infinite_loop_on_super_predicates_elaboration() {
+    check_infer(
+        r#"
+//- minicore: sized
+trait DimMax<Other: Dimension> {
+    type Output: Dimension;
+}
+
+trait Dimension: DimMax<<Self as Dimension>:: Smaller, Output = Self> {
+    type Smaller: Dimension;
+}
+
+fn test<T, U>(t: T)
+where
+    T: DimMax<U>,
+    U: Dimension,
+{
+    let t: <T as DimMax<U>>::Output = loop {};
+}
+"#,
+        expect![[r#"
+            182..183 't': T
+            230..280 '{     ... {}; }': ()
+            240..241 't': <T as DimMax<U>>::Output
+            270..277 'loop {}': !
+            275..277 '{}': ()
+        "#]],
+    )
+}