suggest doubling recursion limit in more situations
This commit is contained in:
@@ -54,12 +54,16 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
if self.steps.len() == tcx.sess.recursion_limit.get() {
|
if self.steps.len() == tcx.sess.recursion_limit.get() {
|
||||||
// We've reached the recursion limit, error gracefully.
|
// We've reached the recursion limit, error gracefully.
|
||||||
|
let suggested_limit = tcx.sess.recursion_limit.get() * 2;
|
||||||
struct_span_err!(tcx.sess,
|
struct_span_err!(tcx.sess,
|
||||||
self.span,
|
self.span,
|
||||||
E0055,
|
E0055,
|
||||||
"reached the recursion limit while auto-dereferencing {:?}",
|
"reached the recursion limit while auto-dereferencing {:?}",
|
||||||
self.cur_ty)
|
self.cur_ty)
|
||||||
.span_label(self.span, &format!("deref recursion limit reached"))
|
.span_label(self.span, &format!("deref recursion limit reached"))
|
||||||
|
.help(&format!(
|
||||||
|
"consider adding a `#[recursion_limit=\"{}\"]` attribute to your crate",
|
||||||
|
suggested_limit))
|
||||||
.emit();
|
.emit();
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use ast::{self, Attribute, Name, PatKind, MetaItem};
|
|||||||
use attr::HasAttrs;
|
use attr::HasAttrs;
|
||||||
use codemap::{self, CodeMap, ExpnInfo, Spanned, respan};
|
use codemap::{self, CodeMap, ExpnInfo, Spanned, respan};
|
||||||
use syntax_pos::{Span, ExpnId, NO_EXPANSION};
|
use syntax_pos::{Span, ExpnId, NO_EXPANSION};
|
||||||
use errors::DiagnosticBuilder;
|
use errors::{DiagnosticBuilder, FatalError};
|
||||||
use ext::expand::{self, Expansion};
|
use ext::expand::{self, Expansion};
|
||||||
use ext::hygiene::Mark;
|
use ext::hygiene::Mark;
|
||||||
use fold::{self, Folder};
|
use fold::{self, Folder};
|
||||||
@@ -674,9 +674,15 @@ impl<'a> ExtCtxt<'a> {
|
|||||||
|
|
||||||
pub fn bt_push(&mut self, ei: ExpnInfo) {
|
pub fn bt_push(&mut self, ei: ExpnInfo) {
|
||||||
if self.current_expansion.depth > self.ecfg.recursion_limit {
|
if self.current_expansion.depth > self.ecfg.recursion_limit {
|
||||||
self.span_fatal(ei.call_site,
|
let suggested_limit = self.ecfg.recursion_limit * 2;
|
||||||
|
let mut err = self.struct_span_fatal(ei.call_site,
|
||||||
&format!("recursion limit reached while expanding the macro `{}`",
|
&format!("recursion limit reached while expanding the macro `{}`",
|
||||||
ei.callee.name()));
|
ei.callee.name()));
|
||||||
|
err.note(&format!(
|
||||||
|
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
|
||||||
|
suggested_limit));
|
||||||
|
err.emit();
|
||||||
|
panic!(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut call_site = ei.call_site;
|
let mut call_site = ei.call_site;
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
#![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(usize) }
|
|
||||||
|
|
||||||
fn is_send<T:Send>() { }
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
is_send::<A>();
|
|
||||||
//~^ ERROR overflow evaluating
|
|
||||||
//~| NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
|
|
||||||
//~| NOTE required because it appears within the type `A`
|
|
||||||
//~| NOTE required because it appears within the type `B`
|
|
||||||
//~| NOTE required because it appears within the type `C`
|
|
||||||
//~| NOTE required because it appears within the type `D`
|
|
||||||
//~| NOTE required because it appears within the type `E`
|
|
||||||
//~| NOTE required because it appears within the type `F`
|
|
||||||
//~| NOTE required because it appears within the type `G`
|
|
||||||
//~| NOTE required because it appears within the type `H`
|
|
||||||
//~| NOTE required because it appears within the type `I`
|
|
||||||
//~| NOTE required because it appears within the type `J`
|
|
||||||
//~| NOTE required by `is_send`
|
|
||||||
}
|
|
||||||
45
src/test/ui/did_you_mean/recursion_limit.rs
Normal file
45
src/test/ui/did_you_mean/recursion_limit.rs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// 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 and that the compiler
|
||||||
|
// suggests a fix. In this case, we have deeply nested types that will
|
||||||
|
// fail the `Send` check by overflow when the recursion limit is set
|
||||||
|
// very low.
|
||||||
|
|
||||||
|
#![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(usize) }
|
||||||
|
|
||||||
|
fn is_send<T:Send>() { }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
is_send::<A>();
|
||||||
|
}
|
||||||
21
src/test/ui/did_you_mean/recursion_limit.stderr
Normal file
21
src/test/ui/did_you_mean/recursion_limit.stderr
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
error[E0275]: overflow evaluating the requirement `K: std::marker::Send`
|
||||||
|
--> $DIR/recursion_limit.rs:44:5
|
||||||
|
|
|
||||||
|
44 | is_send::<A>();
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: consider adding a `#![recursion_limit="20"]` attribute to your crate
|
||||||
|
= note: required because it appears within the type `J`
|
||||||
|
= note: required because it appears within the type `I`
|
||||||
|
= note: required because it appears within the type `H`
|
||||||
|
= note: required because it appears within the type `G`
|
||||||
|
= note: required because it appears within the type `F`
|
||||||
|
= note: required because it appears within the type `E`
|
||||||
|
= note: required because it appears within the type `D`
|
||||||
|
= note: required because it appears within the type `C`
|
||||||
|
= note: required because it appears within the type `B`
|
||||||
|
= note: required because it appears within the type `A`
|
||||||
|
= note: required by `is_send`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
62
src/test/ui/did_you_mean/recursion_limit_deref.rs
Normal file
62
src/test/ui/did_you_mean/recursion_limit_deref.rs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// Copyright 2017 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 and that the compiler
|
||||||
|
// suggests a fix. In this case, we have a long chain of Deref impls
|
||||||
|
// which will cause an overflow during the autoderef loop.
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![recursion_limit="10"]
|
||||||
|
|
||||||
|
macro_rules! link {
|
||||||
|
($outer:ident, $inner:ident) => {
|
||||||
|
struct $outer($inner);
|
||||||
|
|
||||||
|
impl $outer {
|
||||||
|
fn new() -> $outer {
|
||||||
|
$outer($inner::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Deref for $outer {
|
||||||
|
type Target = $inner;
|
||||||
|
|
||||||
|
fn deref(&self) -> &$inner {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bottom;
|
||||||
|
impl Bottom {
|
||||||
|
fn new() -> Bottom {
|
||||||
|
Bottom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
link!(Top, A);
|
||||||
|
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, Bottom);
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let t = Top::new();
|
||||||
|
let x: &Bottom = &t;
|
||||||
|
}
|
||||||
|
|
||||||
23
src/test/ui/did_you_mean/recursion_limit_deref.stderr
Normal file
23
src/test/ui/did_you_mean/recursion_limit_deref.stderr
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
error[E0055]: reached the recursion limit while auto-dereferencing I
|
||||||
|
--> $DIR/recursion_limit_deref.rs:60:22
|
||||||
|
|
|
||||||
|
60 | let x: &Bottom = &t;
|
||||||
|
| ^^ deref recursion limit reached
|
||||||
|
|
|
||||||
|
= help: consider adding a `#[recursion_limit="20"]` attribute to your crate
|
||||||
|
|
||||||
|
error[E0055]: reached the recursion limit while auto-dereferencing I
|
||||||
|
|
|
||||||
|
= help: consider adding a `#[recursion_limit="20"]` attribute to your crate
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/recursion_limit_deref.rs:60:22
|
||||||
|
|
|
||||||
|
60 | let x: &Bottom = &t;
|
||||||
|
| ^^ expected struct `Bottom`, found struct `Top`
|
||||||
|
|
|
||||||
|
= note: expected type `&Bottom`
|
||||||
|
found type `&Top`
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
26
src/test/ui/did_you_mean/recursion_limit_macro.rs
Normal file
26
src/test/ui/did_you_mean/recursion_limit_macro.rs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2017 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 and that the compiler
|
||||||
|
// suggests a fix. In this case, we have a recursing macro that will
|
||||||
|
// overflow if the number of arguments surpasses the recursion limit.
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![recursion_limit="10"]
|
||||||
|
|
||||||
|
macro_rules! recurse {
|
||||||
|
() => { };
|
||||||
|
($t:tt $($tail:tt)*) => { recurse!($($tail)*) };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9);
|
||||||
|
}
|
||||||
|
|
||||||
11
src/test/ui/did_you_mean/recursion_limit_macro.stderr
Normal file
11
src/test/ui/did_you_mean/recursion_limit_macro.stderr
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
error: recursion limit reached while expanding the macro `recurse`
|
||||||
|
--> $DIR/recursion_limit_macro.rs:20:31
|
||||||
|
|
|
||||||
|
20 | ($t:tt $($tail:tt)*) => { recurse!($($tail)*) };
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
24 | recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9);
|
||||||
|
| -------------------------------------------------- in this macro invocation
|
||||||
|
|
|
||||||
|
= note: consider adding a `#![recursion_limit="20"]` attribute to your crate
|
||||||
|
|
||||||
Reference in New Issue
Block a user