Skip to content

Commit ed819cc

Browse files
committed
Add support for shortening Instance and use it
Replace ad-hoc type path shortening logic for recursive mono instantiation errors to use `tcx.short_string()` instead.
1 parent 7278554 commit ed819cc

33 files changed

+192
-199
lines changed

compiler/rustc_middle/messages.ftl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,6 @@ middle_strict_coherence_needs_negative_coherence =
122122
to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
123123
.label = due to this attribute
124124
125-
middle_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
125+
middle_type_length_limit = reached the type-length limit while instantiating `{$instance}`
126126
127127
middle_unsupported_union = we don't support unions yet: '{$ty_name}'
128-
129-
middle_written_to_path = the full type name has been written to '{$path}'

compiler/rustc_middle/src/error.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
use std::path::{Path, PathBuf};
1+
use std::path::Path;
22
use std::{fmt, io};
33

44
use rustc_errors::codes::*;
55
use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage};
66
use rustc_macros::{Diagnostic, Subdiagnostic};
77
use rustc_span::{Span, Symbol};
88

9-
use crate::ty::Ty;
9+
use crate::ty::{Instance, Ty};
1010

1111
#[derive(Diagnostic)]
1212
#[diag(middle_drop_check_overflow, code = E0320)]
@@ -161,13 +161,10 @@ pub(crate) struct ErroneousConstant {
161161
#[derive(Diagnostic)]
162162
#[diag(middle_type_length_limit)]
163163
#[help(middle_consider_type_length_limit)]
164-
pub(crate) struct TypeLengthLimit {
164+
pub(crate) struct TypeLengthLimit<'tcx> {
165165
#[primary_span]
166166
pub span: Span,
167-
pub shrunk: String,
168-
#[note(middle_written_to_path)]
169-
pub was_written: bool,
170-
pub path: PathBuf,
167+
pub instance: Instance<'tcx>,
171168
pub type_length: usize,
172169
}
173170

compiler/rustc_middle/src/ty/diagnostics.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ use rustc_data_structures::fx::FxIndexMap;
77
use rustc_errors::{
88
Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display, listify, pluralize,
99
};
10-
use rustc_hir::def::DefKind;
10+
use rustc_hir::def::{DefKind, Namespace};
1111
use rustc_hir::def_id::DefId;
1212
use rustc_hir::{self as hir, AmbigArg, LangItem, PredicateOrigin, WherePredicateKind};
1313
use rustc_span::{BytePos, Span};
1414
use rustc_type_ir::TyKind::*;
1515

1616
use crate::ty::{
17-
self, AliasTy, Const, ConstKind, FallibleTypeFolder, InferConst, InferTy, Opaque,
17+
self, AliasTy, Const, ConstKind, FallibleTypeFolder, InferConst, InferTy, Instance, Opaque,
1818
PolyTraitPredicate, Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
1919
TypeSuperVisitable, TypeVisitable, TypeVisitor,
2020
};
@@ -28,6 +28,15 @@ impl IntoDiagArg for Ty<'_> {
2828
}
2929
}
3030

31+
impl IntoDiagArg for Instance<'_> {
32+
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
33+
ty::tls::with(|tcx| {
34+
let instance = tcx.short_string_namespace(self, path, Namespace::ValueNS);
35+
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(instance))
36+
})
37+
}
38+
}
39+
3140
into_diag_arg_using_display! {
3241
ty::Region<'_>,
3342
}

compiler/rustc_middle/src/ty/error.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,11 @@ impl<'tcx> Ty<'tcx> {
160160
_ => {
161161
let width = tcx.sess.diagnostic_width();
162162
let length_limit = std::cmp::max(width / 4, 40);
163-
format!("`{}`", tcx.string_with_limit(self, length_limit)).into()
163+
format!(
164+
"`{}`",
165+
tcx.string_with_limit(self, length_limit, hir::def::Namespace::TypeNS)
166+
)
167+
.into()
164168
}
165169
}
166170
}
@@ -213,12 +217,12 @@ impl<'tcx> Ty<'tcx> {
213217
}
214218

215219
impl<'tcx> TyCtxt<'tcx> {
216-
pub fn string_with_limit<T>(self, p: T, length_limit: usize) -> String
220+
pub fn string_with_limit<T>(self, p: T, length_limit: usize, ns: hir::def::Namespace) -> String
217221
where
218222
T: Copy + for<'a, 'b> Lift<TyCtxt<'b>, Lifted: Print<'b, FmtPrinter<'a, 'b>>>,
219223
{
220224
let mut type_limit = 50;
221-
let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| {
225+
let regular = FmtPrinter::print_string(self, ns, |cx| {
222226
self.lift(p).expect("could not lift for printing").print(cx)
223227
})
224228
.expect("could not write to `String`");
@@ -229,11 +233,7 @@ impl<'tcx> TyCtxt<'tcx> {
229233
loop {
230234
// Look for the longest properly trimmed path that still fits in length_limit.
231235
short = with_forced_trimmed_paths!({
232-
let mut cx = FmtPrinter::new_with_limit(
233-
self,
234-
hir::def::Namespace::TypeNS,
235-
rustc_session::Limit(type_limit),
236-
);
236+
let mut cx = FmtPrinter::new_with_limit(self, ns, rustc_session::Limit(type_limit));
237237
self.lift(p)
238238
.expect("could not lift for printing")
239239
.print(&mut cx)
@@ -251,12 +251,28 @@ impl<'tcx> TyCtxt<'tcx> {
251251
/// When calling this after a `Diag` is constructed, the preferred way of doing so is
252252
/// `tcx.short_string(ty, diag.long_ty_path())`. The diagnostic itself is the one that keeps
253253
/// the existence of a "long type" anywhere in the diagnostic, so the note telling the user
254-
/// where we wrote the file to is only printed once.
254+
/// where we wrote the file to is only printed once. The path will use the type namespace.
255255
pub fn short_string<T>(self, p: T, path: &mut Option<PathBuf>) -> String
256256
where
257257
T: Copy + Hash + for<'a, 'b> Lift<TyCtxt<'b>, Lifted: Print<'b, FmtPrinter<'a, 'b>>>,
258258
{
259-
let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| {
259+
self.short_string_namespace(p, path, hir::def::Namespace::TypeNS)
260+
}
261+
262+
/// When calling this after a `Diag` is constructed, the preferred way of doing so is
263+
/// `tcx.short_string(ty, diag.long_ty_path())`. The diagnostic itself is the one that keeps
264+
/// the existence of a "long type" anywhere in the diagnostic, so the note telling the user
265+
/// where we wrote the file to is only printed once.
266+
pub fn short_string_namespace<T>(
267+
self,
268+
p: T,
269+
path: &mut Option<PathBuf>,
270+
namespace: hir::def::Namespace,
271+
) -> String
272+
where
273+
T: Copy + Hash + for<'a, 'b> Lift<TyCtxt<'b>, Lifted: Print<'b, FmtPrinter<'a, 'b>>>,
274+
{
275+
let regular = FmtPrinter::print_string(self, namespace, |cx| {
260276
self.lift(p).expect("could not lift for printing").print(cx)
261277
})
262278
.expect("could not write to `String`");
@@ -270,7 +286,7 @@ impl<'tcx> TyCtxt<'tcx> {
270286
if regular.len() <= width * 2 / 3 {
271287
return regular;
272288
}
273-
let short = self.string_with_limit(p, length_limit);
289+
let short = self.string_with_limit(p, length_limit, namespace);
274290
if regular == short {
275291
return regular;
276292
}

compiler/rustc_middle/src/ty/instance.rs

Lines changed: 9 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::assert_matches::assert_matches;
22
use std::fmt;
3-
use std::path::PathBuf;
43

54
use rustc_data_structures::fx::FxHashMap;
65
use rustc_errors::ErrorGuaranteed;
@@ -17,7 +16,7 @@ use tracing::{debug, instrument};
1716
use crate::error;
1817
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1918
use crate::ty::normalize_erasing_regions::NormalizationError;
20-
use crate::ty::print::{FmtPrinter, Printer, shrunk_instance_name};
19+
use crate::ty::print::{FmtPrinter, Print};
2120
use crate::ty::{
2221
self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
2322
TypeVisitable, TypeVisitableExt, TypeVisitor,
@@ -389,59 +388,15 @@ fn type_length<'tcx>(item: impl TypeVisitable<TyCtxt<'tcx>>) -> usize {
389388
visitor.type_length
390389
}
391390

392-
pub fn fmt_instance(
393-
f: &mut fmt::Formatter<'_>,
394-
instance: Instance<'_>,
395-
type_length: Option<rustc_session::Limit>,
396-
) -> fmt::Result {
397-
ty::tls::with(|tcx| {
398-
let args = tcx.lift(instance.args).expect("could not lift for printing");
399-
400-
let mut cx = if let Some(type_length) = type_length {
401-
FmtPrinter::new_with_limit(tcx, Namespace::ValueNS, type_length)
402-
} else {
403-
FmtPrinter::new(tcx, Namespace::ValueNS)
404-
};
405-
cx.print_def_path(instance.def_id(), args)?;
406-
let s = cx.into_buffer();
407-
f.write_str(&s)
408-
})?;
409-
410-
match instance.def {
411-
InstanceKind::Item(_) => Ok(()),
412-
InstanceKind::VTableShim(_) => write!(f, " - shim(vtable)"),
413-
InstanceKind::ReifyShim(_, None) => write!(f, " - shim(reify)"),
414-
InstanceKind::ReifyShim(_, Some(ReifyReason::FnPtr)) => write!(f, " - shim(reify-fnptr)"),
415-
InstanceKind::ReifyShim(_, Some(ReifyReason::Vtable)) => write!(f, " - shim(reify-vtable)"),
416-
InstanceKind::ThreadLocalShim(_) => write!(f, " - shim(tls)"),
417-
InstanceKind::Intrinsic(_) => write!(f, " - intrinsic"),
418-
InstanceKind::Virtual(_, num) => write!(f, " - virtual#{num}"),
419-
InstanceKind::FnPtrShim(_, ty) => write!(f, " - shim({ty})"),
420-
InstanceKind::ClosureOnceShim { .. } => write!(f, " - shim"),
421-
InstanceKind::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"),
422-
InstanceKind::DropGlue(_, None) => write!(f, " - shim(None)"),
423-
InstanceKind::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
424-
InstanceKind::CloneShim(_, ty) => write!(f, " - shim({ty})"),
425-
InstanceKind::FnPtrAddrShim(_, ty) => write!(f, " - shim({ty})"),
426-
InstanceKind::FutureDropPollShim(_, proxy_ty, impl_ty) => {
427-
write!(f, " - dropshim({proxy_ty}-{impl_ty})")
428-
}
429-
InstanceKind::AsyncDropGlue(_, ty) => write!(f, " - shim({ty})"),
430-
InstanceKind::AsyncDropGlueCtorShim(_, ty) => write!(f, " - shim(Some({ty}))"),
431-
}
432-
}
433-
434-
pub struct ShortInstance<'tcx>(pub Instance<'tcx>, pub usize);
435-
436-
impl<'tcx> fmt::Display for ShortInstance<'tcx> {
437-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
438-
fmt_instance(f, self.0, Some(rustc_session::Limit(self.1)))
439-
}
440-
}
441-
442391
impl<'tcx> fmt::Display for Instance<'tcx> {
443392
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
444-
fmt_instance(f, *self, None)
393+
ty::tls::with(|tcx| {
394+
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
395+
let instance = tcx.lift(*self).expect("could not lift for printing");
396+
instance.print(&mut cx)?;
397+
let s = cx.into_buffer();
398+
f.write_str(&s)
399+
})
445400
}
446401
}
447402

@@ -610,23 +565,12 @@ impl<'tcx> Instance<'tcx> {
610565
Ok(None) => {
611566
let type_length = type_length(args);
612567
if !tcx.type_length_limit().value_within_limit(type_length) {
613-
let (shrunk, written_to_path) =
614-
shrunk_instance_name(tcx, Instance::new_raw(def_id, args));
615-
let mut path = PathBuf::new();
616-
let was_written = if let Some(path2) = written_to_path {
617-
path = path2;
618-
true
619-
} else {
620-
false
621-
};
622568
tcx.dcx().emit_fatal(error::TypeLengthLimit {
623569
// We don't use `def_span(def_id)` so that diagnostics point
624570
// to the crate root during mono instead of to foreign items.
625571
// This is arguably better.
626572
span: span_or_local_def_span(),
627-
shrunk,
628-
was_written,
629-
path,
573+
instance: Instance::new_raw(def_id, args),
630574
type_length,
631575
});
632576
} else {

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ pub use self::context::{
8282
TyCtxtFeed, tls,
8383
};
8484
pub use self::fold::*;
85-
pub use self::instance::{Instance, InstanceKind, ReifyReason, ShortInstance, UnusedGenericParams};
85+
pub use self::instance::{Instance, InstanceKind, ReifyReason, UnusedGenericParams};
8686
pub use self::list::{List, ListWithCachedTypeInfo};
8787
pub use self::opaque_types::OpaqueTypeKey;
8888
pub use self::parameterized::ParameterizedOverTcx;

compiler/rustc_middle/src/ty/print/mod.rs

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::path::PathBuf;
2-
31
use hir::def::Namespace;
42
use rustc_data_structures::fx::FxHashSet;
53
use rustc_data_structures::sso::SsoHashSet;
@@ -8,7 +6,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
86
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
97
use tracing::{debug, instrument, trace};
108

11-
use crate::ty::{self, GenericArg, ShortInstance, Ty, TyCtxt};
9+
use crate::ty::{self, GenericArg, Ty, TyCtxt};
1210

1311
// `pretty` is a separate module only for organization.
1412
mod pretty;
@@ -323,6 +321,43 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
323321
}
324322
}
325323

324+
impl<'tcx, P: Printer<'tcx> + std::fmt::Write> Print<'tcx, P> for ty::Instance<'tcx> {
325+
fn print(&self, cx: &mut P) -> Result<(), PrintError> {
326+
cx.print_def_path(self.def_id(), self.args)?;
327+
match self.def {
328+
ty::InstanceKind::Item(_) => {}
329+
ty::InstanceKind::VTableShim(_) => cx.write_str(" - shim(vtable)")?,
330+
ty::InstanceKind::ReifyShim(_, None) => cx.write_str(" - shim(reify)")?,
331+
ty::InstanceKind::ReifyShim(_, Some(ty::ReifyReason::FnPtr)) => {
332+
cx.write_str(" - shim(reify-fnptr)")?
333+
}
334+
ty::InstanceKind::ReifyShim(_, Some(ty::ReifyReason::Vtable)) => {
335+
cx.write_str(" - shim(reify-vtable)")?
336+
}
337+
ty::InstanceKind::ThreadLocalShim(_) => cx.write_str(" - shim(tls)")?,
338+
ty::InstanceKind::Intrinsic(_) => cx.write_str(" - intrinsic")?,
339+
ty::InstanceKind::Virtual(_, num) => cx.write_str(&format!(" - virtual#{num}"))?,
340+
ty::InstanceKind::FnPtrShim(_, ty) => cx.write_str(&format!(" - shim({ty})"))?,
341+
ty::InstanceKind::ClosureOnceShim { .. } => cx.write_str(" - shim")?,
342+
ty::InstanceKind::ConstructCoroutineInClosureShim { .. } => cx.write_str(" - shim")?,
343+
ty::InstanceKind::DropGlue(_, None) => cx.write_str(" - shim(None)")?,
344+
ty::InstanceKind::DropGlue(_, Some(ty)) => {
345+
cx.write_str(&format!(" - shim(Some({ty}))"))?
346+
}
347+
ty::InstanceKind::CloneShim(_, ty) => cx.write_str(&format!(" - shim({ty})"))?,
348+
ty::InstanceKind::FnPtrAddrShim(_, ty) => cx.write_str(&format!(" - shim({ty})"))?,
349+
ty::InstanceKind::FutureDropPollShim(_, proxy_ty, impl_ty) => {
350+
cx.write_str(&format!(" - dropshim({proxy_ty}-{impl_ty})"))?
351+
}
352+
ty::InstanceKind::AsyncDropGlue(_, ty) => cx.write_str(&format!(" - shim({ty})"))?,
353+
ty::InstanceKind::AsyncDropGlueCtorShim(_, ty) => {
354+
cx.write_str(&format!(" - shim(Some({ty}))"))?
355+
}
356+
};
357+
Ok(())
358+
}
359+
}
360+
326361
impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
327362
fn print(&self, cx: &mut P) -> Result<(), PrintError> {
328363
cx.print_dyn_existential(self)
@@ -362,31 +397,3 @@ where
362397
with_no_trimmed_paths!(Self::print(t, fmt))
363398
}
364399
}
365-
366-
/// Format instance name that is already known to be too long for rustc.
367-
/// Show only the first 2 types if it is longer than 32 characters to avoid blasting
368-
/// the user's terminal with thousands of lines of type-name.
369-
///
370-
/// If the type name is longer than before+after, it will be written to a file.
371-
pub fn shrunk_instance_name<'tcx>(
372-
tcx: TyCtxt<'tcx>,
373-
instance: ty::Instance<'tcx>,
374-
) -> (String, Option<PathBuf>) {
375-
let s = instance.to_string();
376-
377-
// Only use the shrunk version if it's really shorter.
378-
// This also avoids the case where before and after slices overlap.
379-
if s.chars().nth(33).is_some() {
380-
let shrunk = format!("{}", ShortInstance(instance, 4));
381-
if shrunk == s {
382-
return (s, None);
383-
}
384-
385-
let path = tcx.output_filenames(()).temp_path_for_diagnostic("long-type.txt");
386-
let written_to_path = std::fs::write(&path, s).ok().map(|_| path);
387-
388-
(shrunk, written_to_path)
389-
} else {
390-
(s, None)
391-
}
392-
}

compiler/rustc_monomorphize/messages.ftl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ monomorphize_couldnt_dump_mono_stats =
4040
unexpected error occurred while dumping monomorphization stats: {$error}
4141
4242
monomorphize_encountered_error_while_instantiating =
43-
the above error was encountered while instantiating `{$formatted_item}`
43+
the above error was encountered while instantiating `{$kind} {$instance}`
44+
45+
monomorphize_encountered_error_while_instantiating_global_asm =
46+
the above error was encountered while instantiating `global_asm`
4447
4548
monomorphize_large_assignments =
4649
moving {$size} bytes
@@ -52,12 +55,10 @@ monomorphize_no_optimized_mir =
5255
.note = missing optimized MIR for this item (was the crate `{$crate_name}` compiled with `--emit=metadata`?)
5356
5457
monomorphize_recursion_limit =
55-
reached the recursion limit while instantiating `{$shrunk}`
58+
reached the recursion limit while instantiating `{$instance}`
5659
.note = `{$def_path_str}` defined here
5760
5861
monomorphize_start_not_found = using `fn main` requires the standard library
5962
.help = use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[no_mangle]`
6063
6164
monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
62-
63-
monomorphize_written_to_path = the full type name has been written to '{$path}'

0 commit comments

Comments
 (0)