mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Make "long type" printing type aware
Instead of simple string cutting, use a custom printer to hide parts of long printed types.
This commit is contained in:
parent
fd3bfb3551
commit
d49c10ac62
@ -276,17 +276,21 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Display for Instance<'tcx> {
|
fn fmt_instance(
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
f: &mut fmt::Formatter<'_>,
|
||||||
|
instance: &Instance<'_>,
|
||||||
|
type_length: rustc_session::Limit,
|
||||||
|
) -> fmt::Result {
|
||||||
ty::tls::with(|tcx| {
|
ty::tls::with(|tcx| {
|
||||||
let substs = tcx.lift(self.substs).expect("could not lift for printing");
|
let substs = tcx.lift(instance.substs).expect("could not lift for printing");
|
||||||
let s = FmtPrinter::new(tcx, Namespace::ValueNS)
|
|
||||||
.print_def_path(self.def_id(), substs)?
|
let s = FmtPrinter::new_with_limit(tcx, Namespace::ValueNS, type_length)
|
||||||
|
.print_def_path(instance.def_id(), substs)?
|
||||||
.into_buffer();
|
.into_buffer();
|
||||||
f.write_str(&s)
|
f.write_str(&s)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
match self.def {
|
match instance.def {
|
||||||
InstanceDef::Item(_) => Ok(()),
|
InstanceDef::Item(_) => Ok(()),
|
||||||
InstanceDef::VTableShim(_) => write!(f, " - shim(vtable)"),
|
InstanceDef::VTableShim(_) => write!(f, " - shim(vtable)"),
|
||||||
InstanceDef::ReifyShim(_) => write!(f, " - shim(reify)"),
|
InstanceDef::ReifyShim(_) => write!(f, " - shim(reify)"),
|
||||||
@ -299,6 +303,19 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
|
|||||||
InstanceDef::CloneShim(_, ty) => write!(f, " - shim({})", ty),
|
InstanceDef::CloneShim(_, ty) => write!(f, " - shim({})", ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ShortInstance<'a, 'tcx>(pub &'a Instance<'tcx>, pub usize);
|
||||||
|
|
||||||
|
impl<'a, 'tcx> fmt::Display for ShortInstance<'a, 'tcx> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt_instance(f, self.0, rustc_session::Limit(self.1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> fmt::Display for Instance<'tcx> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
ty::tls::with(|tcx| fmt_instance(f, self, tcx.type_length_limit()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Instance<'tcx> {
|
impl<'tcx> Instance<'tcx> {
|
||||||
|
@ -84,7 +84,7 @@ pub use self::context::{
|
|||||||
GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType,
|
GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType,
|
||||||
UserTypeAnnotationIndex,
|
UserTypeAnnotationIndex,
|
||||||
};
|
};
|
||||||
pub use self::instance::{Instance, InstanceDef};
|
pub use self::instance::{Instance, InstanceDef, ShortInstance};
|
||||||
pub use self::list::List;
|
pub use self::list::List;
|
||||||
pub use self::parameterized::ParameterizedOverTcx;
|
pub use self::parameterized::ParameterizedOverTcx;
|
||||||
pub use self::rvalue_scopes::RvalueScopes;
|
pub use self::rvalue_scopes::RvalueScopes;
|
||||||
|
@ -13,6 +13,7 @@ use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_ID, LOCAL_CRATE};
|
|||||||
use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
|
use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
|
||||||
use rustc_session::config::TrimmedDefPaths;
|
use rustc_session::config::TrimmedDefPaths;
|
||||||
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
|
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
|
||||||
|
use rustc_session::Limit;
|
||||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||||
use rustc_target::abi::Size;
|
use rustc_target::abi::Size;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
@ -1583,6 +1584,8 @@ pub struct FmtPrinterData<'a, 'tcx> {
|
|||||||
region_index: usize,
|
region_index: usize,
|
||||||
binder_depth: usize,
|
binder_depth: usize,
|
||||||
printed_type_count: usize,
|
printed_type_count: usize,
|
||||||
|
type_length_limit: Limit,
|
||||||
|
truncated: bool,
|
||||||
|
|
||||||
pub region_highlight_mode: RegionHighlightMode<'tcx>,
|
pub region_highlight_mode: RegionHighlightMode<'tcx>,
|
||||||
|
|
||||||
@ -1605,6 +1608,10 @@ impl DerefMut for FmtPrinter<'_, '_> {
|
|||||||
|
|
||||||
impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
|
impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
|
||||||
pub fn new(tcx: TyCtxt<'tcx>, ns: Namespace) -> Self {
|
pub fn new(tcx: TyCtxt<'tcx>, ns: Namespace) -> Self {
|
||||||
|
Self::new_with_limit(tcx, ns, tcx.type_length_limit())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_with_limit(tcx: TyCtxt<'tcx>, ns: Namespace, type_length_limit: Limit) -> Self {
|
||||||
FmtPrinter(Box::new(FmtPrinterData {
|
FmtPrinter(Box::new(FmtPrinterData {
|
||||||
tcx,
|
tcx,
|
||||||
// Estimated reasonable capacity to allocate upfront based on a few
|
// Estimated reasonable capacity to allocate upfront based on a few
|
||||||
@ -1617,6 +1624,8 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
|
|||||||
region_index: 0,
|
region_index: 0,
|
||||||
binder_depth: 0,
|
binder_depth: 0,
|
||||||
printed_type_count: 0,
|
printed_type_count: 0,
|
||||||
|
type_length_limit,
|
||||||
|
truncated: false,
|
||||||
region_highlight_mode: RegionHighlightMode::new(tcx),
|
region_highlight_mode: RegionHighlightMode::new(tcx),
|
||||||
ty_infer_name_resolver: None,
|
ty_infer_name_resolver: None,
|
||||||
const_infer_name_resolver: None,
|
const_infer_name_resolver: None,
|
||||||
@ -1751,12 +1760,16 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
|
fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
|
||||||
let type_length_limit = self.tcx.type_length_limit();
|
if self.type_length_limit.value_within_limit(self.printed_type_count) {
|
||||||
if type_length_limit.value_within_limit(self.printed_type_count) {
|
|
||||||
self.printed_type_count += 1;
|
self.printed_type_count += 1;
|
||||||
self.pretty_print_type(ty)
|
self.pretty_print_type(ty)
|
||||||
} else {
|
} else {
|
||||||
|
self.truncated = true;
|
||||||
|
if let ty::Adt(_, substs) = ty.kind() && substs.len() > 0 {
|
||||||
write!(self, "...")?;
|
write!(self, "...")?;
|
||||||
|
} else {
|
||||||
|
write!(self, "_")?;
|
||||||
|
}
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,6 @@ use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
|
|||||||
use rustc_session::Limit;
|
use rustc_session::Limit;
|
||||||
use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
|
use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
|
||||||
use rustc_target::abi::Size;
|
use rustc_target::abi::Size;
|
||||||
use std::iter;
|
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
@ -541,29 +540,23 @@ fn collect_items_rec<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Format instance name that is already known to be too long for rustc.
|
/// Format instance name that is already known to be too long for rustc.
|
||||||
/// Show only the first and last 32 characters to avoid blasting
|
/// Show only the first 2 types if it is longer than 32 characters to avoid blasting
|
||||||
/// the user's terminal with thousands of lines of type-name.
|
/// 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.
|
/// If the type name is longer than before+after, it will be written to a file.
|
||||||
fn shrunk_instance_name<'tcx>(
|
fn shrunk_instance_name<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
instance: &Instance<'tcx>,
|
instance: &Instance<'tcx>,
|
||||||
before: usize,
|
|
||||||
after: usize,
|
|
||||||
) -> (String, Option<PathBuf>) {
|
) -> (String, Option<PathBuf>) {
|
||||||
let s = instance.to_string();
|
let s = instance.to_string();
|
||||||
|
|
||||||
// Only use the shrunk version if it's really shorter.
|
// Only use the shrunk version if it's really shorter.
|
||||||
// This also avoids the case where before and after slices overlap.
|
// This also avoids the case where before and after slices overlap.
|
||||||
if s.chars().nth(before + after + 1).is_some() {
|
if s.chars().nth(33).is_some() {
|
||||||
// An iterator of all byte positions including the end of the string.
|
let shrunk = format!("{}", ty::ShortInstance(instance, 4));
|
||||||
let positions = || s.char_indices().map(|(i, _)| i).chain(iter::once(s.len()));
|
if shrunk == s {
|
||||||
|
return (s, None);
|
||||||
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(()).temp_path_ext("long-type.txt", None);
|
let path = tcx.output_filenames(()).temp_path_ext("long-type.txt", None);
|
||||||
let written_to_path = std::fs::write(&path, s).ok().map(|_| path);
|
let written_to_path = std::fs::write(&path, s).ok().map(|_| path);
|
||||||
@ -599,7 +592,7 @@ fn check_recursion_limit<'tcx>(
|
|||||||
if !recursion_limit.value_within_limit(adjusted_recursion_depth) {
|
if !recursion_limit.value_within_limit(adjusted_recursion_depth) {
|
||||||
let def_span = tcx.def_span(def_id);
|
let def_span = tcx.def_span(def_id);
|
||||||
let def_path_str = tcx.def_path_str(def_id);
|
let def_path_str = tcx.def_path_str(def_id);
|
||||||
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
|
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance);
|
||||||
let mut path = PathBuf::new();
|
let mut path = PathBuf::new();
|
||||||
let was_written = if written_to_path.is_some() {
|
let was_written = if written_to_path.is_some() {
|
||||||
path = written_to_path.unwrap();
|
path = written_to_path.unwrap();
|
||||||
@ -641,7 +634,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
|
|||||||
//
|
//
|
||||||
// Bail out in these cases to avoid that bad user experience.
|
// Bail out in these cases to avoid that bad user experience.
|
||||||
if !tcx.type_length_limit().value_within_limit(type_length) {
|
if !tcx.type_length_limit().value_within_limit(type_length) {
|
||||||
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
|
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance);
|
||||||
let span = tcx.def_span(instance.def_id());
|
let span = tcx.def_span(instance.def_id());
|
||||||
let mut path = PathBuf::new();
|
let mut path = PathBuf::new();
|
||||||
let was_written = if written_to_path.is_some() {
|
let was_written = if written_to_path.is_some() {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error: reached the recursion limit while instantiating `function::<Option<Option<Option<...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
|
error: reached the recursion limit while instantiating `function::<Option<Option<Option<Option<Option<...>>>>>>`
|
||||||
--> $DIR/infinite-instantiation.rs:22:9
|
--> $DIR/infinite-instantiation.rs:22:9
|
||||||
|
|
|
|
||||||
LL | function(counter - 1, t.to_option());
|
LL | function(counter - 1, t.to_option());
|
||||||
|
@ -9,7 +9,6 @@ note: `A::matches` defined here
|
|||||||
|
|
|
|
||||||
LL | pub fn matches<F: Fn()>(&self, f: &F) {
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error: reached the recursion limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(.....), ...), ...) as Foo>::recurse`
|
error: reached the recursion limit while instantiating `<(&(&(_, _), _), _) as Foo>::recurse`
|
||||||
--> $DIR/issue-37311.rs:17:9
|
--> $DIR/issue-37311.rs:17:9
|
||||||
|
|
|
|
||||||
LL | (self, self).recurse();
|
LL | (self, self).recurse();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut &... &mut &mut &mut &mut &mut Empty>`
|
error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut _>`
|
||||||
--> $DIR/issue-67552.rs:29:9
|
--> $DIR/issue-67552.rs:29:9
|
||||||
|
|
|
|
||||||
LL | rec(identity(&mut it))
|
LL | rec(identity(&mut it))
|
||||||
|
@ -9,7 +9,7 @@ LL | generic::<Option<T>>();
|
|||||||
= help: a `loop` may express intention better if this is on purpose
|
= help: a `loop` may express intention better if this is on purpose
|
||||||
= note: `#[warn(unconditional_recursion)]` on by default
|
= note: `#[warn(unconditional_recursion)]` on by default
|
||||||
|
|
||||||
error: reached the recursion limit while instantiating `generic::<Option<Option<Option<O...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
|
error: reached the recursion limit while instantiating `generic::<Option<Option<Option<Option<Option<...>>>>>>`
|
||||||
--> $DIR/issue-8727.rs:8:5
|
--> $DIR/issue-8727.rs:8:5
|
||||||
|
|
|
|
||||||
LL | generic::<Option<T>>();
|
LL | generic::<Option<T>>();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error: reached the recursion limit while instantiating `test::<Cons<Cons<Cons<Cons<Cons<...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
|
error: reached the recursion limit while instantiating `test::<Cons<Cons<Cons<Cons<Cons<...>>>>>>`
|
||||||
--> $DIR/recursion.rs:18: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})}
|
LL | _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
// The exact type depends on optimizations, so disable them.
|
// The exact type depends on optimizations, so disable them.
|
||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![type_length_limit="4"]
|
#![type_length_limit="8"]
|
||||||
|
|
||||||
macro_rules! link {
|
macro_rules! link {
|
||||||
($id:ident, $t:ty) => {
|
($id:ident, $t:ty) => {
|
||||||
@ -15,14 +15,19 @@ macro_rules! link {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
link! { A1, B1 }
|
||||||
|
link! { B1, C1 }
|
||||||
|
link! { C1, D1 }
|
||||||
|
link! { D1, E1 }
|
||||||
|
link! { E1, A }
|
||||||
link! { A, B }
|
link! { A, B }
|
||||||
link! { B, C }
|
link! { B, C }
|
||||||
link! { C, D }
|
link! { C, D }
|
||||||
link! { D, E }
|
link! { D, E }
|
||||||
link! { E, F }
|
link! { E, F }
|
||||||
link! { F, G }
|
link! { F, G<Option<i32>, Option<i32>> }
|
||||||
|
|
||||||
pub struct G;
|
pub struct G<T, K>(std::marker::PhantomData::<(T, K)>);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
drop::<Option<A>>(None);
|
drop::<Option<A>>(None);
|
||||||
|
@ -1,20 +1,11 @@
|
|||||||
error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((...,....., ...), ..., ...), ..., ...)>>`
|
error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((_, _, _), _, _), _, _), _, _)>>`
|
||||||
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
||||||
|
|
|
|
||||||
LL | pub fn drop<T>(_x: T) {}
|
LL | pub fn drop<T>(_x: T) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: consider adding a `#![type_length_limit="8"]` attribute to your crate
|
= help: consider adding a `#![type_length_limit="10"]` 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'
|
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
|
||||||
|
|
||||||
error: reached the type-length limit while instantiating `<[closure@std::rt::lang_start<()...e<()>>::call_once - shim(vtable)`
|
error: aborting due to previous error
|
||||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
|
||||||
|
|
|
||||||
LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: 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'
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user