From b4993ec8635a48d4467a69482f77c6370a9709df Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Thu, 5 Jan 2017 23:17:12 +0000 Subject: [PATCH 1/2] suggest doubling recursion limit in more situations --- src/librustc_typeck/check/autoderef.rs | 4 ++ src/libsyntax/ext/base.rs | 14 +++-- src/test/compile-fail/recursion_limit.rs | 57 ----------------- src/test/ui/did_you_mean/recursion_limit.rs | 45 ++++++++++++++ .../ui/did_you_mean/recursion_limit.stderr | 21 +++++++ .../ui/did_you_mean/recursion_limit_deref.rs | 62 +++++++++++++++++++ .../did_you_mean/recursion_limit_deref.stderr | 23 +++++++ .../ui/did_you_mean/recursion_limit_macro.rs | 26 ++++++++ .../did_you_mean/recursion_limit_macro.stderr | 11 ++++ 9 files changed, 202 insertions(+), 61 deletions(-) delete mode 100644 src/test/compile-fail/recursion_limit.rs create mode 100644 src/test/ui/did_you_mean/recursion_limit.rs create mode 100644 src/test/ui/did_you_mean/recursion_limit.stderr create mode 100644 src/test/ui/did_you_mean/recursion_limit_deref.rs create mode 100644 src/test/ui/did_you_mean/recursion_limit_deref.stderr create mode 100644 src/test/ui/did_you_mean/recursion_limit_macro.rs create mode 100644 src/test/ui/did_you_mean/recursion_limit_macro.stderr diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index b4647df3f4f..ca0ab8f1e8c 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -54,12 +54,16 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> { if self.steps.len() == tcx.sess.recursion_limit.get() { // We've reached the recursion limit, error gracefully. + let suggested_limit = tcx.sess.recursion_limit.get() * 2; struct_span_err!(tcx.sess, self.span, E0055, "reached the recursion limit while auto-dereferencing {:?}", self.cur_ty) .span_label(self.span, &format!("deref recursion limit reached")) + .help(&format!( + "consider adding a `#[recursion_limit=\"{}\"]` attribute to your crate", + suggested_limit)) .emit(); return None; } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 9a717b86d09..e7f794328b8 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -14,7 +14,7 @@ use ast::{self, Attribute, Name, PatKind, MetaItem}; use attr::HasAttrs; use codemap::{self, CodeMap, ExpnInfo, Spanned, respan}; use syntax_pos::{Span, ExpnId, NO_EXPANSION}; -use errors::DiagnosticBuilder; +use errors::{DiagnosticBuilder, FatalError}; use ext::expand::{self, Expansion}; use ext::hygiene::Mark; use fold::{self, Folder}; @@ -674,9 +674,15 @@ impl<'a> ExtCtxt<'a> { pub fn bt_push(&mut self, ei: ExpnInfo) { if self.current_expansion.depth > self.ecfg.recursion_limit { - self.span_fatal(ei.call_site, - &format!("recursion limit reached while expanding the macro `{}`", - ei.callee.name())); + 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 `{}`", + 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; diff --git a/src/test/compile-fail/recursion_limit.rs b/src/test/compile-fail/recursion_limit.rs deleted file mode 100644 index 226a6d57ddb..00000000000 --- a/src/test/compile-fail/recursion_limit.rs +++ /dev/null @@ -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 or the MIT license -// , 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() { } - -fn main() { - is_send::(); - //~^ 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` -} diff --git a/src/test/ui/did_you_mean/recursion_limit.rs b/src/test/ui/did_you_mean/recursion_limit.rs new file mode 100644 index 00000000000..becb81b1fff --- /dev/null +++ b/src/test/ui/did_you_mean/recursion_limit.rs @@ -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 or the MIT license +// , 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() { } + +fn main() { + is_send::(); +} diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr new file mode 100644 index 00000000000..524aab87ccf --- /dev/null +++ b/src/test/ui/did_you_mean/recursion_limit.stderr @@ -0,0 +1,21 @@ +error[E0275]: overflow evaluating the requirement `K: std::marker::Send` + --> $DIR/recursion_limit.rs:44:5 + | +44 | is_send::(); + | ^^^^^^^^^^^^ + | + = 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 + diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.rs b/src/test/ui/did_you_mean/recursion_limit_deref.rs new file mode 100644 index 00000000000..ebc56c94adf --- /dev/null +++ b/src/test/ui/did_you_mean/recursion_limit_deref.rs @@ -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 or the MIT license +// , 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; +} + diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr new file mode 100644 index 00000000000..57b28d03736 --- /dev/null +++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr @@ -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 + diff --git a/src/test/ui/did_you_mean/recursion_limit_macro.rs b/src/test/ui/did_you_mean/recursion_limit_macro.rs new file mode 100644 index 00000000000..9fb82b730c9 --- /dev/null +++ b/src/test/ui/did_you_mean/recursion_limit_macro.rs @@ -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 or the MIT license +// , 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); +} + diff --git a/src/test/ui/did_you_mean/recursion_limit_macro.stderr b/src/test/ui/did_you_mean/recursion_limit_macro.stderr new file mode 100644 index 00000000000..6bed78a3bad --- /dev/null +++ b/src/test/ui/did_you_mean/recursion_limit_macro.stderr @@ -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 + From 6e259dc77870d278a37bbc42bcbc5fad64b75930 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Tue, 28 Feb 2017 18:18:54 +0000 Subject: [PATCH 2/2] note -> help --- src/librustc/traits/error_reporting.rs | 2 +- src/libsyntax/ext/base.rs | 2 +- src/test/ui/did_you_mean/recursion_limit.stderr | 2 +- src/test/ui/did_you_mean/recursion_limit_macro.stderr | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 661d47199df..6ba593da51e 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -995,7 +995,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) { let current_limit = self.tcx.sess.recursion_limit.get(); let suggested_limit = current_limit * 2; - err.note(&format!( + err.help(&format!( "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", suggested_limit)); } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index e7f794328b8..7085d0440d3 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -678,7 +678,7 @@ impl<'a> ExtCtxt<'a> { let mut err = self.struct_span_fatal(ei.call_site, &format!("recursion limit reached while expanding the macro `{}`", ei.callee.name())); - err.note(&format!( + err.help(&format!( "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", suggested_limit)); err.emit(); diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr index 524aab87ccf..d157c5de6c7 100644 --- a/src/test/ui/did_you_mean/recursion_limit.stderr +++ b/src/test/ui/did_you_mean/recursion_limit.stderr @@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `K: std::marker::Send` 44 | is_send::(); | ^^^^^^^^^^^^ | - = note: consider adding a `#![recursion_limit="20"]` attribute to your crate + = help: 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` diff --git a/src/test/ui/did_you_mean/recursion_limit_macro.stderr b/src/test/ui/did_you_mean/recursion_limit_macro.stderr index 6bed78a3bad..19aac1f77e7 100644 --- a/src/test/ui/did_you_mean/recursion_limit_macro.stderr +++ b/src/test/ui/did_you_mean/recursion_limit_macro.stderr @@ -7,5 +7,5 @@ error: recursion limit reached while expanding the macro `recurse` 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 + = help: consider adding a `#![recursion_limit="20"]` attribute to your crate