From 34d3c7df80dc687e184d8bfa456e851cad9839de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kornel=20Lesi=C5=84ski?= Date: Wed, 16 Sep 2020 03:45:58 +0100 Subject: [PATCH] Let user see the full type of type-length limit error --- .../rustc_mir/src/monomorphize/collector.rs | 66 +++++++++++-------- .../ui/infinite/infinite-instantiation.rs | 1 + .../ui/infinite/infinite-instantiation.stderr | 5 +- src/test/ui/issues/issue-22638.rs | 1 + src/test/ui/issues/issue-22638.stderr | 5 +- .../issue-37311.rs | 1 + .../issue-37311.stderr | 5 +- src/test/ui/issues/issue-67552.rs | 1 + src/test/ui/issues/issue-67552.stderr | 5 +- src/test/ui/issues/issue-8727.rs | 1 + src/test/ui/issues/issue-8727.stderr | 7 +- ...ssue-38591-non-regular-dropck-recursion.rs | 2 + ...-38591-non-regular-dropck-recursion.stderr | 1 + src/test/ui/recursion/recursion.rs | 1 + src/test/ui/recursion/recursion.stderr | 5 +- src/test/ui/type_length_limit.rs | 1 + src/test/ui/type_length_limit.stderr | 3 +- 17 files changed, 71 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 4ef871b05f47f..7e12cc9176ee1 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -197,6 +197,7 @@ use rustc_session::config::EntryFnType; use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP}; use smallvec::SmallVec; use std::iter; +use std::path::PathBuf; #[derive(PartialEq)] pub enum MonoItemCollectionMode { @@ -420,27 +421,38 @@ fn record_accesses<'a, 'tcx: 'a>( inlining_map.lock_mut().record_accesses(caller, &accesses); } -// Shrinks string by keeping prefix and suffix of given sizes. -fn shrink(s: String, before: usize, after: usize) -> String { - // An iterator of all byte positions including the end of the string. - let positions = || s.char_indices().map(|(i, _)| i).chain(iter::once(s.len())); - - let shrunk = format!( - "{before}...{after}", - before = &s[..positions().nth(before).unwrap_or(s.len())], - after = &s[positions().rev().nth(after).unwrap_or(0)..], - ); +/// Format instance name that is already known to be too long for rustc. +/// Show only the first and last 32 characters to avoid blasting +/// the user's terminal with thousands of lines of type-name. +/// +/// If the type name is longer than before+after, it will be written to a file. +fn shrunk_instance_name( + tcx: TyCtxt<'tcx>, + instance: &Instance<'tcx>, + before: usize, + after: usize, +) -> (String, Option) { + let s = instance.to_string(); // Only use the shrunk version if it's really shorter. // This also avoids the case where before and after slices overlap. - if shrunk.len() < s.len() { shrunk } else { s } -} + if s.chars().nth(before + after + 1).is_some() { + // An iterator of all byte positions including the end of the string. + let positions = || s.char_indices().map(|(i, _)| i).chain(iter::once(s.len())); + + let shrunk = format!( + "{before}...{after}", + before = &s[..positions().nth(before).unwrap_or(s.len())], + after = &s[positions().rev().nth(after).unwrap_or(0)..], + ); + + let path = tcx.output_filenames(LOCAL_CRATE).temp_path_ext("long-type.txt", None); + let written_to_path = std::fs::write(&path, s).ok().map(|_| path); -// Format instance name that is already known to be too long for rustc. -// Show only the first and last 32 characters to avoid blasting -// the user's terminal with thousands of lines of type-name. -fn shrunk_instance_name(instance: &Instance<'tcx>) -> String { - shrink(instance.to_string(), 32, 32) + (shrunk, written_to_path) + } else { + (s, None) + } } fn check_recursion_limit<'tcx>( @@ -465,15 +477,16 @@ fn check_recursion_limit<'tcx>( // more than the recursion limit is assumed to be causing an // infinite expansion. if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) { - let error = format!( - "reached the recursion limit while instantiating `{}`", - shrunk_instance_name(&instance), - ); + let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32); + let error = format!("reached the recursion limit while instantiating `{}`", shrunk); let mut err = tcx.sess.struct_span_fatal(span, &error); err.span_note( tcx.def_span(def_id), &format!("`{}` defined here", tcx.def_path_str(def_id)), ); + if let Some(path) = written_to_path { + err.note(&format!("the full type name has been written to '{}'", path.display())); + } err.emit(); FatalError.raise(); } @@ -502,12 +515,13 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { // // Bail out in these cases to avoid that bad user experience. if !tcx.sess.type_length_limit().value_within_limit(type_length) { - let msg = format!( - "reached the type-length limit while instantiating `{}`", - shrunk_instance_name(&instance), - ); + let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32); + let msg = format!("reached the type-length limit while instantiating `{}`", shrunk); let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg); - diag.note(&format!( + if let Some(path) = written_to_path { + diag.note(&format!("the full type name has been written to '{}'", path.display())); + } + diag.help(&format!( "consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate", type_length )); diff --git a/src/test/ui/infinite/infinite-instantiation.rs b/src/test/ui/infinite/infinite-instantiation.rs index cb3550cf66bed..9b9f332ca86de 100644 --- a/src/test/ui/infinite/infinite-instantiation.rs +++ b/src/test/ui/infinite/infinite-instantiation.rs @@ -1,4 +1,5 @@ // build-fail +// normalize-stderr-test: ".nll/" -> "/" trait ToOpt: Sized { fn to_option(&self) -> Option; diff --git a/src/test/ui/infinite/infinite-instantiation.stderr b/src/test/ui/infinite/infinite-instantiation.stderr index d27d14842ce99..52f5781349e16 100644 --- a/src/test/ui/infinite/infinite-instantiation.stderr +++ b/src/test/ui/infinite/infinite-instantiation.stderr @@ -1,14 +1,15 @@ error: reached the recursion limit while instantiating `function::>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/infinite-instantiation.rs:21:9 + --> $DIR/infinite-instantiation.rs:22:9 | LL | function(counter - 1, t.to_option()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `function` defined here - --> $DIR/infinite-instantiation.rs:19:1 + --> $DIR/infinite-instantiation.rs:20:1 | LL | fn function(counter: usize, t: T) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/infinite/infinite-instantiation/infinite-instantiation.long-type.txt' error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22638.rs b/src/test/ui/issues/issue-22638.rs index 89137538425bf..198ceccc2c33c 100644 --- a/src/test/ui/issues/issue-22638.rs +++ b/src/test/ui/issues/issue-22638.rs @@ -1,5 +1,6 @@ // build-fail // normalize-stderr-test: "<\[closure@.+`" -> "$$CLOSURE`" +// normalize-stderr-test: ".nll/" -> "/" #![allow(unused)] diff --git a/src/test/ui/issues/issue-22638.stderr b/src/test/ui/issues/issue-22638.stderr index c4255b95b704e..1354ec8e899c0 100644 --- a/src/test/ui/issues/issue-22638.stderr +++ b/src/test/ui/issues/issue-22638.stderr @@ -1,14 +1,15 @@ error: reached the recursion limit while instantiating `A::matches::$CLOSURE` - --> $DIR/issue-22638.rs:55:9 + --> $DIR/issue-22638.rs:56:9 | LL | a.matches(f) | ^^^^^^^^^^^^ | note: `A::matches` defined here - --> $DIR/issue-22638.rs:14:5 + --> $DIR/issue-22638.rs:15:5 | LL | pub fn matches(&self, f: &F) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-22638/issue-22638.long-type.txt' error: aborting due to previous error diff --git a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs index d3d5863ddb3c9..50d1f166c9865 100644 --- a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs +++ b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs @@ -1,4 +1,5 @@ // build-fail +// normalize-stderr-test: ".nll/" -> "/" trait Mirror { type Image; diff --git a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr index a94f190d6b25d..93aeb89469d4a 100644 --- a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr +++ b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr @@ -1,14 +1,15 @@ error: reached the recursion limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(.....), ...), ...) as Foo>::recurse` - --> $DIR/issue-37311.rs:16:9 + --> $DIR/issue-37311.rs:17:9 | LL | (self, self).recurse(); | ^^^^^^^^^^^^^^^^^^^^^^ | note: `::recurse` defined here - --> $DIR/issue-37311.rs:15:5 + --> $DIR/issue-37311.rs:16:5 | LL | fn recurse(&self) { | ^^^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-37311-type-length-limit/issue-37311/issue-37311.long-type.txt' error: aborting due to previous error diff --git a/src/test/ui/issues/issue-67552.rs b/src/test/ui/issues/issue-67552.rs index b0fcb74764b98..98192dae20da8 100644 --- a/src/test/ui/issues/issue-67552.rs +++ b/src/test/ui/issues/issue-67552.rs @@ -1,4 +1,5 @@ // build-fail +// normalize-stderr-test: ".nll/" -> "/" fn main() { rec(Empty); diff --git a/src/test/ui/issues/issue-67552.stderr b/src/test/ui/issues/issue-67552.stderr index f3e73399b57ce..cf05a72e921e0 100644 --- a/src/test/ui/issues/issue-67552.stderr +++ b/src/test/ui/issues/issue-67552.stderr @@ -1,16 +1,17 @@ error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut &... &mut &mut &mut &mut &mut Empty>` - --> $DIR/issue-67552.rs:27:9 + --> $DIR/issue-67552.rs:28:9 | LL | rec(identity(&mut it)) | ^^^^^^^^^^^^^^^^^^^^^^ | note: `rec` defined here - --> $DIR/issue-67552.rs:20:1 + --> $DIR/issue-67552.rs:21:1 | LL | / fn rec(mut it: T) LL | | where LL | | T: Iterator, | |________________^ + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-67552/issue-67552.long-type.txt' error: aborting due to previous error diff --git a/src/test/ui/issues/issue-8727.rs b/src/test/ui/issues/issue-8727.rs index 01b3bc582f7e0..a9b8126618fe5 100644 --- a/src/test/ui/issues/issue-8727.rs +++ b/src/test/ui/issues/issue-8727.rs @@ -2,6 +2,7 @@ // recursions. // build-fail +// normalize-stderr-test: ".nll/" -> "/" fn generic() { //~ WARN function cannot return without recursing generic::>(); diff --git a/src/test/ui/issues/issue-8727.stderr b/src/test/ui/issues/issue-8727.stderr index 279e3ffbb4a41..10daba5ef3dd5 100644 --- a/src/test/ui/issues/issue-8727.stderr +++ b/src/test/ui/issues/issue-8727.stderr @@ -1,5 +1,5 @@ warning: function cannot return without recursing - --> $DIR/issue-8727.rs:6:1 + --> $DIR/issue-8727.rs:7:1 | LL | fn generic() { | ^^^^^^^^^^^^^^^ cannot return without recursing @@ -10,16 +10,17 @@ LL | generic::>(); = help: a `loop` may express intention better if this is on purpose error: reached the recursion limit while instantiating `generic::>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-8727.rs:7:5 + --> $DIR/issue-8727.rs:8:5 | LL | generic::>(); | ^^^^^^^^^^^^^^^^^^^^^^ | note: `generic` defined here - --> $DIR/issue-8727.rs:6:1 + --> $DIR/issue-8727.rs:7:1 | LL | fn generic() { | ^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-8727/issue-8727.long-type.txt' error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs index d9996b80ac09d..658def0ad5a72 100644 --- a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs +++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs @@ -2,7 +2,9 @@ // no free regions or type parameters. // Codegen however, has to error for the infinitely many `drop_in_place` // functions it has been asked to create. + // build-fail +// normalize-stderr-test: ".nll/" -> "/" struct S { t: T, diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr index 4d77b3d295c00..3efe13b3de3d0 100644 --- a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr +++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr @@ -21,6 +21,7 @@ LL | | // SAFETY: see comment above LL | | unsafe { drop_in_place(to_drop) } LL | | } | |_^ + = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-38591-non-regular-dropck-recursion/issue-38591-non-regular-dropck-recursion.long-type.txt' error: aborting due to previous error diff --git a/src/test/ui/recursion/recursion.rs b/src/test/ui/recursion/recursion.rs index 373cc17d0e0fe..b3ba0ec3a2a01 100644 --- a/src/test/ui/recursion/recursion.rs +++ b/src/test/ui/recursion/recursion.rs @@ -1,5 +1,6 @@ // build-fail // compile-flags:-C overflow-checks=off +// normalize-stderr-test: ".nll/" -> "/" enum Nil {NilValue} struct Cons {head:isize, tail:T} diff --git a/src/test/ui/recursion/recursion.stderr b/src/test/ui/recursion/recursion.stderr index 085bf82ef8b93..d2844d0e6d9f0 100644 --- a/src/test/ui/recursion/recursion.stderr +++ b/src/test/ui/recursion/recursion.stderr @@ -1,14 +1,15 @@ error: reached the recursion limit while instantiating `test::>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/recursion.rs:17:11 + --> $DIR/recursion.rs:18:11 | LL | _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `test` defined here - --> $DIR/recursion.rs:15:1 + --> $DIR/recursion.rs:16:1 | LL | fn test (n:isize, i:isize, first:T, second:T) ->isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/recursion/recursion.long-type.txt' error: aborting due to previous error diff --git a/src/test/ui/type_length_limit.rs b/src/test/ui/type_length_limit.rs index 921cded5037b6..c1f3acbecf95f 100644 --- a/src/test/ui/type_length_limit.rs +++ b/src/test/ui/type_length_limit.rs @@ -1,5 +1,6 @@ // build-fail // error-pattern: reached the type-length limit while instantiating +// normalize-stderr-test: ".nll/" -> "/" // Test that the type length limit can be changed. diff --git a/src/test/ui/type_length_limit.stderr b/src/test/ui/type_length_limit.stderr index cf3d64d734ba0..1c0a596a64cb9 100644 --- a/src/test/ui/type_length_limit.stderr +++ b/src/test/ui/type_length_limit.stderr @@ -4,7 +4,8 @@ error: reached the type-length limit while instantiating `std::mem::drop::(_x: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: consider adding a `#![type_length_limit="8"]` attribute to your crate + = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt' + = help: consider adding a `#![type_length_limit="8"]` attribute to your crate error: aborting due to previous error