]> git.lizzy.rs Git - rust.git/commitdiff
Add ability to configure recursion limit.
authorNiko Matsakis <niko@alum.mit.edu>
Tue, 2 Dec 2014 17:57:38 +0000 (12:57 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Mon, 8 Dec 2014 20:51:38 +0000 (15:51 -0500)
Fixes #19318.

src/librustc/lib.rs
src/librustc/middle/recursion_limit.rs [new file with mode: 0644]
src/librustc_driver/driver.rs
src/test/compile-fail/recursion_limit.rs [new file with mode: 0644]

index a964609e4e63404b928e95528f853c1ace0f3c23..2af6a4876299b69ba043106133179764f06d39ad 100644 (file)
@@ -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 (file)
index 0000000..a6a6703
--- /dev/null
@@ -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\")]");
+    }
+}
index f3d76a8f12f1f38f37b80d4b8293a24e1586156b..749bed15e38e05cc05a4c293d35f667327f1fed3 100644 (file)
@@ -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 (file)
index 0000000..35713f7
--- /dev/null
@@ -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
+}