about summary refs log tree commit diff
path: root/src/librustc
diff options
context:
space:
mode:
authorFisher Darling <fdarling@mines.edu>2019-12-12 21:18:21 -0700
committerFisher Darling <fdarlingco@gmail.com>2020-02-16 19:08:25 -0700
commitc53693d34d83e6221dc8b93a2c4e17e66fa6f0e2 (patch)
treedfdd15a42fa21e8ecd3cf1f8313a96688b12cd3b /src/librustc
parent116dff95a37214e86f067715374a18a4de1621f0 (diff)
Handle recursion_limit parsing errors
Diffstat (limited to 'src/librustc')
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/middle/recursion_limit.rs46
2 files changed, 41 insertions, 6 deletions
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index ceac68704d2..b5c88b33b4a 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -50,6 +50,7 @@
 #![feature(associated_type_bounds)]
 #![feature(rustc_attrs)]
 #![feature(hash_raw_entry)]
+#![feature(int_error_matching)]
 #![recursion_limit = "512"]
 
 #[macro_use]
diff --git a/src/librustc/middle/recursion_limit.rs b/src/librustc/middle/recursion_limit.rs
index b33cde8e2af..be530da5910 100644
--- a/src/librustc/middle/recursion_limit.rs
+++ b/src/librustc/middle/recursion_limit.rs
@@ -6,26 +6,60 @@
 // just peeks and looks for that attribute.
 
 use crate::session::Session;
+use core::num::IntErrorKind;
+use rustc::bug;
 use rustc_span::symbol::{sym, Symbol};
 use syntax::ast;
 
 use rustc_data_structures::sync::Once;
 
 pub fn update_limits(sess: &Session, krate: &ast::Crate) {
-    update_limit(krate, &sess.recursion_limit, sym::recursion_limit, 128);
-    update_limit(krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
+    update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
+    update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
 }
 
-fn update_limit(krate: &ast::Crate, limit: &Once<usize>, name: Symbol, default: usize) {
+fn update_limit(
+    sess: &Session,
+    krate: &ast::Crate,
+    limit: &Once<usize>,
+    name: Symbol,
+    default: usize,
+) {
     for attr in &krate.attrs {
         if !attr.check_name(name) {
             continue;
         }
 
         if let Some(s) = attr.value_str() {
-            if let Some(n) = s.as_str().parse().ok() {
-                limit.set(n);
-                return;
+            match s.as_str().parse() {
+                Ok(n) => {
+                    limit.set(n);
+                    return;
+                }
+                Err(e) => {
+                    let mut err = sess.struct_span_err(
+                        attr.span,
+                        "`recursion_limit` must be a non-negative integer",
+                    );
+
+                    let value_span = attr
+                        .meta()
+                        .and_then(|meta| meta.name_value_literal().cloned())
+                        .map(|lit| lit.span)
+                        .unwrap_or(attr.span);
+
+                    let error_str = match e.kind() {
+                        IntErrorKind::Overflow => "`recursion_limit` is too large",
+                        IntErrorKind::Empty => "`recursion_limit` must be a non-negative integer",
+                        IntErrorKind::InvalidDigit => "not a valid integer",
+                        IntErrorKind::Underflow => bug!("`recursion_limit` should never underflow"),
+                        IntErrorKind::Zero => bug!("zero is a valid `recursion_limit`"),
+                        kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
+                    };
+
+                    err.span_label(value_span, error_str);
+                    err.emit();
+                }
             }
         }
     }