From 268c56e14455d8889b818c4ea55470b94649aebc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 7 Apr 2025 20:35:41 +0000 Subject: [PATCH] Implement overflow for infinite implied lifetime bounds --- .../src/outlives/implicit_infer.rs | 21 +++++++++++++++---- tests/ui/implied-bounds/overflow.rs | 11 ++++++++++ tests/ui/implied-bounds/overflow.stderr | 8 +++++++ 3 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 tests/ui/implied-bounds/overflow.rs create mode 100644 tests/ui/implied-bounds/overflow.stderr diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index a0faa5e8429..780c27d4595 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -24,8 +24,8 @@ pub(super) fn infer_predicates( // If new predicates were added then we need to re-calculate // all crates since there could be new implied predicates. - loop { - let mut predicates_added = false; + for i in 0.. { + let mut predicates_added = vec![]; // Visit all the crates and infer predicates for id in tcx.hir_free_items() { @@ -83,14 +83,27 @@ pub(super) fn infer_predicates( .get(&item_did.to_def_id()) .map_or(0, |p| p.as_ref().skip_binder().len()); if item_required_predicates.len() > item_predicates_len { - predicates_added = true; + predicates_added.push(item_did); global_inferred_outlives .insert(item_did.to_def_id(), ty::EarlyBinder::bind(item_required_predicates)); } } - if !predicates_added { + if predicates_added.is_empty() { + // We've reached a fixed point. break; + } else if !tcx.recursion_limit().value_within_limit(i) { + let msg = if let &[id] = &predicates_added[..] { + format!("overflow computing implied lifetime bounds for `{}`", tcx.def_path_str(id),) + } else { + "overflow computing implied lifetime bounds".to_string() + }; + tcx.dcx() + .struct_span_fatal( + predicates_added.iter().map(|id| tcx.def_span(*id)).collect::>(), + msg, + ) + .emit(); } } diff --git a/tests/ui/implied-bounds/overflow.rs b/tests/ui/implied-bounds/overflow.rs new file mode 100644 index 00000000000..7c36998dd4d --- /dev/null +++ b/tests/ui/implied-bounds/overflow.rs @@ -0,0 +1,11 @@ +trait Tailed<'a>: 'a { + type Tail: Tailed<'a>; +} + +struct List<'a, T: Tailed<'a>> { + //~^ ERROR overflow computing implied lifetime bounds for `List` + next: Box>, + node: &'a T, +} + +fn main() {} diff --git a/tests/ui/implied-bounds/overflow.stderr b/tests/ui/implied-bounds/overflow.stderr new file mode 100644 index 00000000000..2e5a9ab141c --- /dev/null +++ b/tests/ui/implied-bounds/overflow.stderr @@ -0,0 +1,8 @@ +error: overflow computing implied lifetime bounds for `List` + --> $DIR/overflow.rs:5:1 + | +LL | struct List<'a, T: Tailed<'a>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error +