From c5968e8a4b22aa9bff2a8b1ace5f0991aa396bf2 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.stderr | 1 + src/test/ui/issues/issue-22638.stderr | 1 + .../issue-37311.stderr | 1 + src/test/ui/issues/issue-67552.stderr | 1 + src/test/ui/issues/issue-8727.stderr | 1 + ...-38591-non-regular-dropck-recursion.stderr | 1 + src/test/ui/recursion/recursion.stderr | 1 + src/test/ui/type_length_limit.stderr | 3 +- 9 files changed, 49 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 0dbb4b1015e79..a20094fd2c876 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 { @@ -418,27 +419,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>( @@ -463,15 +475,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(); } @@ -500,12 +513,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.stderr b/src/test/ui/infinite/infinite-instantiation.stderr index d27d14842ce99..29829179c22ed 100644 --- a/src/test/ui/infinite/infinite-instantiation.stderr +++ b/src/test/ui/infinite/infinite-instantiation.stderr @@ -9,6 +9,7 @@ note: `function` defined here | 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.stderr b/src/test/ui/issues/issue-22638.stderr index c4255b95b704e..11286011ec29a 100644 --- a/src/test/ui/issues/issue-22638.stderr +++ b/src/test/ui/issues/issue-22638.stderr @@ -9,6 +9,7 @@ note: `A::matches` defined here | 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.stderr b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr index a94f190d6b25d..22918835844e4 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 @@ -9,6 +9,7 @@ note: `::recurse` defined here | 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.stderr b/src/test/ui/issues/issue-67552.stderr index f3e73399b57ce..ac7635bd7f80c 100644 --- a/src/test/ui/issues/issue-67552.stderr +++ b/src/test/ui/issues/issue-67552.stderr @@ -11,6 +11,7 @@ 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.stderr b/src/test/ui/issues/issue-8727.stderr index 279e3ffbb4a41..82f6231d396ea 100644 --- a/src/test/ui/issues/issue-8727.stderr +++ b/src/test/ui/issues/issue-8727.stderr @@ -20,6 +20,7 @@ note: `generic` defined here | 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.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.stderr b/src/test/ui/recursion/recursion.stderr index 085bf82ef8b93..082e784f0c9be 100644 --- a/src/test/ui/recursion/recursion.stderr +++ b/src/test/ui/recursion/recursion.stderr @@ -9,6 +9,7 @@ note: `test` defined here | 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.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