Let user see the full type of type-length limit error
This commit is contained in:
parent
1fd5b9d516
commit
34d3c7df80
@ -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()));
|
||||
|
||||
// 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)
|
||||
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);
|
||||
|
||||
(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
|
||||
));
|
||||
|
@ -1,4 +1,5 @@
|
||||
// build-fail
|
||||
// normalize-stderr-test: ".nll/" -> "/"
|
||||
|
||||
trait ToOpt: Sized {
|
||||
fn to_option(&self) -> Option<Self>;
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
// build-fail
|
||||
// normalize-stderr-test: "<\[closure@.+`" -> "$$CLOSURE`"
|
||||
// normalize-stderr-test: ".nll/" -> "/"
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// build-fail
|
||||
// normalize-stderr-test: ".nll/" -> "/"
|
||||
|
||||
trait Mirror {
|
||||
type Image;
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// build-fail
|
||||
// normalize-stderr-test: ".nll/" -> "/"
|
||||
|
||||
fn main() {
|
||||
rec(Empty);
|
||||
|
@ -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
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
// recursions.
|
||||
|
||||
// build-fail
|
||||
// normalize-stderr-test: ".nll/" -> "/"
|
||||
|
||||
fn generic<T>() { //~ WARN function cannot return without recursing
|
||||
generic::<Option<T>>();
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user