]> git.lizzy.rs Git - rust.git/commitdiff
suggest doubling recursion limit in more situations
authorAlex Burka <durka42@gmail.com>
Thu, 5 Jan 2017 23:17:12 +0000 (23:17 +0000)
committerAlex Burka <alex@alexburka.com>
Thu, 9 Feb 2017 06:40:23 +0000 (06:40 +0000)
src/librustc_typeck/check/autoderef.rs
src/libsyntax/ext/base.rs
src/test/compile-fail/recursion_limit.rs [deleted file]
src/test/ui/did_you_mean/recursion_limit.rs [new file with mode: 0644]
src/test/ui/did_you_mean/recursion_limit.stderr [new file with mode: 0644]
src/test/ui/did_you_mean/recursion_limit_deref.rs [new file with mode: 0644]
src/test/ui/did_you_mean/recursion_limit_deref.stderr [new file with mode: 0644]
src/test/ui/did_you_mean/recursion_limit_macro.rs [new file with mode: 0644]
src/test/ui/did_you_mean/recursion_limit_macro.stderr [new file with mode: 0644]

index b4647df3f4f0a6bed7b874084131c44b06379522..ca0ab8f1e8c7742b4310816e7a1a6efdc6125430 100644 (file)
@@ -54,12 +54,16 @@ fn next(&mut self) -> Option<Self::Item> {
 
         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;
         }
index 9a717b86d091ed6682cd67427c89bda2baadf850..e7f794328b8935984d39fa5ada410ff29936299c 100644 (file)
@@ -14,7 +14,7 @@
 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};
@@ -674,9 +674,15 @@ pub fn expansion_cause(&self) -> Span {
 
     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;
diff --git a/src/test/compile-fail/recursion_limit.rs b/src/test/compile-fail/recursion_limit.rs
deleted file mode 100644 (file)
index 226a6d5..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// 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`
-}
diff --git a/src/test/ui/did_you_mean/recursion_limit.rs b/src/test/ui/did_you_mean/recursion_limit.rs
new file mode 100644 (file)
index 0000000..becb81b
--- /dev/null
@@ -0,0 +1,45 @@
+// 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>();
+}
diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr
new file mode 100644 (file)
index 0000000..524aab8
--- /dev/null
@@ -0,0 +1,21 @@
+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
+
diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.rs b/src/test/ui/did_you_mean/recursion_limit_deref.rs
new file mode 100644 (file)
index 0000000..ebc56c9
--- /dev/null
@@ -0,0 +1,62 @@
+// 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;
+}
+
diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
new file mode 100644 (file)
index 0000000..57b28d0
--- /dev/null
@@ -0,0 +1,23 @@
+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
+
diff --git a/src/test/ui/did_you_mean/recursion_limit_macro.rs b/src/test/ui/did_you_mean/recursion_limit_macro.rs
new file mode 100644 (file)
index 0000000..9fb82b7
--- /dev/null
@@ -0,0 +1,26 @@
+// 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);
+}
+
diff --git a/src/test/ui/did_you_mean/recursion_limit_macro.stderr b/src/test/ui/did_you_mean/recursion_limit_macro.stderr
new file mode 100644 (file)
index 0000000..6bed78a
--- /dev/null
@@ -0,0 +1,11 @@
+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
+