diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index 4f4e5c6a2c9..bd9d89deee1 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -16,6 +16,10 @@ middle_limit_invalid = `limit` must be a non-negative integer .label = {$error_str} +middle_recursion_limit_reached = + reached the recursion limit finding the struct tail for `{$ty}` + .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` + middle_const_eval_non_int = constant evaluation of enum discriminant resulted in non-integer diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 5e94da8cb4d..dc4aa18640f 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -49,6 +49,14 @@ pub struct LimitInvalid<'a> { pub error_str: &'a str, } +#[derive(Diagnostic)] +#[diag(middle_recursion_limit_reached)] +#[help] +pub struct RecursionLimitReached<'tcx> { + pub ty: Ty<'tcx>, + pub suggested_limit: rustc_session::Limit, +} + #[derive(Diagnostic)] #[diag(middle_const_eval_non_int)] pub struct ConstEvalNonIntError { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index d3565b28ae5..4411bcd927d 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -19,7 +19,8 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::bit_set::GrowableBitSet; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; -use rustc_span::{sym, DUMMY_SP}; +use rustc_session::Limit; +use rustc_span::sym; use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout}; use rustc_target::spec::abi::Abi; use smallvec::SmallVec; @@ -225,10 +226,13 @@ impl<'tcx> TyCtxt<'tcx> { let recursion_limit = self.recursion_limit(); for iteration in 0.. { if !recursion_limit.value_within_limit(iteration) { - return self.ty_error_with_message( - DUMMY_SP, - &format!("reached the recursion limit finding the struct tail for {}", ty), - ); + let suggested_limit = match recursion_limit { + Limit(0) => Limit(2), + limit => limit * 2, + }; + let reported = + self.sess.emit_err(crate::error::RecursionLimitReached { ty, suggested_limit }); + return self.ty_error(reported); } match *ty.kind() { ty::Adt(def, substs) => { diff --git a/tests/ui/autoref-autoderef/issue-38940.rs b/tests/ui/autoref-autoderef/issue-38940.rs deleted file mode 100644 index d2f1c6e3271..00000000000 --- a/tests/ui/autoref-autoderef/issue-38940.rs +++ /dev/null @@ -1,52 +0,0 @@ -// issue-38940: error printed twice for deref recursion limit exceeded -// Test that the recursion limit can be changed. In this case, we have -// deeply nested types that will fail the `Send` check by overflow -// when the recursion limit is set very low. -// compile-flags: -Zdeduplicate-diagnostics=yes - -#![allow(dead_code)] -#![recursion_limit = "10"] -macro_rules! link { - ($outer:ident, $inner:ident) => { - struct $outer($inner); - impl $outer { - fn new() -> $outer { - $outer($inner::new()) - } - } - impl std::ops::Deref for $outer { - type Target = $inner; - fn deref(&self) -> &$inner { - &self.0 - } - } - }; -} - -struct Bottom; - -impl Bottom { - fn new() -> Bottom { - Bottom - } -} - -link!(Top, A); -link!(A, B); -link!(B, C); -link!(C, D); -link!(D, E); -link!(E, F); -link!(F, G); -link!(G, H); -link!(H, I); -link!(I, J); -link!(J, K); -link!(K, Bottom); - -fn main() { - let t = Top::new(); - let x: &Bottom = &t; - //~^ ERROR mismatched types - //~| ERROR reached the recursion limit while auto-dereferencing `J` -} diff --git a/tests/ui/autoref-autoderef/issue-38940.stderr b/tests/ui/autoref-autoderef/issue-38940.stderr deleted file mode 100644 index 8e98bfcd90f..00000000000 --- a/tests/ui/autoref-autoderef/issue-38940.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0055]: reached the recursion limit while auto-dereferencing `J` - --> $DIR/issue-38940.rs:49:22 - | -LL | let x: &Bottom = &t; - | ^^ deref recursion limit reached - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`issue_38940`) - -error[E0308]: mismatched types - --> $DIR/issue-38940.rs:49:22 - | -LL | let x: &Bottom = &t; - | ------- ^^ expected `&Bottom`, found `&Top` - | | - | expected due to this - | - = note: expected reference `&Bottom` - found reference `&Top` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0055, E0308. -For more information about an error, try `rustc --explain E0055`. diff --git a/tests/ui/did_you_mean/recursion_limit_deref.stderr b/tests/ui/did_you_mean/recursion_limit_deref.stderr index 32fb628c470..b0c493faf1e 100644 --- a/tests/ui/did_you_mean/recursion_limit_deref.stderr +++ b/tests/ui/did_you_mean/recursion_limit_deref.stderr @@ -1,3 +1,7 @@ +error: reached the recursion limit finding the struct tail for `Bottom` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` + error[E0055]: reached the recursion limit while auto-dereferencing `J` --> $DIR/recursion_limit_deref.rs:51:22 | @@ -17,7 +21,7 @@ LL | let x: &Bottom = &t; = note: expected reference `&Bottom` found reference `&Top` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0055, E0308. For more information about an error, try `rustc --explain E0055`.