]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #76843 - kornelski:longtypetofile, r=ecstatic-morse
authorbors <bors@rust-lang.org>
Mon, 21 Sep 2020 08:20:38 +0000 (08:20 +0000)
committerbors <bors@rust-lang.org>
Mon, 21 Sep 2020 08:20:38 +0000 (08:20 +0000)
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

17 files changed:
compiler/rustc_mir/src/monomorphize/collector.rs
src/test/ui/infinite/infinite-instantiation.rs
src/test/ui/infinite/infinite-instantiation.stderr
src/test/ui/issues/issue-22638.rs
src/test/ui/issues/issue-22638.stderr
src/test/ui/issues/issue-37311-type-length-limit/issue-37311.rs
src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr
src/test/ui/issues/issue-67552.rs
src/test/ui/issues/issue-67552.stderr
src/test/ui/issues/issue-8727.rs
src/test/ui/issues/issue-8727.stderr
src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
src/test/ui/recursion/recursion.rs
src/test/ui/recursion/recursion.stderr
src/test/ui/type_length_limit.rs
src/test/ui/type_length_limit.stderr

index 4ef871b05f47f3375916fd58c7717ef789a30feb..7e12cc9176ee169844b12e46d0abf2e7a2823761 100644 (file)
 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
         ));
index cb3550cf66bed289f121baa731d813be1c5c6024..9b9f332ca86deb92c4b31a088da5f815a6075769 100644 (file)
@@ -1,4 +1,5 @@
 // build-fail
+// normalize-stderr-test: ".nll/" -> "/"
 
 trait ToOpt: Sized {
     fn to_option(&self) -> Option<Self>;
index d27d14842ce99f1f61c6cdc35a6f515722c9d3a3..52f5781349e1650996fae4ffb94bd0ac8df21ff9 100644 (file)
@@ -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
 
index 89137538425bfbdb948e30b78ccc7572e366aee5..198ceccc2c33cd95cc9f884e60afac413a8465e2 100644 (file)
@@ -1,5 +1,6 @@
 // build-fail
 // normalize-stderr-test: "<\[closure@.+`" -> "$$CLOSURE`"
+// normalize-stderr-test: ".nll/" -> "/"
 
 #![allow(unused)]
 
index c4255b95b704e4016bc4dc93f6a4e3356e82077a..1354ec8e899c09c09f17f68c9c42e4062cd37471 100644 (file)
@@ -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
 
index d3d5863ddb3c9b6d1c757b7bb4f64c12889f7451..50d1f166c98650a09b562e5c47b0e3975dfc3406 100644 (file)
@@ -1,4 +1,5 @@
 // build-fail
+// normalize-stderr-test: ".nll/" -> "/"
 
 trait Mirror {
     type Image;
index a94f190d6b25d2f566c5ec45b37ceba07946b5d4..93aeb89469d4a3dbe9702dca34d3e66ce03a31a0 100644 (file)
@@ -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
 
index b0fcb74764b987b8e3f2fe1160cf4d1d2ee48a9e..98192dae20da878fe90dfe2e086a1aae324f37b6 100644 (file)
@@ -1,4 +1,5 @@
 // build-fail
+// normalize-stderr-test: ".nll/" -> "/"
 
 fn main() {
     rec(Empty);
index f3e73399b57ce7445ca61bdfca2f7f52239e4874..cf05a72e921e01c987f23b19c0ba494f05ca1181 100644 (file)
@@ -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
 
index 01b3bc582f7e04f50e3287a35137de28c00d2e4b..a9b8126618fe5e4d504d31307823686d75b9b1a6 100644 (file)
@@ -2,6 +2,7 @@
 // recursions.
 
 // build-fail
+// normalize-stderr-test: ".nll/" -> "/"
 
 fn generic<T>() { //~ WARN function cannot return without recursing
     generic::<Option<T>>();
index 279e3ffbb4a41772ea53b7171172aa490fa3666a..10daba5ef3dd5d2475d1eaada272aa2997619f3a 100644 (file)
@@ -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
 
index d9996b80ac09d172f96a6c40e91793f7683a1d4a..658def0ad5a72d7515efdfa65ae9606db7481cfd 100644 (file)
@@ -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,
index 4d77b3d295c00bc203843fe98a6ecf64d669367b..3efe13b3de3d0f9e93aa411111f9b7a8eef7e59e 100644 (file)
@@ -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
 
index 373cc17d0e0fe1c05ceccc17740f8e3733a13d9a..b3ba0ec3a2a01e9680f5aa5f622af6368f05808f 100644 (file)
@@ -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}
index 085bf82ef8b9351773b4bafd488a96476dcfb256..d2844d0e6d9f026f04fb6c10a7d35fc6f98721ec 100644 (file)
@@ -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
 
index 921cded5037b67c3dcec87b9e8ababb67014e488..c1f3acbecf95fab10c3f676cb6b4ce4e9e8f355a 100644 (file)
@@ -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.
 
index cf3d64d734ba0de7c28f986d1f75e1087e45dd4c..1c0a596a64cb9fa04828a34b5a57fa7d22c62b20 100644 (file)
@@ -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