if self.steps.len() == tcx.sess.recursion_limit.get() {
// We've reached the recursion limit, error gracefully.
+ let suggested_limit = tcx.sess.recursion_limit.get() * 2;
struct_span_err!(tcx.sess,
self.span,
E0055,
"reached the recursion limit while auto-dereferencing {:?}",
self.cur_ty)
.span_label(self.span, &format!("deref recursion limit reached"))
+ .help(&format!(
+ "consider adding a `#[recursion_limit=\"{}\"]` attribute to your crate",
+ suggested_limit))
.emit();
return None;
}
use attr::HasAttrs;
use codemap::{self, CodeMap, ExpnInfo, Spanned, respan};
use syntax_pos::{Span, ExpnId, NO_EXPANSION};
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder, FatalError};
use ext::expand::{self, Expansion};
use ext::hygiene::Mark;
use fold::{self, Folder};
pub fn bt_push(&mut self, ei: ExpnInfo) {
if self.current_expansion.depth > self.ecfg.recursion_limit {
- self.span_fatal(ei.call_site,
- &format!("recursion limit reached while expanding the macro `{}`",
- ei.callee.name()));
+ let suggested_limit = self.ecfg.recursion_limit * 2;
+ let mut err = self.struct_span_fatal(ei.call_site,
+ &format!("recursion limit reached while expanding the macro `{}`",
+ ei.callee.name()));
+ err.note(&format!(
+ "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
+ suggested_limit));
+ err.emit();
+ panic!(FatalError);
}
let mut call_site = ei.call_site;
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// 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.
-
-#![allow(dead_code)]
-#![recursion_limit="10"]
-
-macro_rules! link {
- ($id:ident, $t:ty) => {
- enum $id { $id($t) }
- }
-}
-
-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, L }
-link! { L, M }
-link! { M, N }
-
-enum N { N(usize) }
-
-fn is_send<T:Send>() { }
-
-fn main() {
- is_send::<A>();
- //~^ ERROR overflow evaluating
- //~| NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
- //~| NOTE required because it appears within the type `A`
- //~| NOTE required because it appears within the type `B`
- //~| NOTE required because it appears within the type `C`
- //~| NOTE required because it appears within the type `D`
- //~| NOTE required because it appears within the type `E`
- //~| NOTE required because it appears within the type `F`
- //~| NOTE required because it appears within the type `G`
- //~| NOTE required because it appears within the type `H`
- //~| NOTE required because it appears within the type `I`
- //~| NOTE required because it appears within the type `J`
- //~| NOTE required by `is_send`
-}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the recursion limit can be changed and that the compiler
+// suggests a fix. In this case, we have deeply nested types that will
+// fail the `Send` check by overflow when the recursion limit is set
+// very low.
+
+#![allow(dead_code)]
+#![recursion_limit="10"]
+
+macro_rules! link {
+ ($id:ident, $t:ty) => {
+ enum $id { $id($t) }
+ }
+}
+
+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, L }
+link! { L, M }
+link! { M, N }
+
+enum N { N(usize) }
+
+fn is_send<T:Send>() { }
+
+fn main() {
+ is_send::<A>();
+}
--- /dev/null
+error[E0275]: overflow evaluating the requirement `K: std::marker::Send`
+ --> $DIR/recursion_limit.rs:44:5
+ |
+44 | is_send::<A>();
+ | ^^^^^^^^^^^^
+ |
+ = note: consider adding a `#![recursion_limit="20"]` attribute to your crate
+ = note: required because it appears within the type `J`
+ = note: required because it appears within the type `I`
+ = note: required because it appears within the type `H`
+ = note: required because it appears within the type `G`
+ = note: required because it appears within the type `F`
+ = note: required because it appears within the type `E`
+ = note: required because it appears within the type `D`
+ = note: required because it appears within the type `C`
+ = note: required because it appears within the type `B`
+ = note: required because it appears within the type `A`
+ = note: required by `is_send`
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the recursion limit can be changed and that the compiler
+// suggests a fix. In this case, we have a long chain of Deref impls
+// which will cause an overflow during the autoderef loop.
+
+#![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;
+}
+
--- /dev/null
+error[E0055]: reached the recursion limit while auto-dereferencing I
+ --> $DIR/recursion_limit_deref.rs:60:22
+ |
+60 | let x: &Bottom = &t;
+ | ^^ deref recursion limit reached
+ |
+ = help: consider adding a `#[recursion_limit="20"]` attribute to your crate
+
+error[E0055]: reached the recursion limit while auto-dereferencing I
+ |
+ = help: consider adding a `#[recursion_limit="20"]` attribute to your crate
+
+error[E0308]: mismatched types
+ --> $DIR/recursion_limit_deref.rs:60:22
+ |
+60 | let x: &Bottom = &t;
+ | ^^ expected struct `Bottom`, found struct `Top`
+ |
+ = note: expected type `&Bottom`
+ found type `&Top`
+
+error: aborting due to 3 previous errors
+
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the recursion limit can be changed and that the compiler
+// suggests a fix. In this case, we have a recursing macro that will
+// overflow if the number of arguments surpasses the recursion limit.
+
+#![allow(dead_code)]
+#![recursion_limit="10"]
+
+macro_rules! recurse {
+ () => { };
+ ($t:tt $($tail:tt)*) => { recurse!($($tail)*) };
+}
+
+fn main() {
+ recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9);
+}
+
--- /dev/null
+error: recursion limit reached while expanding the macro `recurse`
+ --> $DIR/recursion_limit_macro.rs:20:31
+ |
+20 | ($t:tt $($tail:tt)*) => { recurse!($($tail)*) };
+ | ^^^^^^^^^^^^^^^^^^^
+...
+24 | recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9);
+ | -------------------------------------------------- in this macro invocation
+ |
+ = note: consider adding a `#![recursion_limit="20"]` attribute to your crate
+