Skip to content

Commit 87edbea

Browse files
committed
Add ability to configure recursion limit.
Fixes #19318.
1 parent 2e996ff commit 87edbea

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

src/librustc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ pub mod middle {
8888
pub mod privacy;
8989
pub mod reachable;
9090
pub mod region;
91+
pub mod recursion_limit;
9192
pub mod resolve;
9293
pub mod resolve_lifetime;
9394
pub mod stability;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Recursion limit.
12+
//
13+
// There are various parts of the compiler that must impose arbitrary limits
14+
// on how deeply they recurse to prevent stack overflow. Users can override
15+
// this via an attribute on the crate like `#![recursion_limit(22)]`. This pass
16+
// just peeks and looks for that attribute.
17+
18+
use session::Session;
19+
use syntax::ast;
20+
use syntax::attr::AttrMetaMethods;
21+
use std::str::FromStr;
22+
23+
pub fn update_recursion_limit(sess: &Session, krate: &ast::Crate) {
24+
for attr in krate.attrs.iter() {
25+
if !attr.check_name("recursion_limit") {
26+
continue;
27+
}
28+
29+
if let Some(s) = attr.value_str() {
30+
if let Some(n) = FromStr::from_str(s.get()) {
31+
sess.recursion_limit.set(n);
32+
return;
33+
}
34+
}
35+
36+
sess.span_err(attr.span, "malformed recursion limit attribute, \
37+
expected #![recursion_limit(\"N\")]");
38+
}
39+
}

src/librustc_driver/driver.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ pub fn phase_2_configure_and_expand(sess: &Session,
180180
*sess.features.borrow_mut() = features;
181181
});
182182

183+
time(time_passes, "recursion limit", (), |_| {
184+
middle::recursion_limit::update_recursion_limit(sess, &krate);
185+
});
186+
183187
// strip before expansion to allow macros to depend on
184188
// configuration variables e.g/ in
185189
//
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that the recursion limit can be changed. In this case, we have
12+
// deeply nested types that will fail the `Send` check by overflow
13+
// when the recursion limit is set very low.
14+
15+
#![feature(macro_rules)]
16+
#![allow(dead_code)]
17+
#![recursion_limit="10"]
18+
19+
macro_rules! link {
20+
($id:ident, $t:ty) => {
21+
enum $id { $id($t) }
22+
}
23+
}
24+
25+
link!(A,B)
26+
link!(B,C)
27+
link!(C,D)
28+
link!(D,E)
29+
link!(E,F)
30+
link!(F,G)
31+
link!(G,H)
32+
link!(H,I)
33+
link!(I,J)
34+
link!(J,K)
35+
link!(K,L)
36+
link!(L,M)
37+
link!(M,N)
38+
39+
enum N { N(uint) }
40+
41+
fn is_send<T:Send>() { }
42+
43+
fn main() {
44+
is_send::<A>();
45+
//~^ ERROR not implemented
46+
//~^^ ERROR not implemented
47+
}

0 commit comments

Comments
 (0)