Skip to content

Commit c53693d

Browse files
Fisher Darlingfisherdarling
Fisher Darling
authored andcommitted
Handle recursion_limit parsing errors
1 parent 116dff9 commit c53693d

File tree

10 files changed

+112
-6
lines changed

10 files changed

+112
-6
lines changed

src/librustc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#![feature(associated_type_bounds)]
5151
#![feature(rustc_attrs)]
5252
#![feature(hash_raw_entry)]
53+
#![feature(int_error_matching)]
5354
#![recursion_limit = "512"]
5455

5556
#[macro_use]

src/librustc/middle/recursion_limit.rs

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,60 @@
66
// just peeks and looks for that attribute.
77

88
use crate::session::Session;
9+
use core::num::IntErrorKind;
10+
use rustc::bug;
911
use rustc_span::symbol::{sym, Symbol};
1012
use syntax::ast;
1113

1214
use rustc_data_structures::sync::Once;
1315

1416
pub fn update_limits(sess: &Session, krate: &ast::Crate) {
15-
update_limit(krate, &sess.recursion_limit, sym::recursion_limit, 128);
16-
update_limit(krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
17+
update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
18+
update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
1719
}
1820

19-
fn update_limit(krate: &ast::Crate, limit: &Once<usize>, name: Symbol, default: usize) {
21+
fn update_limit(
22+
sess: &Session,
23+
krate: &ast::Crate,
24+
limit: &Once<usize>,
25+
name: Symbol,
26+
default: usize,
27+
) {
2028
for attr in &krate.attrs {
2129
if !attr.check_name(name) {
2230
continue;
2331
}
2432

2533
if let Some(s) = attr.value_str() {
26-
if let Some(n) = s.as_str().parse().ok() {
27-
limit.set(n);
28-
return;
34+
match s.as_str().parse() {
35+
Ok(n) => {
36+
limit.set(n);
37+
return;
38+
}
39+
Err(e) => {
40+
let mut err = sess.struct_span_err(
41+
attr.span,
42+
"`recursion_limit` must be a non-negative integer",
43+
);
44+
45+
let value_span = attr
46+
.meta()
47+
.and_then(|meta| meta.name_value_literal().cloned())
48+
.map(|lit| lit.span)
49+
.unwrap_or(attr.span);
50+
51+
let error_str = match e.kind() {
52+
IntErrorKind::Overflow => "`recursion_limit` is too large",
53+
IntErrorKind::Empty => "`recursion_limit` must be a non-negative integer",
54+
IntErrorKind::InvalidDigit => "not a valid integer",
55+
IntErrorKind::Underflow => bug!("`recursion_limit` should never underflow"),
56+
IntErrorKind::Zero => bug!("zero is a valid `recursion_limit`"),
57+
kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
58+
};
59+
60+
err.span_label(value_span, error_str);
61+
err.emit();
62+
}
2963
}
3064
}
3165
}

src/test/ui/recursion_limit/empty.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Test the parse error for an empty recursion_limit
2+
3+
#![recursion_limit = ""] //~ ERROR `recursion_limit` must be a non-negative integer
4+
//~| `recursion_limit` must be a non-negative integer
5+
6+
fn main() {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: `recursion_limit` must be a non-negative integer
2+
--> $DIR/empty.rs:3:1
3+
|
4+
LL | #![recursion_limit = ""]
5+
| ^^^^^^^^^^^^^^^^^^^^^--^
6+
| |
7+
| `recursion_limit` must be a non-negative integer
8+
9+
error: aborting due to previous error
10+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Test the parse error for an invalid digit in recursion_limit
2+
3+
#![recursion_limit = "-100"] //~ ERROR `recursion_limit` must be a non-negative integer
4+
//~| not a valid integer
5+
6+
fn main() {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: `recursion_limit` must be a non-negative integer
2+
--> $DIR/invalid_digit.rs:3:1
3+
|
4+
LL | #![recursion_limit = "-100"]
5+
| ^^^^^^^^^^^^^^^^^^^^^------^
6+
| |
7+
| not a valid integer
8+
9+
error: aborting due to previous error
10+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Test the parse error for an overflowing recursion_limit
2+
3+
#![recursion_limit = "999999999999999999999999"]
4+
//~^ ERROR `recursion_limit` must be a non-negative integer
5+
//~| `recursion_limit` is too large
6+
7+
fn main() {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: `recursion_limit` must be a non-negative integer
2+
--> $DIR/overflow.rs:3:1
3+
|
4+
LL | #![recursion_limit = "999999999999999999999999"]
5+
| ^^^^^^^^^^^^^^^^^^^^^--------------------------^
6+
| |
7+
| `recursion_limit` is too large
8+
9+
error: aborting due to previous error
10+

src/test/ui/recursion_limit/zero.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Test that a `recursion_limit` of 0 is valid
2+
3+
#![recursion_limit = "0"]
4+
5+
macro_rules! test {
6+
() => {};
7+
($tt:tt) => { test!(); };
8+
}
9+
10+
test!(test); //~ ERROR 10:1: 10:13: recursion limit reached while expanding `test!`
11+
12+
fn main() {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: recursion limit reached while expanding `test!`
2+
--> $DIR/zero.rs:10:1
3+
|
4+
LL | test!(test);
5+
| ^^^^^^^^^^^^
6+
|
7+
= help: consider adding a `#![recursion_limit="0"]` attribute to your crate (`zero`)
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)