about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-12-02 12:57:38 -0500
committerNiko Matsakis <niko@alum.mit.edu>2014-12-08 15:51:38 -0500
commit87edbea9da1d7dfd7e8c68e15f846f08d5f3a8c0 (patch)
tree6292fe21bf40e35ba3509ce7317790a8e0934bac
parent2e996ffb46d4f9e58d111d7e0de21602ac92411f (diff)
downloadrust-87edbea9da1d7dfd7e8c68e15f846f08d5f3a8c0.tar.gz
rust-87edbea9da1d7dfd7e8c68e15f846f08d5f3a8c0.zip
Add ability to configure recursion limit.
Fixes #19318.
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/middle/recursion_limit.rs39
-rw-r--r--src/librustc_driver/driver.rs4
-rw-r--r--src/test/compile-fail/recursion_limit.rs47
4 files changed, 91 insertions, 0 deletions
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index a964609e4e6..2af6a487629 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -88,6 +88,7 @@ pub mod middle {
     pub mod privacy;
     pub mod reachable;
     pub mod region;
+    pub mod recursion_limit;
     pub mod resolve;
     pub mod resolve_lifetime;
     pub mod stability;
diff --git a/src/librustc/middle/recursion_limit.rs b/src/librustc/middle/recursion_limit.rs
new file mode 100644
index 00000000000..a6a6703353c
--- /dev/null
+++ b/src/librustc/middle/recursion_limit.rs
@@ -0,0 +1,39 @@
+// Copyright 2012 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.
+
+// Recursion limit.
+//
+// There are various parts of the compiler that must impose arbitrary limits
+// on how deeply they recurse to prevent stack overflow. Users can override
+// this via an attribute on the crate like `#![recursion_limit(22)]`. This pass
+// just peeks and looks for that attribute.
+
+use session::Session;
+use syntax::ast;
+use syntax::attr::AttrMetaMethods;
+use std::str::FromStr;
+
+pub fn update_recursion_limit(sess: &Session, krate: &ast::Crate) {
+    for attr in krate.attrs.iter() {
+        if !attr.check_name("recursion_limit") {
+            continue;
+        }
+
+        if let Some(s) = attr.value_str() {
+            if let Some(n) = FromStr::from_str(s.get()) {
+                sess.recursion_limit.set(n);
+                return;
+            }
+        }
+
+        sess.span_err(attr.span, "malformed recursion limit attribute, \
+                                  expected #![recursion_limit(\"N\")]");
+    }
+}
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index f3d76a8f12f..749bed15e38 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -180,6 +180,10 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         *sess.features.borrow_mut() = features;
     });
 
+    time(time_passes, "recursion limit", (), |_| {
+        middle::recursion_limit::update_recursion_limit(sess, &krate);
+    });
+
     // strip before expansion to allow macros to depend on
     // configuration variables e.g/ in
     //
diff --git a/src/test/compile-fail/recursion_limit.rs b/src/test/compile-fail/recursion_limit.rs
new file mode 100644
index 00000000000..35713f7cfa2
--- /dev/null
+++ b/src/test/compile-fail/recursion_limit.rs
@@ -0,0 +1,47 @@
+// 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.
+
+#![feature(macro_rules)]
+#![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(uint) }
+
+fn is_send<T:Send>() { }
+
+fn main() {
+    is_send::<A>();
+    //~^ ERROR not implemented
+    //~^^ ERROR not implemented
+}