about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-09-21 08:20:38 +0000
committerbors <bors@rust-lang.org>2020-09-21 08:20:38 +0000
commit0433fdf93b0346e136c03ed49c0e90346035f191 (patch)
tree7b4a9c6fc8b3e17d0cab3e2dc4e2aff81b5669ec
parenta409a233e02b1864d1b76495a1f946bb56c7aeb2 (diff)
parent34d3c7df80dc687e184d8bfa456e851cad9839de (diff)
downloadrust-0433fdf93b0346e136c03ed49c0e90346035f191.tar.gz
rust-0433fdf93b0346e136c03ed49c0e90346035f191.zip
Auto merge of #76843 - kornelski:longtypetofile, r=ecstatic-morse
Let user see the full type of type-length limit error

Seeing the full type of the error is sometimes essential to diagnosing the problem, but the type itself is too long to be displayed in the terminal in a useful fashion. This change solves this dilemma by writing the full offending type name to a file, and displays this filename as a note.

> note: the full type name been written to '$TEST_BUILD_DIR/issues/issue-22638/issue-22638.long-type.txt'

Closes #76777
-rw-r--r--compiler/rustc_mir/src/monomorphize/collector.rs66
-rw-r--r--src/test/ui/infinite/infinite-instantiation.rs1
-rw-r--r--src/test/ui/infinite/infinite-instantiation.stderr5
-rw-r--r--src/test/ui/issues/issue-22638.rs1
-rw-r--r--src/test/ui/issues/issue-22638.stderr5
-rw-r--r--src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs1
-rw-r--r--src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr5
-rw-r--r--src/test/ui/issues/issue-67552.rs1
-rw-r--r--src/test/ui/issues/issue-67552.stderr5
-rw-r--r--src/test/ui/issues/issue-8727.rs1
-rw-r--r--src/test/ui/issues/issue-8727.stderr7
-rw-r--r--src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs2
-rw-r--r--src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr1
-rw-r--r--src/test/ui/recursion/recursion.rs1
-rw-r--r--src/test/ui/recursion/recursion.stderr5
-rw-r--r--src/test/ui/type_length_limit.rs1
-rw-r--r--src/test/ui/type_length_limit.stderr3
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 4ef871b05f4..7e12cc9176e 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<PathBuf>) {
+    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 cb3550cf66b..9b9f332ca86 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<Self>;
diff --git a/src/test/ui/infinite/infinite-instantiation.stderr b/src/test/ui/infinite/infinite-instantiation.stderr
index d27d14842ce..52f5781349e 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::<Option<Option<Option<...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $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<T:ToOpt + Clone>(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 89137538425..198ceccc2c3 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 c4255b95b70..1354ec8e899 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<F: Fn()>(&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 d3d5863ddb3..50d1f166c98 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 a94f190d6b2..93aeb89469d 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: `<T as Foo>::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 b0fcb74764b..98192dae20d 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 f3e73399b57..cf05a72e921 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<T>(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 01b3bc582f7..a9b8126618f 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<T>() { //~ WARN function cannot return without recursing
     generic::<Option<T>>();
diff --git a/src/test/ui/issues/issue-8727.stderr b/src/test/ui/issues/issue-8727.stderr
index 279e3ffbb4a..10daba5ef3d 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<T>() {
    | ^^^^^^^^^^^^^^^ cannot return without recursing
@@ -10,16 +10,17 @@ LL |     generic::<Option<T>>();
    = help: a `loop` may express intention better if this is on purpose
 
 error: reached the recursion limit while instantiating `generic::<Option<Option<Option<O...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-8727.rs:7:5
+  --> $DIR/issue-8727.rs:8:5
    |
 LL |     generic::<Option<T>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `generic` defined here
-  --> $DIR/issue-8727.rs:6:1
+  --> $DIR/issue-8727.rs:7:1
    |
 LL | fn generic<T>() {
    | ^^^^^^^^^^^^^^^
+   = 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 d9996b80ac0..658def0ad5a 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: 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 4d77b3d295c..3efe13b3de3 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 373cc17d0e0..b3ba0ec3a2a 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<T> {head:isize, tail:T}
diff --git a/src/test/ui/recursion/recursion.stderr b/src/test/ui/recursion/recursion.stderr
index 085bf82ef8b..d2844d0e6d9 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::<Cons<Cons<Cons<Cons<Cons<...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $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<T:Dot> (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 921cded5037..c1f3acbecf9 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 cf3d64d734b..1c0a596a64c 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::<Optio
 LL | pub fn drop<T>(_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