Skip to content

Commit c5968e8

Browse files
committed
Let user see the full type of type-length limit error
1 parent 9f8ac71 commit c5968e8

File tree

9 files changed

+49
-27
lines changed

9 files changed

+49
-27
lines changed

compiler/rustc_mir/src/monomorphize/collector.rs

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ use rustc_session::config::EntryFnType;
197197
use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
198198
use smallvec::SmallVec;
199199
use std::iter;
200+
use std::path::PathBuf;
200201

201202
#[derive(PartialEq)]
202203
pub enum MonoItemCollectionMode {
@@ -418,27 +419,38 @@ fn record_accesses<'a, 'tcx: 'a>(
418419
inlining_map.lock_mut().record_accesses(caller, &accesses);
419420
}
420421

421-
// Shrinks string by keeping prefix and suffix of given sizes.
422-
fn shrink(s: String, before: usize, after: usize) -> String {
423-
// An iterator of all byte positions including the end of the string.
424-
let positions = || s.char_indices().map(|(i, _)| i).chain(iter::once(s.len()));
425-
426-
let shrunk = format!(
427-
"{before}...{after}",
428-
before = &s[..positions().nth(before).unwrap_or(s.len())],
429-
after = &s[positions().rev().nth(after).unwrap_or(0)..],
430-
);
422+
/// Format instance name that is already known to be too long for rustc.
423+
/// Show only the first and last 32 characters to avoid blasting
424+
/// the user's terminal with thousands of lines of type-name.
425+
///
426+
/// If the type name is longer than before+after, it will be written to a file.
427+
fn shrunk_instance_name(
428+
tcx: TyCtxt<'tcx>,
429+
instance: &Instance<'tcx>,
430+
before: usize,
431+
after: usize,
432+
) -> (String, Option<PathBuf>) {
433+
let s = instance.to_string();
431434

432435
// Only use the shrunk version if it's really shorter.
433436
// This also avoids the case where before and after slices overlap.
434-
if shrunk.len() < s.len() { shrunk } else { s }
435-
}
437+
if s.chars().nth(before + after + 1).is_some() {
438+
// An iterator of all byte positions including the end of the string.
439+
let positions = || s.char_indices().map(|(i, _)| i).chain(iter::once(s.len()));
440+
441+
let shrunk = format!(
442+
"{before}...{after}",
443+
before = &s[..positions().nth(before).unwrap_or(s.len())],
444+
after = &s[positions().rev().nth(after).unwrap_or(0)..],
445+
);
446+
447+
let path = tcx.output_filenames(LOCAL_CRATE).temp_path_ext("long-type.txt", None);
448+
let written_to_path = std::fs::write(&path, s).ok().map(|_| path);
436449

437-
// Format instance name that is already known to be too long for rustc.
438-
// Show only the first and last 32 characters to avoid blasting
439-
// the user's terminal with thousands of lines of type-name.
440-
fn shrunk_instance_name(instance: &Instance<'tcx>) -> String {
441-
shrink(instance.to_string(), 32, 32)
450+
(shrunk, written_to_path)
451+
} else {
452+
(s, None)
453+
}
442454
}
443455

444456
fn check_recursion_limit<'tcx>(
@@ -463,15 +475,16 @@ fn check_recursion_limit<'tcx>(
463475
// more than the recursion limit is assumed to be causing an
464476
// infinite expansion.
465477
if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) {
466-
let error = format!(
467-
"reached the recursion limit while instantiating `{}`",
468-
shrunk_instance_name(&instance),
469-
);
478+
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
479+
let error = format!("reached the recursion limit while instantiating `{}`", shrunk);
470480
let mut err = tcx.sess.struct_span_fatal(span, &error);
471481
err.span_note(
472482
tcx.def_span(def_id),
473483
&format!("`{}` defined here", tcx.def_path_str(def_id)),
474484
);
485+
if let Some(path) = written_to_path {
486+
err.note(&format!("the full type name has been written to '{}'", path.display()));
487+
}
475488
err.emit();
476489
FatalError.raise();
477490
}
@@ -500,12 +513,13 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
500513
//
501514
// Bail out in these cases to avoid that bad user experience.
502515
if !tcx.sess.type_length_limit().value_within_limit(type_length) {
503-
let msg = format!(
504-
"reached the type-length limit while instantiating `{}`",
505-
shrunk_instance_name(&instance),
506-
);
516+
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
517+
let msg = format!("reached the type-length limit while instantiating `{}`", shrunk);
507518
let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg);
508-
diag.note(&format!(
519+
if let Some(path) = written_to_path {
520+
diag.note(&format!("the full type name has been written to '{}'", path.display()));
521+
}
522+
diag.help(&format!(
509523
"consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate",
510524
type_length
511525
));

src/test/ui/infinite/infinite-instantiation.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ note: `function` defined here
99
|
1010
LL | fn function<T:ToOpt + Clone>(counter: usize, t: T) {
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
= note: the full type name has been written to '$TEST_BUILD_DIR/infinite/infinite-instantiation/infinite-instantiation.long-type.txt'
1213

1314
error: aborting due to previous error
1415

src/test/ui/issues/issue-22638.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ note: `A::matches` defined here
99
|
1010
LL | pub fn matches<F: Fn()>(&self, f: &F) {
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-22638/issue-22638.long-type.txt'
1213

1314
error: aborting due to previous error
1415

src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ note: `<T as Foo>::recurse` defined here
99
|
1010
LL | fn recurse(&self) {
1111
| ^^^^^^^^^^^^^^^^^
12+
= 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'
1213

1314
error: aborting due to previous error
1415

src/test/ui/issues/issue-67552.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ LL | / fn rec<T>(mut it: T)
1111
LL | | where
1212
LL | | T: Iterator,
1313
| |________________^
14+
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-67552/issue-67552.long-type.txt'
1415

1516
error: aborting due to previous error
1617

src/test/ui/issues/issue-8727.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ note: `generic` defined here
2020
|
2121
LL | fn generic<T>() {
2222
| ^^^^^^^^^^^^^^^
23+
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-8727/issue-8727.long-type.txt'
2324

2425
error: aborting due to previous error; 1 warning emitted
2526

src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ LL | | // SAFETY: see comment above
2121
LL | | unsafe { drop_in_place(to_drop) }
2222
LL | | }
2323
| |_^
24+
= 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'
2425

2526
error: aborting due to previous error
2627

src/test/ui/recursion/recursion.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ note: `test` defined here
99
|
1010
LL | fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
= note: the full type name has been written to '$TEST_BUILD_DIR/recursion/recursion/recursion.long-type.txt'
1213

1314
error: aborting due to previous error
1415

src/test/ui/type_length_limit.stderr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ error: reached the type-length limit while instantiating `std::mem::drop::<Optio
44
LL | pub fn drop<T>(_x: T) {}
55
| ^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: consider adding a `#![type_length_limit="8"]` attribute to your crate
7+
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
8+
= help: consider adding a `#![type_length_limit="8"]` attribute to your crate
89

910
error: aborting due to previous error
1011

0 commit comments

Comments
 (0)