Teach structured errors to display short Ty

Make it so that every structured error annotated with `#[derive(Diagnostic)]` that has a field of type `Ty<'_>`, the printing of that value into a `String` will look at the thread-local storage `TyCtxt` in order to shorten to a length appropriate with the terminal width. When this happen, the resulting error will have a note with the file where the full type name was written to.

```
error[E0618]: expected function, found `((..., ..., ..., ...), ..., ..., ...)``
 --> long.rs:7:5
  |
6 | fn foo(x: D) { //~ `x` has type `(...
  |        - `x` has type `((..., ..., ..., ...), ..., ..., ...)`
7 |     x(); //~ ERROR expected function, found `(...
  |     ^--
  |     |
  |     call expression requires function
  |
  = note: the full name for the type has been written to 'long.long-type-14182675702747116984.txt'
  = note: consider using `--verbose` to print the full type name to the console
```
This commit is contained in:
Esteban Küber 2025-02-18 01:15:59 +00:00
parent c51b9b6d52
commit d12ecaed55
42 changed files with 217 additions and 168 deletions

View file

@ -535,7 +535,6 @@ pub(crate) struct WhereClauseBeforeTypeAlias {
} }
#[derive(Subdiagnostic)] #[derive(Subdiagnostic)]
pub(crate) enum WhereClauseBeforeTypeAliasSugg { pub(crate) enum WhereClauseBeforeTypeAliasSugg {
#[suggestion(ast_passes_remove_suggestion, applicability = "machine-applicable", code = "")] #[suggestion(ast_passes_remove_suggestion, applicability = "machine-applicable", code = "")]
Remove { Remove {

View file

@ -287,7 +287,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
None => "value".to_owned(), None => "value".to_owned(),
}; };
if needs_note { if needs_note {
let ty = self.infcx.tcx.short_string(ty, err.long_ty_path());
if let Some(local) = place.as_local() { if let Some(local) = place.as_local() {
let span = self.body.local_decls[local].source_info.span; let span = self.body.local_decls[local].source_info.span;
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {

View file

@ -596,10 +596,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
self.suggest_cloning(err, place_ty, expr, None); self.suggest_cloning(err, place_ty, expr, None);
} }
let ty = self.infcx.tcx.short_string(place_ty, err.long_ty_path());
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false, is_partial_move: false,
ty, ty: place_ty,
place: &place_desc, place: &place_desc,
span, span,
}); });
@ -629,10 +628,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
self.suggest_cloning(err, place_ty, expr, Some(use_spans)); self.suggest_cloning(err, place_ty, expr, Some(use_spans));
} }
let ty = self.infcx.tcx.short_string(place_ty, err.long_ty_path());
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false, is_partial_move: false,
ty, ty: place_ty,
place: &place_desc, place: &place_desc,
span: use_span, span: use_span,
}); });
@ -833,10 +831,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
self.suggest_cloning(err, bind_to.ty, expr, None); self.suggest_cloning(err, bind_to.ty, expr, None);
} }
let ty = self.infcx.tcx.short_string(bind_to.ty, err.long_ty_path());
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false, is_partial_move: false,
ty, ty: bind_to.ty,
place: place_desc, place: place_desc,
span: binding_span, span: binding_span,
}); });

View file

@ -194,8 +194,8 @@ impl Display for RegionName {
} }
impl rustc_errors::IntoDiagArg for RegionName { impl rustc_errors::IntoDiagArg for RegionName {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
self.to_string().into_diag_arg() self.to_string().into_diag_arg(path)
} }
} }

View file

@ -459,17 +459,17 @@ pub(crate) enum OnClosureNote<'a> {
} }
#[derive(Subdiagnostic)] #[derive(Subdiagnostic)]
pub(crate) enum TypeNoCopy<'a> { pub(crate) enum TypeNoCopy<'a, 'tcx> {
#[label(borrowck_ty_no_impl_copy)] #[label(borrowck_ty_no_impl_copy)]
Label { Label {
is_partial_move: bool, is_partial_move: bool,
ty: String, ty: Ty<'tcx>,
place: &'a str, place: &'a str,
#[primary_span] #[primary_span]
span: Span, span: Span,
}, },
#[note(borrowck_ty_no_impl_copy)] #[note(borrowck_ty_no_impl_copy)]
Note { is_partial_move: bool, ty: String, place: &'a str }, Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str },
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]

View file

@ -211,7 +211,7 @@ impl fmt::Display for CguReuse {
} }
impl IntoDiagArg for CguReuse { impl IntoDiagArg for CguReuse {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Owned(self.to_string())) DiagArgValue::Str(Cow::Owned(self.to_string()))
} }
} }

View file

@ -161,7 +161,7 @@ impl<'a> CopyPath<'a> {
struct DebugArgPath<'a>(pub &'a Path); struct DebugArgPath<'a>(pub &'a Path);
impl IntoDiagArg for DebugArgPath<'_> { impl IntoDiagArg for DebugArgPath<'_> {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
DiagArgValue::Str(Cow::Owned(format!("{:?}", self.0))) DiagArgValue::Str(Cow::Owned(format!("{:?}", self.0)))
} }
} }
@ -1087,7 +1087,7 @@ pub enum ExpectedPointerMutability {
} }
impl IntoDiagArg for ExpectedPointerMutability { impl IntoDiagArg for ExpectedPointerMutability {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
match self { match self {
ExpectedPointerMutability::Mut => DiagArgValue::Str(Cow::Borrowed("*mut")), ExpectedPointerMutability::Mut => DiagArgValue::Str(Cow::Borrowed("*mut")),
ExpectedPointerMutability::Not => DiagArgValue::Str(Cow::Borrowed("*_")), ExpectedPointerMutability::Not => DiagArgValue::Str(Cow::Borrowed("*_")),

View file

@ -49,10 +49,10 @@ impl MachineStopType for ConstEvalErrKind {
| WriteThroughImmutablePointer => {} | WriteThroughImmutablePointer => {}
AssertFailure(kind) => kind.add_args(adder), AssertFailure(kind) => kind.add_args(adder),
Panic { msg, line, col, file } => { Panic { msg, line, col, file } => {
adder("msg".into(), msg.into_diag_arg()); adder("msg".into(), msg.into_diag_arg(&mut None));
adder("file".into(), file.into_diag_arg()); adder("file".into(), file.into_diag_arg(&mut None));
adder("line".into(), line.into_diag_arg()); adder("line".into(), line.into_diag_arg(&mut None));
adder("col".into(), col.into_diag_arg()); adder("col".into(), col.into_diag_arg(&mut None));
} }
} }
} }

View file

@ -967,7 +967,7 @@ impl ReportErrorExt for ResourceExhaustionInfo {
} }
impl rustc_errors::IntoDiagArg for InternKind { impl rustc_errors::IntoDiagArg for InternKind {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Borrowed(match self { DiagArgValue::Str(Cow::Borrowed(match self {
InternKind::Static(Mutability::Not) => "static", InternKind::Static(Mutability::Not) => "static",
InternKind::Static(Mutability::Mut) => "static_mut", InternKind::Static(Mutability::Mut) => "static_mut",

View file

@ -148,11 +148,11 @@ where
/// converted rather than on `DiagArgValue`, which enables types from other `rustc_*` crates to /// converted rather than on `DiagArgValue`, which enables types from other `rustc_*` crates to
/// implement this. /// implement this.
pub trait IntoDiagArg { pub trait IntoDiagArg {
fn into_diag_arg(self) -> DiagArgValue; fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue;
} }
impl IntoDiagArg for DiagArgValue { impl IntoDiagArg for DiagArgValue {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self self
} }
} }
@ -395,7 +395,7 @@ impl DiagInner {
} }
pub(crate) fn arg(&mut self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) { pub(crate) fn arg(&mut self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) {
self.args.insert(name.into(), arg.into_diag_arg()); self.args.insert(name.into(), arg.into_diag_arg(&mut self.long_ty_path));
} }
/// Fields used for Hash, and PartialEq trait. /// Fields used for Hash, and PartialEq trait.

View file

@ -25,8 +25,8 @@ use crate::{
pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display); pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display);
impl IntoDiagArg for DiagArgFromDisplay<'_> { impl IntoDiagArg for DiagArgFromDisplay<'_> {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self.0.to_string().into_diag_arg() self.0.to_string().into_diag_arg(path)
} }
} }
@ -43,8 +43,8 @@ impl<'a, T: fmt::Display> From<&'a T> for DiagArgFromDisplay<'a> {
} }
impl<'a, T: Clone + IntoDiagArg> IntoDiagArg for &'a T { impl<'a, T: Clone + IntoDiagArg> IntoDiagArg for &'a T {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self.clone().into_diag_arg() self.clone().into_diag_arg(path)
} }
} }
@ -53,8 +53,8 @@ macro_rules! into_diag_arg_using_display {
($( $ty:ty ),+ $(,)?) => { ($( $ty:ty ),+ $(,)?) => {
$( $(
impl IntoDiagArg for $ty { impl IntoDiagArg for $ty {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self.to_string().into_diag_arg() self.to_string().into_diag_arg(path)
} }
} }
)+ )+
@ -65,13 +65,13 @@ macro_rules! into_diag_arg_for_number {
($( $ty:ty ),+ $(,)?) => { ($( $ty:ty ),+ $(,)?) => {
$( $(
impl IntoDiagArg for $ty { impl IntoDiagArg for $ty {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
// Convert to a string if it won't fit into `Number`. // Convert to a string if it won't fit into `Number`.
#[allow(irrefutable_let_patterns)] #[allow(irrefutable_let_patterns)]
if let Ok(n) = TryInto::<i32>::try_into(self) { if let Ok(n) = TryInto::<i32>::try_into(self) {
DiagArgValue::Number(n) DiagArgValue::Number(n)
} else { } else {
self.to_string().into_diag_arg() self.to_string().into_diag_arg(path)
} }
} }
} }
@ -104,26 +104,26 @@ impl IntoDiagArg for RustcVersion {
} }
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::TraitRef<I> { impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::TraitRef<I> {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self.to_string().into_diag_arg() self.to_string().into_diag_arg(path)
} }
} }
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::ExistentialTraitRef<I> { impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::ExistentialTraitRef<I> {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self.to_string().into_diag_arg() self.to_string().into_diag_arg(path)
} }
} }
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::UnevaluatedConst<I> { impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::UnevaluatedConst<I> {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
format!("{self:?}").into_diag_arg() format!("{self:?}").into_diag_arg(path)
} }
} }
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::FnSig<I> { impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::FnSig<I> {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
format!("{self:?}").into_diag_arg() format!("{self:?}").into_diag_arg(path)
} }
} }
@ -131,15 +131,15 @@ impl<I: rustc_type_ir::Interner, T> IntoDiagArg for rustc_type_ir::Binder<I, T>
where where
T: IntoDiagArg, T: IntoDiagArg,
{ {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self.skip_binder().into_diag_arg() self.skip_binder().into_diag_arg(path)
} }
} }
into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize); into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
impl IntoDiagArg for bool { impl IntoDiagArg for bool {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
if self { if self {
DiagArgValue::Str(Cow::Borrowed("true")) DiagArgValue::Str(Cow::Borrowed("true"))
} else { } else {
@ -149,13 +149,13 @@ impl IntoDiagArg for bool {
} }
impl IntoDiagArg for char { impl IntoDiagArg for char {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Owned(format!("{self:?}"))) DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
} }
} }
impl IntoDiagArg for Vec<char> { impl IntoDiagArg for Vec<char> {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::StrListSepByAnd( DiagArgValue::StrListSepByAnd(
self.into_iter().map(|c| Cow::Owned(format!("{c:?}"))).collect(), self.into_iter().map(|c| Cow::Owned(format!("{c:?}"))).collect(),
) )
@ -163,49 +163,49 @@ impl IntoDiagArg for Vec<char> {
} }
impl IntoDiagArg for Symbol { impl IntoDiagArg for Symbol {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self.to_ident_string().into_diag_arg() self.to_ident_string().into_diag_arg(path)
} }
} }
impl<'a> IntoDiagArg for &'a str { impl<'a> IntoDiagArg for &'a str {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self.to_string().into_diag_arg() self.to_string().into_diag_arg(path)
} }
} }
impl IntoDiagArg for String { impl IntoDiagArg for String {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Owned(self)) DiagArgValue::Str(Cow::Owned(self))
} }
} }
impl<'a> IntoDiagArg for Cow<'a, str> { impl<'a> IntoDiagArg for Cow<'a, str> {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Owned(self.into_owned())) DiagArgValue::Str(Cow::Owned(self.into_owned()))
} }
} }
impl<'a> IntoDiagArg for &'a Path { impl<'a> IntoDiagArg for &'a Path {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Owned(self.display().to_string())) DiagArgValue::Str(Cow::Owned(self.display().to_string()))
} }
} }
impl IntoDiagArg for PathBuf { impl IntoDiagArg for PathBuf {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Owned(self.display().to_string())) DiagArgValue::Str(Cow::Owned(self.display().to_string()))
} }
} }
impl IntoDiagArg for PanicStrategy { impl IntoDiagArg for PanicStrategy {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Owned(self.desc().to_string())) DiagArgValue::Str(Cow::Owned(self.desc().to_string()))
} }
} }
impl IntoDiagArg for hir::ConstContext { impl IntoDiagArg for hir::ConstContext {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Borrowed(match self { DiagArgValue::Str(Cow::Borrowed(match self {
hir::ConstContext::ConstFn => "const_fn", hir::ConstContext::ConstFn => "const_fn",
hir::ConstContext::Static(_) => "static", hir::ConstContext::Static(_) => "static",
@ -215,49 +215,49 @@ impl IntoDiagArg for hir::ConstContext {
} }
impl IntoDiagArg for ast::Expr { impl IntoDiagArg for ast::Expr {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Owned(pprust::expr_to_string(&self))) DiagArgValue::Str(Cow::Owned(pprust::expr_to_string(&self)))
} }
} }
impl IntoDiagArg for ast::Path { impl IntoDiagArg for ast::Path {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Owned(pprust::path_to_string(&self))) DiagArgValue::Str(Cow::Owned(pprust::path_to_string(&self)))
} }
} }
impl IntoDiagArg for ast::token::Token { impl IntoDiagArg for ast::token::Token {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(pprust::token_to_string(&self)) DiagArgValue::Str(pprust::token_to_string(&self))
} }
} }
impl IntoDiagArg for ast::token::TokenKind { impl IntoDiagArg for ast::token::TokenKind {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(pprust::token_kind_to_string(&self)) DiagArgValue::Str(pprust::token_kind_to_string(&self))
} }
} }
impl IntoDiagArg for FloatTy { impl IntoDiagArg for FloatTy {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Borrowed(self.name_str())) DiagArgValue::Str(Cow::Borrowed(self.name_str()))
} }
} }
impl IntoDiagArg for std::ffi::CString { impl IntoDiagArg for std::ffi::CString {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned())) DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
} }
} }
impl IntoDiagArg for rustc_data_structures::small_c_str::SmallCStr { impl IntoDiagArg for rustc_data_structures::small_c_str::SmallCStr {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned())) DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
} }
} }
impl IntoDiagArg for ast::Visibility { impl IntoDiagArg for ast::Visibility {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
let s = pprust::vis_to_string(&self); let s = pprust::vis_to_string(&self);
let s = s.trim_end().to_string(); let s = s.trim_end().to_string();
DiagArgValue::Str(Cow::Owned(s)) DiagArgValue::Str(Cow::Owned(s))
@ -265,49 +265,49 @@ impl IntoDiagArg for ast::Visibility {
} }
impl IntoDiagArg for rustc_lint_defs::Level { impl IntoDiagArg for rustc_lint_defs::Level {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Borrowed(self.to_cmd_flag())) DiagArgValue::Str(Cow::Borrowed(self.to_cmd_flag()))
} }
} }
impl<Id> IntoDiagArg for hir::def::Res<Id> { impl<Id> IntoDiagArg for hir::def::Res<Id> {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Borrowed(self.descr())) DiagArgValue::Str(Cow::Borrowed(self.descr()))
} }
} }
impl IntoDiagArg for DiagLocation { impl IntoDiagArg for DiagLocation {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::from(self.to_string())) DiagArgValue::Str(Cow::from(self.to_string()))
} }
} }
impl IntoDiagArg for Backtrace { impl IntoDiagArg for Backtrace {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::from(self.to_string())) DiagArgValue::Str(Cow::from(self.to_string()))
} }
} }
impl IntoDiagArg for Level { impl IntoDiagArg for Level {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::from(self.to_string())) DiagArgValue::Str(Cow::from(self.to_string()))
} }
} }
impl IntoDiagArg for ClosureKind { impl IntoDiagArg for ClosureKind {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(self.as_str().into()) DiagArgValue::Str(self.as_str().into())
} }
} }
impl IntoDiagArg for hir::def::Namespace { impl IntoDiagArg for hir::def::Namespace {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Borrowed(self.descr())) DiagArgValue::Str(Cow::Borrowed(self.descr()))
} }
} }
impl IntoDiagArg for ExprPrecedence { impl IntoDiagArg for ExprPrecedence {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Number(self as i32) DiagArgValue::Number(self as i32)
} }
} }
@ -328,7 +328,7 @@ impl<S> FromIterator<S> for DiagSymbolList<S> {
} }
impl<S: std::fmt::Display> IntoDiagArg for DiagSymbolList<S> { impl<S: std::fmt::Display> IntoDiagArg for DiagSymbolList<S> {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::StrListSepByAnd( DiagArgValue::StrListSepByAnd(
self.0.into_iter().map(|sym| Cow::Owned(format!("`{sym}`"))).collect(), self.0.into_iter().map(|sym| Cow::Owned(format!("`{sym}`"))).collect(),
) )

View file

@ -112,7 +112,11 @@ hir_typeck_int_to_fat = cannot cast `{$expr_ty}` to a pointer that {$known_wide
hir_typeck_int_to_fat_label = creating a `{$cast_ty}` requires both an address and {$metadata} hir_typeck_int_to_fat_label = creating a `{$cast_ty}` requires both an address and {$metadata}
hir_typeck_int_to_fat_label_nightly = consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` hir_typeck_int_to_fat_label_nightly = consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
hir_typeck_invalid_callee = expected function, found {$ty} hir_typeck_invalid_callee = expected function, found {$found}
hir_typeck_invalid_defined = `{$path}` defined here
hir_typeck_invalid_defined_kind = {$kind} `{$path}` defined here
hir_typeck_invalid_fn_defined = `{$func}` defined here returns `{$ty}`
hir_typeck_invalid_local = `{$local_name}` has type `{$ty}`
hir_typeck_lossy_provenance_int2ptr = hir_typeck_lossy_provenance_int2ptr =
strict provenance disallows casting integer `{$expr_ty}` to pointer `{$cast_ty}` strict provenance disallows casting integer `{$expr_ty}` to pointer `{$cast_ty}`

View file

@ -23,7 +23,7 @@ use tracing::{debug, instrument};
use super::method::MethodCallee; use super::method::MethodCallee;
use super::method::probe::ProbeScope; use super::method::probe::ProbeScope;
use super::{Expectation, FnCtxt, TupleArgumentsFlag}; use super::{Expectation, FnCtxt, TupleArgumentsFlag};
use crate::errors; use crate::{errors, fluent_generated};
/// Checks that it is legal to call methods of the trait corresponding /// Checks that it is legal to call methods of the trait corresponding
/// to `trait_id` (this only cares about the trait, not the specific /// to `trait_id` (this only cares about the trait, not the specific
@ -674,13 +674,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
let callee_ty = self.resolve_vars_if_possible(callee_ty); let callee_ty = self.resolve_vars_if_possible(callee_ty);
let mut path = None;
let mut err = self.dcx().create_err(errors::InvalidCallee { let mut err = self.dcx().create_err(errors::InvalidCallee {
span: callee_expr.span, span: callee_expr.span,
ty: match &unit_variant { ty: callee_ty,
found: match &unit_variant {
Some((_, kind, path)) => format!("{kind} `{path}`"), Some((_, kind, path)) => format!("{kind} `{path}`"),
None => format!("`{callee_ty}`"), None => format!("`{}`", self.tcx.short_string(callee_ty, &mut path)),
}, },
}); });
*err.long_ty_path() = path;
if callee_ty.references_error() { if callee_ty.references_error() {
err.downgrade_to_delayed_bug(); err.downgrade_to_delayed_bug();
} }
@ -780,27 +783,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(span) = self.tcx.hir().res_span(def) { if let Some(span) = self.tcx.hir().res_span(def) {
let callee_ty = callee_ty.to_string(); let callee_ty = callee_ty.to_string();
let label = match (unit_variant, inner_callee_path) { let label = match (unit_variant, inner_callee_path) {
(Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")), (Some((_, kind, path)), _) => {
(_, Some(hir::QPath::Resolved(_, path))) => self err.arg("kind", kind);
.tcx err.arg("path", path);
.sess Some(fluent_generated::hir_typeck_invalid_defined_kind)
.source_map() }
.span_to_snippet(path.span) (_, Some(hir::QPath::Resolved(_, path))) => {
.ok() self.tcx.sess.source_map().span_to_snippet(path.span).ok().map(|p| {
.map(|p| format!("`{p}` defined here returns `{callee_ty}`")), err.arg("func", p);
fluent_generated::hir_typeck_invalid_fn_defined
})
}
_ => { _ => {
match def { match def {
// Emit a different diagnostic for local variables, as they are not // Emit a different diagnostic for local variables, as they are not
// type definitions themselves, but rather variables *of* that type. // type definitions themselves, but rather variables *of* that type.
Res::Local(hir_id) => Some(format!( Res::Local(hir_id) => {
"`{}` has type `{}`", err.arg("local_name", self.tcx.hir().name(hir_id));
self.tcx.hir().name(hir_id), Some(fluent_generated::hir_typeck_invalid_local)
callee_ty }
)), Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => { err.arg("path", self.tcx.def_path_str(def_id));
Some(format!("`{}` defined here", self.tcx.def_path_str(def_id),)) Some(fluent_generated::hir_typeck_invalid_defined)
}
_ => {
err.arg("path", callee_ty);
Some(fluent_generated::hir_typeck_invalid_defined)
} }
_ => Some(format!("`{callee_ty}` defined here")),
} }
} }
}; };

View file

@ -548,17 +548,19 @@ impl<'a, 'tcx> CastCheck<'tcx> {
err.emit(); err.emit();
} }
CastError::SizedUnsizedCast => { CastError::SizedUnsizedCast => {
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
fcx.dcx().emit_err(errors::CastThinPointerToWidePointer { fcx.dcx().emit_err(errors::CastThinPointerToWidePointer {
span: self.span, span: self.span,
expr_ty: self.expr_ty, expr_ty,
cast_ty: fcx.ty_to_string(self.cast_ty), cast_ty,
teach: fcx.tcx.sess.teach(E0607), teach: fcx.tcx.sess.teach(E0607),
}); });
} }
CastError::IntToWideCast(known_metadata) => { CastError::IntToWideCast(known_metadata) => {
let expr_if_nightly = fcx.tcx.sess.is_nightly_build().then_some(self.expr_span); let expr_if_nightly = fcx.tcx.sess.is_nightly_build().then_some(self.expr_span);
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty); let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
let expr_ty = fcx.ty_to_string(self.expr_ty); let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
let metadata = known_metadata.unwrap_or("type-specific metadata"); let metadata = known_metadata.unwrap_or("type-specific metadata");
let known_wide = known_metadata.is_some(); let known_wide = known_metadata.is_some();
let span = self.cast_span; let span = self.cast_span;
@ -1164,10 +1166,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
if let Some((deref_ty, _)) = derefed { if let Some((deref_ty, _)) = derefed {
// Give a note about what the expr derefs to. // Give a note about what the expr derefs to.
if deref_ty != self.expr_ty.peel_refs() { if deref_ty != self.expr_ty.peel_refs() {
err.subdiagnostic(errors::DerefImplsIsEmpty { err.subdiagnostic(errors::DerefImplsIsEmpty { span: self.expr_span, deref_ty });
span: self.expr_span,
deref_ty: fcx.ty_to_string(deref_ty),
});
} }
// Create a multipart suggestion: add `!` and `.is_empty()` in // Create a multipart suggestion: add `!` and `.is_empty()` in
@ -1175,7 +1174,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
err.subdiagnostic(errors::UseIsEmpty { err.subdiagnostic(errors::UseIsEmpty {
lo: self.expr_span.shrink_to_lo(), lo: self.expr_span.shrink_to_lo(),
hi: self.span.with_lo(self.expr_span.hi()), hi: self.span.with_lo(self.expr_span.hi()),
expr_ty: fcx.ty_to_string(self.expr_ty), expr_ty: self.expr_ty,
}); });
} }
} }

View file

@ -91,7 +91,7 @@ pub(crate) enum ReturnLikeStatementKind {
} }
impl IntoDiagArg for ReturnLikeStatementKind { impl IntoDiagArg for ReturnLikeStatementKind {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
let kind = match self { let kind = match self {
Self::Return => "return", Self::Return => "return",
Self::Become => "become", Self::Become => "become",
@ -456,10 +456,11 @@ impl HelpUseLatestEdition {
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(hir_typeck_invalid_callee, code = E0618)] #[diag(hir_typeck_invalid_callee, code = E0618)]
pub(crate) struct InvalidCallee { pub(crate) struct InvalidCallee<'tcx> {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
pub ty: String, pub ty: Ty<'tcx>,
pub found: String,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
@ -469,7 +470,7 @@ pub(crate) struct IntToWide<'tcx> {
#[label(hir_typeck_int_to_fat_label)] #[label(hir_typeck_int_to_fat_label)]
pub span: Span, pub span: Span,
pub metadata: &'tcx str, pub metadata: &'tcx str,
pub expr_ty: String, pub expr_ty: Ty<'tcx>,
pub cast_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>,
#[label(hir_typeck_int_to_fat_label_nightly)] #[label(hir_typeck_int_to_fat_label_nightly)]
pub expr_if_nightly: Option<Span>, pub expr_if_nightly: Option<Span>,
@ -581,12 +582,12 @@ pub(crate) struct UnionPatDotDot {
applicability = "maybe-incorrect", applicability = "maybe-incorrect",
style = "verbose" style = "verbose"
)] )]
pub(crate) struct UseIsEmpty { pub(crate) struct UseIsEmpty<'tcx> {
#[suggestion_part(code = "!")] #[suggestion_part(code = "!")]
pub lo: Span, pub lo: Span,
#[suggestion_part(code = ".is_empty()")] #[suggestion_part(code = ".is_empty()")]
pub hi: Span, pub hi: Span,
pub expr_ty: String, pub expr_ty: Ty<'tcx>,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
@ -745,10 +746,10 @@ pub(crate) struct CtorIsPrivate {
#[derive(Subdiagnostic)] #[derive(Subdiagnostic)]
#[note(hir_typeck_deref_is_empty)] #[note(hir_typeck_deref_is_empty)]
pub(crate) struct DerefImplsIsEmpty { pub(crate) struct DerefImplsIsEmpty<'tcx> {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
pub deref_ty: String, pub deref_ty: Ty<'tcx>,
} }
#[derive(Subdiagnostic)] #[derive(Subdiagnostic)]
@ -826,7 +827,7 @@ pub(crate) struct CastThinPointerToWidePointer<'tcx> {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
pub expr_ty: Ty<'tcx>, pub expr_ty: Ty<'tcx>,
pub cast_ty: String, pub cast_ty: Ty<'tcx>,
#[note(hir_typeck_teach_help)] #[note(hir_typeck_teach_help)]
pub(crate) teach: bool, pub(crate) teach: bool,
} }

View file

@ -290,7 +290,7 @@ impl fmt::Display for CrateFlavor {
} }
impl IntoDiagArg for CrateFlavor { impl IntoDiagArg for CrateFlavor {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
match self { match self {
CrateFlavor::Rlib => DiagArgValue::Str(Cow::Borrowed("rlib")), CrateFlavor::Rlib => DiagArgValue::Str(Cow::Borrowed("rlib")),
CrateFlavor::Rmeta => DiagArgValue::Str(Cow::Borrowed("rmeta")), CrateFlavor::Rmeta => DiagArgValue::Str(Cow::Borrowed("rmeta")),

View file

@ -47,10 +47,10 @@ pub struct UnsupportedUnion {
// FIXME(autodiff): I should get used somewhere // FIXME(autodiff): I should get used somewhere
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(middle_autodiff_unsafe_inner_const_ref)] #[diag(middle_autodiff_unsafe_inner_const_ref)]
pub struct AutodiffUnsafeInnerConstRef { pub struct AutodiffUnsafeInnerConstRef<'tcx> {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
pub ty: String, pub ty: Ty<'tcx>,
} }
#[derive(Subdiagnostic)] #[derive(Subdiagnostic)]

View file

@ -248,7 +248,7 @@ pub enum InvalidMetaKind {
} }
impl IntoDiagArg for InvalidMetaKind { impl IntoDiagArg for InvalidMetaKind {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Borrowed(match self { DiagArgValue::Str(Cow::Borrowed(match self {
InvalidMetaKind::SliceTooBig => "slice_too_big", InvalidMetaKind::SliceTooBig => "slice_too_big",
InvalidMetaKind::TooBig => "too_big", InvalidMetaKind::TooBig => "too_big",
@ -282,7 +282,7 @@ pub struct Misalignment {
macro_rules! impl_into_diag_arg_through_debug { macro_rules! impl_into_diag_arg_through_debug {
($($ty:ty),*$(,)?) => {$( ($($ty:ty),*$(,)?) => {$(
impl IntoDiagArg for $ty { impl IntoDiagArg for $ty {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Owned(format!("{self:?}"))) DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
} }
} }
@ -401,7 +401,7 @@ pub enum PointerKind {
} }
impl IntoDiagArg for PointerKind { impl IntoDiagArg for PointerKind {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str( DiagArgValue::Str(
match self { match self {
Self::Ref(_) => "ref", Self::Ref(_) => "ref",
@ -666,7 +666,7 @@ macro_rules! err_ub_custom {
msg: || $msg, msg: || $msg,
add_args: Box::new(move |mut set_arg| { add_args: Box::new(move |mut set_arg| {
$($( $($(
set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name)); set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name, &mut None));
)*)? )*)?
}) })
} }

View file

@ -357,7 +357,7 @@ impl<O> AssertKind<O> {
macro_rules! add { macro_rules! add {
($name: expr, $value: expr) => { ($name: expr, $value: expr) => {
adder($name.into(), $value.into_diag_arg()); adder($name.into(), $value.into_diag_arg(&mut None));
}; };
} }

View file

@ -118,7 +118,7 @@ impl std::fmt::Debug for ConstInt {
impl IntoDiagArg for ConstInt { impl IntoDiagArg for ConstInt {
// FIXME this simply uses the Debug impl, but we could probably do better by converting both // FIXME this simply uses the Debug impl, but we could probably do better by converting both
// to an inherent method that returns `Cow`. // to an inherent method that returns `Cow`.
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(format!("{self:?}").into()) DiagArgValue::Str(format!("{self:?}").into())
} }
} }

View file

@ -19,8 +19,16 @@ use crate::ty::{
TypeSuperVisitable, TypeVisitable, TypeVisitor, TypeSuperVisitable, TypeVisitable, TypeVisitor,
}; };
impl IntoDiagArg for Ty<'_> {
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
ty::tls::with(|tcx| {
let ty = tcx.short_string(self, path);
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(ty))
})
}
}
into_diag_arg_using_display! { into_diag_arg_using_display! {
Ty<'_>,
ty::Region<'_>, ty::Region<'_>,
} }

View file

@ -213,10 +213,9 @@ impl<'tcx> Ty<'tcx> {
} }
impl<'tcx> TyCtxt<'tcx> { impl<'tcx> TyCtxt<'tcx> {
pub fn string_with_limit<'a, T>(self, p: T, length_limit: usize) -> String pub fn string_with_limit<T>(self, p: T, length_limit: usize) -> String
where where
T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift<TyCtxt<'tcx>> + Copy, T: Copy + for<'a, 'b> Lift<TyCtxt<'b>, Lifted: Print<'b, FmtPrinter<'a, 'b>>>,
<T as Lift<TyCtxt<'tcx>>>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>,
{ {
let mut type_limit = 50; let mut type_limit = 50;
let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| { let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| {
@ -253,10 +252,9 @@ impl<'tcx> TyCtxt<'tcx> {
/// `tcx.short_string(ty, diag.long_ty_path())`. The diagnostic itself is the one that keeps /// `tcx.short_string(ty, diag.long_ty_path())`. The diagnostic itself is the one that keeps
/// the existence of a "long type" anywhere in the diagnostic, so the note telling the user /// the existence of a "long type" anywhere in the diagnostic, so the note telling the user
/// where we wrote the file to is only printed once. /// where we wrote the file to is only printed once.
pub fn short_string<'a, T>(self, p: T, path: &mut Option<PathBuf>) -> String pub fn short_string<T>(self, p: T, path: &mut Option<PathBuf>) -> String
where where
T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift<TyCtxt<'tcx>> + Copy + Hash, T: Copy + Hash + for<'a, 'b> Lift<TyCtxt<'b>, Lifted: Print<'b, FmtPrinter<'a, 'b>>>,
<T as Lift<TyCtxt<'tcx>>>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>,
{ {
let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| { let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| {
self.lift(p).expect("could not lift for printing").print(cx) self.lift(p).expect("could not lift for printing").print(cx)

View file

@ -159,8 +159,8 @@ unsafe impl<'tcx> Sync for GenericArg<'tcx> where
} }
impl<'tcx> IntoDiagArg for GenericArg<'tcx> { impl<'tcx> IntoDiagArg for GenericArg<'tcx> {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self.to_string().into_diag_arg() self.to_string().into_diag_arg(&mut None)
} }
} }

View file

@ -315,8 +315,8 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
} }
impl<'tcx> IntoDiagArg for LayoutError<'tcx> { impl<'tcx> IntoDiagArg for LayoutError<'tcx> {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self.to_string().into_diag_arg() self.to_string().into_diag_arg(&mut None)
} }
} }

View file

@ -158,15 +158,21 @@ impl<'tcx> Predicate<'tcx> {
} }
} }
impl rustc_errors::IntoDiagArg for Predicate<'_> { impl<'tcx> rustc_errors::IntoDiagArg for Predicate<'tcx> {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(self.to_string())) ty::tls::with(|tcx| {
let pred = tcx.short_string(self, path);
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(pred))
})
} }
} }
impl rustc_errors::IntoDiagArg for Clause<'_> { impl<'tcx> rustc_errors::IntoDiagArg for Clause<'tcx> {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(self.to_string())) ty::tls::with(|tcx| {
let clause = tcx.short_string(self, path);
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(clause))
})
} }
} }

View file

@ -2898,12 +2898,15 @@ where
/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
/// the trait path. That is, it will print `Trait<U>` instead of /// the trait path. That is, it will print `Trait<U>` instead of
/// `<T as Trait<U>>`. /// `<T as Trait<U>>`.
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] #[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)]
pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>); pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);
impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintOnlyTraitPath<'tcx> { impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintOnlyTraitPath<'tcx> {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
self.to_string().into_diag_arg() ty::tls::with(|tcx| {
let trait_ref = tcx.short_string(self, path);
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(trait_ref))
})
} }
} }
@ -2915,12 +2918,15 @@ impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
/// the trait path, and additionally tries to "sugar" `Fn(...)` trait bounds. /// the trait path, and additionally tries to "sugar" `Fn(...)` trait bounds.
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] #[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)]
pub struct TraitRefPrintSugared<'tcx>(ty::TraitRef<'tcx>); pub struct TraitRefPrintSugared<'tcx>(ty::TraitRef<'tcx>);
impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintSugared<'tcx> { impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintSugared<'tcx> {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
self.to_string().into_diag_arg() ty::tls::with(|tcx| {
let trait_ref = tcx.short_string(self, path);
rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(trait_ref))
})
} }
} }

View file

@ -828,7 +828,7 @@ pub(crate) struct IrrefutableLetPatternsWhileLet {
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(mir_build_borrow_of_moved_value)] #[diag(mir_build_borrow_of_moved_value)]
pub(crate) struct BorrowOfMovedValue { pub(crate) struct BorrowOfMovedValue<'tcx> {
#[primary_span] #[primary_span]
#[label] #[label]
#[label(mir_build_occurs_because_label)] #[label(mir_build_occurs_because_label)]
@ -836,7 +836,7 @@ pub(crate) struct BorrowOfMovedValue {
#[label(mir_build_value_borrowed_label)] #[label(mir_build_value_borrowed_label)]
pub(crate) conflicts_ref: Vec<Span>, pub(crate) conflicts_ref: Vec<Span>,
pub(crate) name: Ident, pub(crate) name: Ident,
pub(crate) ty: String, pub(crate) ty: Ty<'tcx>,
#[suggestion(code = "ref ", applicability = "machine-applicable")] #[suggestion(code = "ref ", applicability = "machine-applicable")]
pub(crate) suggest_borrowing: Option<Span>, pub(crate) suggest_borrowing: Option<Span>,
} }

View file

@ -786,17 +786,13 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
} }
}); });
if !conflicts_ref.is_empty() { if !conflicts_ref.is_empty() {
let mut path = None; sess.dcx().emit_err(BorrowOfMovedValue {
let ty = cx.tcx.short_string(ty, &mut path);
let mut err = sess.dcx().create_err(BorrowOfMovedValue {
binding_span: pat.span, binding_span: pat.span,
conflicts_ref, conflicts_ref,
name: Ident::new(name, pat.span), name: Ident::new(name, pat.span),
ty, ty,
suggest_borrowing: Some(pat.span.shrink_to_lo()), suggest_borrowing: Some(pat.span.shrink_to_lo()),
}); });
*err.long_ty_path() = path;
err.emit();
} }
return; return;
} }

View file

@ -772,7 +772,6 @@ pub(crate) struct LabeledLoopInBreak {
} }
#[derive(Subdiagnostic)] #[derive(Subdiagnostic)]
pub(crate) enum WrapInParentheses { pub(crate) enum WrapInParentheses {
#[multipart_suggestion( #[multipart_suggestion(
parse_sugg_wrap_expression_in_parentheses, parse_sugg_wrap_expression_in_parentheses,

View file

@ -80,13 +80,13 @@ pub(crate) enum ProcMacroKind {
} }
impl IntoDiagArg for ProcMacroKind { impl IntoDiagArg for ProcMacroKind {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
match self { match self {
ProcMacroKind::Attribute => "attribute proc macro", ProcMacroKind::Attribute => "attribute proc macro",
ProcMacroKind::Derive => "derive proc macro", ProcMacroKind::Derive => "derive proc macro",
ProcMacroKind::FunctionLike => "function-like proc macro", ProcMacroKind::FunctionLike => "function-like proc macro",
} }
.into_diag_arg() .into_diag_arg(&mut None)
} }
} }

View file

@ -1005,10 +1005,10 @@ pub(crate) struct LayoutHomogeneousAggregate {
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(passes_layout_of)] #[diag(passes_layout_of)]
pub(crate) struct LayoutOf { pub(crate) struct LayoutOf<'tcx> {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
pub normalized_ty: String, pub normalized_ty: Ty<'tcx>,
pub ty_layout: String, pub ty_layout: String,
} }

View file

@ -112,8 +112,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
} }
sym::debug => { sym::debug => {
let normalized_ty = let normalized_ty = tcx.normalize_erasing_regions(typing_env, ty);
format!("{}", tcx.normalize_erasing_regions(typing_env, ty));
// FIXME: using the `Debug` impl here isn't ideal. // FIXME: using the `Debug` impl here isn't ideal.
let ty_layout = format!("{:#?}", *ty_layout); let ty_layout = format!("{:#?}", *ty_layout);
tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout }); tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout });

View file

@ -94,7 +94,7 @@ impl PatternSource {
} }
impl IntoDiagArg for PatternSource { impl IntoDiagArg for PatternSource {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(Cow::Borrowed(self.descr())) DiagArgValue::Str(Cow::Borrowed(self.descr()))
} }
} }

View file

@ -2807,8 +2807,8 @@ impl fmt::Display for CrateType {
} }
impl IntoDiagArg for CrateType { impl IntoDiagArg for CrateType {
fn into_diag_arg(self) -> DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self.to_string().into_diag_arg() self.to_string().into_diag_arg(&mut None)
} }
} }

View file

@ -109,8 +109,8 @@ impl Mul<usize> for Limit {
} }
impl rustc_errors::IntoDiagArg for Limit { impl rustc_errors::IntoDiagArg for Limit {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
self.to_string().into_diag_arg() self.to_string().into_diag_arg(&mut None)
} }
} }

View file

@ -2418,7 +2418,7 @@ impl<'tcx> ObligationCause<'tcx> {
pub struct ObligationCauseAsDiagArg<'tcx>(pub ObligationCause<'tcx>); pub struct ObligationCauseAsDiagArg<'tcx>(pub ObligationCause<'tcx>);
impl IntoDiagArg for ObligationCauseAsDiagArg<'_> { impl IntoDiagArg for ObligationCauseAsDiagArg<'_> {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
let kind = match self.0.code() { let kind = match self.0.code() {
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => "method_compat", ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => "method_compat",
ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => "type_compat", ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => "type_compat",

View file

@ -137,7 +137,7 @@ impl InferenceDiagnosticsParentData {
} }
impl IntoDiagArg for UnderspecifiedArgKind { impl IntoDiagArg for UnderspecifiedArgKind {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
let kind = match self { let kind = match self {
Self::Type { .. } => "type", Self::Type { .. } => "type",
Self::Const { is_parameter: true } => "const_with_param", Self::Const { is_parameter: true } => "const_with_param",

View file

@ -31,7 +31,7 @@ impl<'tcx, T> IntoDiagArg for Highlighted<'tcx, T>
where where
T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>, T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>,
{ {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
rustc_errors::DiagArgValue::Str(self.to_string().into()) rustc_errors::DiagArgValue::Str(self.to_string().into())
} }
} }

View file

@ -784,10 +784,10 @@ pub enum TyOrSig<'tcx> {
} }
impl IntoDiagArg for TyOrSig<'_> { impl IntoDiagArg for TyOrSig<'_> {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
match self { match self {
TyOrSig::Ty(ty) => ty.into_diag_arg(), TyOrSig::Ty(ty) => ty.into_diag_arg(path),
TyOrSig::ClosureSig(sig) => sig.into_diag_arg(), TyOrSig::ClosureSig(sig) => sig.into_diag_arg(path),
} }
} }
} }

View file

@ -105,7 +105,7 @@ pub enum SuffixKind {
} }
impl IntoDiagArg for PrefixKind { impl IntoDiagArg for PrefixKind {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
let kind = match self { let kind = match self {
Self::Empty => "empty", Self::Empty => "empty",
Self::RefValidFor => "ref_valid_for", Self::RefValidFor => "ref_valid_for",
@ -127,7 +127,7 @@ impl IntoDiagArg for PrefixKind {
} }
impl IntoDiagArg for SuffixKind { impl IntoDiagArg for SuffixKind {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue { fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
let kind = match self { let kind = match self {
Self::Empty => "empty", Self::Empty => "empty",
Self::Continues => "continues", Self::Continues => "continues",

View file

@ -0,0 +1,13 @@
//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
// The regex below normalizes the long type file name to make it suitable for compare-modes.
//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
type A = (i32, i32, i32, i32);
type B = (A, A, A, A);
type C = (B, B, B, B);
type D = (C, C, C, C);
fn foo(x: D) { //~ `x` has type `(...
x(); //~ ERROR expected function, found `(...
}
fn main() {}

View file

@ -0,0 +1,16 @@
error[E0618]: expected function, found `(..., ..., ..., ...)`
--> $DIR/long-E0618.rs:10:5
|
LL | fn foo(x: D) {
| - `x` has type `(..., ..., ..., ...)`
LL | x();
| ^--
| |
| call expression requires function
|
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
= note: consider using `--verbose` to print the full type name to the console
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0618`.