Rework "long type names" printing logic
Make it so more type-system types can be printed in a shortened version (like `Predicate`s). Centralize printing the information about the "full type name path". Make the "long type path" for the file where long types are written part of `Diag`, so that it becomes easier to keep track of it, and ensure it will always will be printed out last in the diagnostic by making its addition to the output implicit. Tweak the shortening of types in "expected/found" labels. Remove dead file `note.rs`.
This commit is contained in:
parent
7f36543a48
commit
0751e9036a
43 changed files with 332 additions and 741 deletions
|
@ -92,9 +92,6 @@ borrowck_lifetime_constraints_error =
|
||||||
borrowck_limitations_implies_static =
|
borrowck_limitations_implies_static =
|
||||||
due to current limitations in the borrow checker, this implies a `'static` lifetime
|
due to current limitations in the borrow checker, this implies a `'static` lifetime
|
||||||
|
|
||||||
borrowck_long_type_consider_verbose = consider using `--verbose` to print the full type name to the console
|
|
||||||
borrowck_long_type_full_path = the full type name has been written to '{$path}'
|
|
||||||
|
|
||||||
borrowck_move_closure_suggestion =
|
borrowck_move_closure_suggestion =
|
||||||
consider adding 'move' keyword before the nested closure
|
consider adding 'move' keyword before the nested closure
|
||||||
|
|
||||||
|
|
|
@ -289,8 +289,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
None => "value".to_owned(),
|
None => "value".to_owned(),
|
||||||
};
|
};
|
||||||
if needs_note {
|
if needs_note {
|
||||||
let mut path = None;
|
let ty = self.infcx.tcx.short_string(ty, err.long_ty_path());
|
||||||
let ty = self.infcx.tcx.short_ty_string(ty, &mut 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 {
|
||||||
|
@ -306,11 +305,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
place: ¬e_msg,
|
place: ¬e_msg,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
if let Some(path) = path {
|
|
||||||
err.subdiagnostic(crate::session_diagnostics::LongTypePath {
|
|
||||||
path: path.display().to_string(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let UseSpans::FnSelfUse {
|
if let UseSpans::FnSelfUse {
|
||||||
|
|
|
@ -596,19 +596,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||||
self.suggest_cloning(err, place_ty, expr, None);
|
self.suggest_cloning(err, place_ty, expr, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut path = None;
|
let ty = self.infcx.tcx.short_string(place_ty, err.long_ty_path());
|
||||||
let ty = self.infcx.tcx.short_ty_string(place_ty, &mut 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: &place_desc,
|
place: &place_desc,
|
||||||
span,
|
span,
|
||||||
});
|
});
|
||||||
if let Some(path) = path {
|
|
||||||
err.subdiagnostic(crate::session_diagnostics::LongTypePath {
|
|
||||||
path: path.display().to_string(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
binds_to.sort();
|
binds_to.sort();
|
||||||
binds_to.dedup();
|
binds_to.dedup();
|
||||||
|
@ -635,19 +629,13 @@ 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 mut path = None;
|
let ty = self.infcx.tcx.short_string(place_ty, err.long_ty_path());
|
||||||
let ty = self.infcx.tcx.short_ty_string(place_ty, &mut 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: &place_desc,
|
place: &place_desc,
|
||||||
span: use_span,
|
span: use_span,
|
||||||
});
|
});
|
||||||
if let Some(path) = path {
|
|
||||||
err.subdiagnostic(crate::session_diagnostics::LongTypePath {
|
|
||||||
path: path.display().to_string(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
use_spans.args_subdiag(err, |args_span| {
|
use_spans.args_subdiag(err, |args_span| {
|
||||||
crate::session_diagnostics::CaptureArgLabel::MoveOutPlace {
|
crate::session_diagnostics::CaptureArgLabel::MoveOutPlace {
|
||||||
|
@ -845,19 +833,13 @@ 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 mut path = None;
|
let ty = self.infcx.tcx.short_string(bind_to.ty, err.long_ty_path());
|
||||||
let ty = self.infcx.tcx.short_ty_string(bind_to.ty, &mut 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: place_desc,
|
place: place_desc,
|
||||||
span: binding_span,
|
span: binding_span,
|
||||||
});
|
});
|
||||||
if let Some(path) = path {
|
|
||||||
err.subdiagnostic(crate::session_diagnostics::LongTypePath {
|
|
||||||
path: path.display().to_string(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -458,13 +458,6 @@ pub(crate) enum OnClosureNote<'a> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
|
||||||
#[note(borrowck_long_type_full_path)]
|
|
||||||
#[note(borrowck_long_type_consider_verbose)]
|
|
||||||
pub(crate) struct LongTypePath {
|
|
||||||
pub(crate) path: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic)]
|
||||||
pub(crate) enum TypeNoCopy<'a> {
|
pub(crate) enum TypeNoCopy<'a> {
|
||||||
#[label(borrowck_ty_no_impl_copy)]
|
#[label(borrowck_ty_no_impl_copy)]
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::hash::{Hash, Hasher};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::panic;
|
use std::panic;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::thread::panicking;
|
use std::thread::panicking;
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
|
@ -301,6 +302,7 @@ pub struct DiagInner {
|
||||||
|
|
||||||
pub is_lint: Option<IsLint>,
|
pub is_lint: Option<IsLint>,
|
||||||
|
|
||||||
|
pub long_ty_path: Option<PathBuf>,
|
||||||
/// With `-Ztrack_diagnostics` enabled,
|
/// With `-Ztrack_diagnostics` enabled,
|
||||||
/// we print where in rustc this error was emitted.
|
/// we print where in rustc this error was emitted.
|
||||||
pub(crate) emitted_at: DiagLocation,
|
pub(crate) emitted_at: DiagLocation,
|
||||||
|
@ -324,6 +326,7 @@ impl DiagInner {
|
||||||
args: Default::default(),
|
args: Default::default(),
|
||||||
sort_span: DUMMY_SP,
|
sort_span: DUMMY_SP,
|
||||||
is_lint: None,
|
is_lint: None,
|
||||||
|
long_ty_path: None,
|
||||||
emitted_at: DiagLocation::caller(),
|
emitted_at: DiagLocation::caller(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1293,9 +1296,37 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
||||||
/// `cancel`, etc. Afterwards, `drop` is the only code that will be run on
|
/// `cancel`, etc. Afterwards, `drop` is the only code that will be run on
|
||||||
/// `self`.
|
/// `self`.
|
||||||
fn take_diag(&mut self) -> DiagInner {
|
fn take_diag(&mut self) -> DiagInner {
|
||||||
|
if let Some(path) = &self.long_ty_path {
|
||||||
|
self.note(format!(
|
||||||
|
"the full name for the type has been written to '{}'",
|
||||||
|
path.display()
|
||||||
|
));
|
||||||
|
self.note("consider using `--verbose` to print the full type name to the console");
|
||||||
|
}
|
||||||
Box::into_inner(self.diag.take().unwrap())
|
Box::into_inner(self.diag.take().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This method allows us to access the path of the file where "long types" are written to.
|
||||||
|
///
|
||||||
|
/// When calling `Diag::emit`, as part of that we will check if a `long_ty_path` has been set,
|
||||||
|
/// and if it has been then we add a note mentioning the file where the "long types" were
|
||||||
|
/// written to.
|
||||||
|
///
|
||||||
|
/// When calling `tcx.short_string()` after a `Diag` is constructed, the preferred way of doing
|
||||||
|
/// so is `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 where we wrote the file to is only printed once at most, *and* it makes it much harder
|
||||||
|
/// to forget to set it.
|
||||||
|
///
|
||||||
|
/// If the diagnostic hasn't been created before a "short ty string" is created, then you should
|
||||||
|
/// ensure that this method is called to set it `*diag.long_ty_path() = path`.
|
||||||
|
///
|
||||||
|
/// As a rule of thumb, if you see or add at least one `tcx.short_string()` call anywhere, in a
|
||||||
|
/// scope, `diag.long_ty_path()` should be called once somewhere close by.
|
||||||
|
pub fn long_ty_path(&mut self) -> &mut Option<PathBuf> {
|
||||||
|
&mut self.long_ty_path
|
||||||
|
}
|
||||||
|
|
||||||
/// Most `emit_producing_guarantee` functions use this as a starting point.
|
/// Most `emit_producing_guarantee` functions use this as a starting point.
|
||||||
fn emit_producing_nothing(mut self) {
|
fn emit_producing_nothing(mut self) {
|
||||||
let diag = self.take_diag();
|
let diag = self.take_diag();
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
use core::ops::ControlFlow;
|
use core::ops::ControlFlow;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use hir::Expr;
|
use hir::Expr;
|
||||||
use rustc_ast::ast::Mutability;
|
use rustc_ast::ast::Mutability;
|
||||||
|
@ -362,14 +363,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
fn suggest_missing_writer(&self, rcvr_ty: Ty<'tcx>, rcvr_expr: &hir::Expr<'tcx>) -> Diag<'_> {
|
fn suggest_missing_writer(&self, rcvr_ty: Ty<'tcx>, rcvr_expr: &hir::Expr<'tcx>) -> Diag<'_> {
|
||||||
let mut file = None;
|
let mut file = None;
|
||||||
let ty_str = self.tcx.short_ty_string(rcvr_ty, &mut file);
|
|
||||||
let mut err = struct_span_code_err!(
|
let mut err = struct_span_code_err!(
|
||||||
self.dcx(),
|
self.dcx(),
|
||||||
rcvr_expr.span,
|
rcvr_expr.span,
|
||||||
E0599,
|
E0599,
|
||||||
"cannot write into `{}`",
|
"cannot write into `{}`",
|
||||||
ty_str
|
self.tcx.short_string(rcvr_ty, &mut file),
|
||||||
);
|
);
|
||||||
|
*err.long_ty_path() = file;
|
||||||
err.span_note(
|
err.span_note(
|
||||||
rcvr_expr.span,
|
rcvr_expr.span,
|
||||||
"must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
|
"must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
|
||||||
|
@ -380,11 +381,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
"a writer is needed before this format string",
|
"a writer is needed before this format string",
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
if let Some(file) = file {
|
|
||||||
err.note(format!("the full type name has been written to '{}'", file.display()));
|
|
||||||
err.note("consider using `--verbose` to print the full type name to the console");
|
|
||||||
}
|
|
||||||
|
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,7 +591,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
(predicates.to_string(), with_forced_trimmed_paths!(predicates.to_string()))
|
(predicates.to_string(), with_forced_trimmed_paths!(predicates.to_string()))
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
tcx.short_ty_string(rcvr_ty, &mut ty_file),
|
tcx.short_string(rcvr_ty, &mut ty_file),
|
||||||
with_forced_trimmed_paths!(rcvr_ty.to_string()),
|
with_forced_trimmed_paths!(rcvr_ty.to_string()),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -624,6 +620,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
span,
|
span,
|
||||||
item_name,
|
item_name,
|
||||||
&short_ty_str,
|
&short_ty_str,
|
||||||
|
&mut ty_file,
|
||||||
) {
|
) {
|
||||||
return guar;
|
return guar;
|
||||||
}
|
}
|
||||||
|
@ -635,6 +632,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
item_kind,
|
item_kind,
|
||||||
item_name,
|
item_name,
|
||||||
&short_ty_str,
|
&short_ty_str,
|
||||||
|
&mut ty_file,
|
||||||
) {
|
) {
|
||||||
return guar;
|
return guar;
|
||||||
}
|
}
|
||||||
|
@ -728,10 +726,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
ty_str = short_ty_str;
|
ty_str = short_ty_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(file) = ty_file {
|
|
||||||
err.note(format!("the full type name has been written to '{}'", file.display(),));
|
|
||||||
err.note("consider using `--verbose` to print the full type name to the console");
|
|
||||||
}
|
|
||||||
if rcvr_ty.references_error() {
|
if rcvr_ty.references_error() {
|
||||||
err.downgrade_to_delayed_bug();
|
err.downgrade_to_delayed_bug();
|
||||||
}
|
}
|
||||||
|
@ -1314,7 +1308,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
bound_list.into_iter().map(|(_, path)| path).collect::<Vec<_>>().join("\n");
|
bound_list.into_iter().map(|(_, path)| path).collect::<Vec<_>>().join("\n");
|
||||||
let actual_prefix = rcvr_ty.prefix_string(self.tcx);
|
let actual_prefix = rcvr_ty.prefix_string(self.tcx);
|
||||||
info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
|
info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
|
||||||
let mut long_ty_file = None;
|
|
||||||
let (primary_message, label, notes) = if unimplemented_traits.len() == 1
|
let (primary_message, label, notes) = if unimplemented_traits.len() == 1
|
||||||
&& unimplemented_traits_only
|
&& unimplemented_traits_only
|
||||||
{
|
{
|
||||||
|
@ -1329,7 +1322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
let OnUnimplementedNote { message, label, notes, .. } = self
|
let OnUnimplementedNote { message, label, notes, .. } = self
|
||||||
.err_ctxt()
|
.err_ctxt()
|
||||||
.on_unimplemented_note(trait_ref, &obligation, &mut long_ty_file);
|
.on_unimplemented_note(trait_ref, &obligation, &mut ty_file);
|
||||||
(message, label, notes)
|
(message, label, notes)
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -1343,15 +1336,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
err.primary_message(primary_message);
|
err.primary_message(primary_message);
|
||||||
if let Some(file) = long_ty_file {
|
|
||||||
err.note(format!(
|
|
||||||
"the full name for the type has been written to '{}'",
|
|
||||||
file.display(),
|
|
||||||
));
|
|
||||||
err.note(
|
|
||||||
"consider using `--verbose` to print the full type name to the console",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if let Some(label) = label {
|
if let Some(label) = label {
|
||||||
custom_span_label = true;
|
custom_span_label = true;
|
||||||
err.span_label(span, label);
|
err.span_label(span, label);
|
||||||
|
@ -2403,6 +2387,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
item_name: Ident,
|
item_name: Ident,
|
||||||
ty_str: &str,
|
ty_str: &str,
|
||||||
|
long_ty_path: &mut Option<PathBuf>,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
if let SelfSource::MethodCall(expr) = source {
|
if let SelfSource::MethodCall(expr) = source {
|
||||||
for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
|
for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
|
||||||
|
@ -2460,7 +2445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
if pick.is_ok() {
|
if pick.is_ok() {
|
||||||
let range_span = parent_expr.span.with_hi(expr.span.hi());
|
let range_span = parent_expr.span.with_hi(expr.span.hi());
|
||||||
return Err(self.dcx().emit_err(errors::MissingParenthesesInRange {
|
let mut err = self.dcx().create_err(errors::MissingParenthesesInRange {
|
||||||
span,
|
span,
|
||||||
ty_str: ty_str.to_string(),
|
ty_str: ty_str.to_string(),
|
||||||
method_name: item_name.as_str().to_string(),
|
method_name: item_name.as_str().to_string(),
|
||||||
|
@ -2469,7 +2454,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
left: range_span.shrink_to_lo(),
|
left: range_span.shrink_to_lo(),
|
||||||
right: range_span.shrink_to_hi(),
|
right: range_span.shrink_to_hi(),
|
||||||
}),
|
}),
|
||||||
}));
|
});
|
||||||
|
*err.long_ty_path() = long_ty_path.take();
|
||||||
|
return Err(err.emit());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2486,6 +2473,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
item_kind: &str,
|
item_kind: &str,
|
||||||
item_name: Ident,
|
item_name: Ident,
|
||||||
ty_str: &str,
|
ty_str: &str,
|
||||||
|
long_ty_path: &mut Option<PathBuf>,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let found_candidate = all_traits(self.tcx)
|
let found_candidate = all_traits(self.tcx)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -2526,6 +2514,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
item_name,
|
item_name,
|
||||||
ty_str
|
ty_str
|
||||||
);
|
);
|
||||||
|
*err.long_ty_path() = long_ty_path.take();
|
||||||
let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
|
let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ExprKind::Lit(lit) => {
|
ExprKind::Lit(lit) => {
|
||||||
|
|
|
@ -10,8 +10,8 @@ use rustc_hir::def::{CtorOf, DefKind};
|
||||||
use rustc_macros::extension;
|
use rustc_macros::extension;
|
||||||
pub use rustc_type_ir::error::ExpectedFound;
|
pub use rustc_type_ir::error::ExpectedFound;
|
||||||
|
|
||||||
use crate::ty::print::{FmtPrinter, PrettyPrinter, with_forced_trimmed_paths};
|
use crate::ty::print::{FmtPrinter, Print, with_forced_trimmed_paths};
|
||||||
use crate::ty::{self, Ty, TyCtxt};
|
use crate::ty::{self, Lift, Ty, TyCtxt};
|
||||||
|
|
||||||
pub type TypeError<'tcx> = rustc_type_ir::error::TypeError<TyCtxt<'tcx>>;
|
pub type TypeError<'tcx> = rustc_type_ir::error::TypeError<TyCtxt<'tcx>>;
|
||||||
|
|
||||||
|
@ -159,8 +159,8 @@ impl<'tcx> Ty<'tcx> {
|
||||||
ty::Error(_) => "type error".into(),
|
ty::Error(_) => "type error".into(),
|
||||||
_ => {
|
_ => {
|
||||||
let width = tcx.sess.diagnostic_width();
|
let width = tcx.sess.diagnostic_width();
|
||||||
let length_limit = std::cmp::max(width / 4, 15);
|
let length_limit = std::cmp::max(width / 4, 40);
|
||||||
format!("`{}`", tcx.ty_string_with_limit(self, length_limit)).into()
|
format!("`{}`", tcx.string_with_limit(self, length_limit)).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,10 +213,14 @@ impl<'tcx> Ty<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TyCtxt<'tcx> {
|
impl<'tcx> TyCtxt<'tcx> {
|
||||||
pub fn ty_string_with_limit(self, ty: Ty<'tcx>, length_limit: usize) -> String {
|
pub fn string_with_limit<'a, T>(self, p: T, length_limit: usize) -> String
|
||||||
|
where
|
||||||
|
T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift<TyCtxt<'tcx>> + Copy,
|
||||||
|
<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| {
|
||||||
cx.pretty_print_type(ty)
|
self.lift(p).expect("could not lift for printing").print(cx)
|
||||||
})
|
})
|
||||||
.expect("could not write to `String`");
|
.expect("could not write to `String`");
|
||||||
if regular.len() <= length_limit {
|
if regular.len() <= length_limit {
|
||||||
|
@ -231,7 +235,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
hir::def::Namespace::TypeNS,
|
hir::def::Namespace::TypeNS,
|
||||||
rustc_session::Limit(type_limit),
|
rustc_session::Limit(type_limit),
|
||||||
);
|
);
|
||||||
cx.pretty_print_type(ty).expect("could not write to `String`");
|
self.lift(p)
|
||||||
|
.expect("could not lift for printing")
|
||||||
|
.print(&mut cx)
|
||||||
|
.expect("could not print type");
|
||||||
cx.into_buffer()
|
cx.into_buffer()
|
||||||
});
|
});
|
||||||
if short.len() <= length_limit || type_limit == 0 {
|
if short.len() <= length_limit || type_limit == 0 {
|
||||||
|
@ -242,9 +249,17 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
short
|
short
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn short_ty_string(self, ty: Ty<'tcx>, path: &mut Option<PathBuf>) -> String {
|
/// When calling this after a `Diag` is constructed, the preferred way of doing so is
|
||||||
|
/// `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
|
||||||
|
/// where we wrote the file to is only printed once.
|
||||||
|
pub fn short_string<'a, T>(self, p: T, path: &mut Option<PathBuf>) -> String
|
||||||
|
where
|
||||||
|
T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift<TyCtxt<'tcx>> + Copy + Hash,
|
||||||
|
<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| {
|
||||||
cx.pretty_print_type(ty)
|
self.lift(p).expect("could not lift for printing").print(cx)
|
||||||
})
|
})
|
||||||
.expect("could not write to `String`");
|
.expect("could not write to `String`");
|
||||||
|
|
||||||
|
@ -257,13 +272,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
if regular.len() <= width * 2 / 3 {
|
if regular.len() <= width * 2 / 3 {
|
||||||
return regular;
|
return regular;
|
||||||
}
|
}
|
||||||
let short = self.ty_string_with_limit(ty, length_limit);
|
let short = self.string_with_limit(p, length_limit);
|
||||||
if regular == short {
|
if regular == short {
|
||||||
return regular;
|
return regular;
|
||||||
}
|
}
|
||||||
// Ensure we create an unique file for the type passed in when we create a file.
|
// Ensure we create an unique file for the type passed in when we create a file.
|
||||||
let mut s = DefaultHasher::new();
|
let mut s = DefaultHasher::new();
|
||||||
ty.hash(&mut s);
|
p.hash(&mut s);
|
||||||
let hash = s.finish();
|
let hash = s.finish();
|
||||||
*path = Some(path.take().unwrap_or_else(|| {
|
*path = Some(path.take().unwrap_or_else(|| {
|
||||||
self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None)
|
self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None)
|
||||||
|
|
|
@ -105,6 +105,10 @@ pub trait Printer<'tcx>: Sized {
|
||||||
args: &[GenericArg<'tcx>],
|
args: &[GenericArg<'tcx>],
|
||||||
) -> Result<(), PrintError>;
|
) -> Result<(), PrintError>;
|
||||||
|
|
||||||
|
fn should_truncate(&mut self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
// Defaults (should not be overridden):
|
// Defaults (should not be overridden):
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
|
|
|
@ -865,7 +865,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
p!(write("{{"));
|
p!(write("{{"));
|
||||||
if !self.tcx().sess.verbose_internals() {
|
if !self.tcx().sess.verbose_internals() {
|
||||||
p!("coroutine witness");
|
p!("coroutine witness");
|
||||||
// FIXME(eddyb) should use `def_span`.
|
|
||||||
if let Some(did) = did.as_local() {
|
if let Some(did) = did.as_local() {
|
||||||
let span = self.tcx().def_span(did);
|
let span = self.tcx().def_span(did);
|
||||||
p!(write(
|
p!(write(
|
||||||
|
@ -887,26 +886,30 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
p!(write("{{"));
|
p!(write("{{"));
|
||||||
if !self.should_print_verbose() {
|
if !self.should_print_verbose() {
|
||||||
p!(write("closure"));
|
p!(write("closure"));
|
||||||
// FIXME(eddyb) should use `def_span`.
|
if self.should_truncate() {
|
||||||
if let Some(did) = did.as_local() {
|
write!(self, "@...}}")?;
|
||||||
if self.tcx().sess.opts.unstable_opts.span_free_formats {
|
return Ok(());
|
||||||
p!("@", print_def_path(did.to_def_id(), args));
|
|
||||||
} else {
|
|
||||||
let span = self.tcx().def_span(did);
|
|
||||||
let preference = if with_forced_trimmed_paths() {
|
|
||||||
FileNameDisplayPreference::Short
|
|
||||||
} else {
|
|
||||||
FileNameDisplayPreference::Remapped
|
|
||||||
};
|
|
||||||
p!(write(
|
|
||||||
"@{}",
|
|
||||||
// This may end up in stderr diagnostics but it may also be emitted
|
|
||||||
// into MIR. Hence we use the remapped path if available
|
|
||||||
self.tcx().sess.source_map().span_to_string(span, preference)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
p!(write("@"), print_def_path(did, args));
|
if let Some(did) = did.as_local() {
|
||||||
|
if self.tcx().sess.opts.unstable_opts.span_free_formats {
|
||||||
|
p!("@", print_def_path(did.to_def_id(), args));
|
||||||
|
} else {
|
||||||
|
let span = self.tcx().def_span(did);
|
||||||
|
let preference = if with_forced_trimmed_paths() {
|
||||||
|
FileNameDisplayPreference::Short
|
||||||
|
} else {
|
||||||
|
FileNameDisplayPreference::Remapped
|
||||||
|
};
|
||||||
|
p!(write(
|
||||||
|
"@{}",
|
||||||
|
// This may end up in stderr diagnostics but it may also be emitted
|
||||||
|
// into MIR. Hence we use the remapped path if available
|
||||||
|
self.tcx().sess.source_map().span_to_string(span, preference)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p!(write("@"), print_def_path(did, args));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p!(print_def_path(did, args));
|
p!(print_def_path(did, args));
|
||||||
|
@ -942,7 +945,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
"coroutine from coroutine-closure should have CoroutineSource::Closure"
|
"coroutine from coroutine-closure should have CoroutineSource::Closure"
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
// FIXME(eddyb) should use `def_span`.
|
|
||||||
if let Some(did) = did.as_local() {
|
if let Some(did) = did.as_local() {
|
||||||
if self.tcx().sess.opts.unstable_opts.span_free_formats {
|
if self.tcx().sess.opts.unstable_opts.span_free_formats {
|
||||||
p!("@", print_def_path(did.to_def_id(), args));
|
p!("@", print_def_path(did.to_def_id(), args));
|
||||||
|
@ -1994,7 +1996,6 @@ pub struct FmtPrinterData<'a, 'tcx> {
|
||||||
binder_depth: usize,
|
binder_depth: usize,
|
||||||
printed_type_count: usize,
|
printed_type_count: usize,
|
||||||
type_length_limit: Limit,
|
type_length_limit: Limit,
|
||||||
truncated: bool,
|
|
||||||
|
|
||||||
pub region_highlight_mode: RegionHighlightMode<'tcx>,
|
pub region_highlight_mode: RegionHighlightMode<'tcx>,
|
||||||
|
|
||||||
|
@ -2046,7 +2047,6 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
|
||||||
binder_depth: 0,
|
binder_depth: 0,
|
||||||
printed_type_count: 0,
|
printed_type_count: 0,
|
||||||
type_length_limit,
|
type_length_limit,
|
||||||
truncated: false,
|
|
||||||
region_highlight_mode: RegionHighlightMode::default(),
|
region_highlight_mode: RegionHighlightMode::default(),
|
||||||
ty_infer_name_resolver: None,
|
ty_infer_name_resolver: None,
|
||||||
const_infer_name_resolver: None,
|
const_infer_name_resolver: None,
|
||||||
|
@ -2183,16 +2183,49 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
|
fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
|
||||||
if self.type_length_limit.value_within_limit(self.printed_type_count) {
|
match ty.kind() {
|
||||||
self.printed_type_count += 1;
|
ty::Tuple(tys) if tys.len() == 0 && self.should_truncate() => {
|
||||||
self.pretty_print_type(ty)
|
// Don't truncate `()`.
|
||||||
} else {
|
self.printed_type_count += 1;
|
||||||
self.truncated = true;
|
self.pretty_print_type(ty)
|
||||||
write!(self, "...")?;
|
}
|
||||||
Ok(())
|
ty::Adt(..)
|
||||||
|
| ty::Foreign(_)
|
||||||
|
| ty::Pat(..)
|
||||||
|
| ty::RawPtr(..)
|
||||||
|
| ty::Ref(..)
|
||||||
|
| ty::FnDef(..)
|
||||||
|
| ty::FnPtr(..)
|
||||||
|
| ty::UnsafeBinder(..)
|
||||||
|
| ty::Dynamic(..)
|
||||||
|
| ty::Closure(..)
|
||||||
|
| ty::CoroutineClosure(..)
|
||||||
|
| ty::Coroutine(..)
|
||||||
|
| ty::CoroutineWitness(..)
|
||||||
|
| ty::Tuple(_)
|
||||||
|
| ty::Alias(..)
|
||||||
|
| ty::Param(_)
|
||||||
|
| ty::Bound(..)
|
||||||
|
| ty::Placeholder(_)
|
||||||
|
| ty::Error(_)
|
||||||
|
if self.should_truncate() =>
|
||||||
|
{
|
||||||
|
// We only truncate types that we know are likely to be much longer than 3 chars.
|
||||||
|
// There's no point in replacing `i32` or `!`.
|
||||||
|
write!(self, "...")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.printed_type_count += 1;
|
||||||
|
self.pretty_print_type(ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn should_truncate(&mut self) -> bool {
|
||||||
|
!self.type_length_limit.value_within_limit(self.printed_type_count)
|
||||||
|
}
|
||||||
|
|
||||||
fn print_dyn_existential(
|
fn print_dyn_existential(
|
||||||
&mut self,
|
&mut self,
|
||||||
predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||||
|
@ -2942,7 +2975,7 @@ impl<'tcx> ty::TraitPredicate<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
|
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)]
|
||||||
pub struct TraitPredPrintWithBoundConstness<'tcx>(
|
pub struct TraitPredPrintWithBoundConstness<'tcx>(
|
||||||
ty::TraitPredicate<'tcx>,
|
ty::TraitPredicate<'tcx>,
|
||||||
Option<ty::BoundConstness>,
|
Option<ty::BoundConstness>,
|
||||||
|
|
|
@ -25,8 +25,6 @@ mir_build_borrow_of_moved_value = borrow of moved value
|
||||||
.occurs_because_label = move occurs because `{$name}` has type `{$ty}`, which does not implement the `Copy` trait
|
.occurs_because_label = move occurs because `{$name}` has type `{$ty}`, which does not implement the `Copy` trait
|
||||||
.value_borrowed_label = value borrowed here after move
|
.value_borrowed_label = value borrowed here after move
|
||||||
.suggestion = borrow this binding in the pattern to avoid moving the value
|
.suggestion = borrow this binding in the pattern to avoid moving the value
|
||||||
.full_type_name = the full type name has been written to '{$path}'
|
|
||||||
.consider_verbose = consider using `--verbose` to print the full type name to the console
|
|
||||||
|
|
||||||
mir_build_call_to_deprecated_safe_fn_requires_unsafe =
|
mir_build_call_to_deprecated_safe_fn_requires_unsafe =
|
||||||
call to deprecated safe function `{$function}` is unsafe and requires unsafe block
|
call to deprecated safe function `{$function}` is unsafe and requires unsafe block
|
||||||
|
|
|
@ -801,10 +801,6 @@ pub(crate) struct BorrowOfMovedValue {
|
||||||
pub(crate) ty: String,
|
pub(crate) ty: String,
|
||||||
#[suggestion(code = "ref ", applicability = "machine-applicable")]
|
#[suggestion(code = "ref ", applicability = "machine-applicable")]
|
||||||
pub(crate) suggest_borrowing: Option<Span>,
|
pub(crate) suggest_borrowing: Option<Span>,
|
||||||
#[note(mir_build_full_type_name)]
|
|
||||||
#[note(mir_build_consider_verbose)]
|
|
||||||
pub(crate) has_path: bool,
|
|
||||||
pub(crate) path: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
|
|
@ -796,16 +796,16 @@ 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;
|
let mut path = None;
|
||||||
let ty = cx.tcx.short_ty_string(ty, &mut path);
|
let ty = cx.tcx.short_string(ty, &mut path);
|
||||||
sess.dcx().emit_err(BorrowOfMovedValue {
|
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()),
|
||||||
has_path: path.is_some(),
|
|
||||||
path: path.map(|p| p.display().to_string()).unwrap_or_default(),
|
|
||||||
});
|
});
|
||||||
|
*err.long_ty_path() = path;
|
||||||
|
err.emit();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -435,7 +435,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
|
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
|
||||||
terr: TypeError<'tcx>,
|
terr: TypeError<'tcx>,
|
||||||
param_env: Option<ParamEnv<'tcx>>,
|
param_env: Option<ParamEnv<'tcx>>,
|
||||||
path: &mut Option<PathBuf>,
|
|
||||||
) {
|
) {
|
||||||
match *cause.code() {
|
match *cause.code() {
|
||||||
ObligationCauseCode::Pattern {
|
ObligationCauseCode::Pattern {
|
||||||
|
@ -458,7 +457,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
format!("this is an iterator with items of type `{}`", args.type_at(0)),
|
format!("this is an iterator with items of type `{}`", args.type_at(0)),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let expected_ty = self.tcx.short_ty_string(expected_ty, path);
|
let expected_ty = self.tcx.short_string(expected_ty, err.long_ty_path());
|
||||||
err.span_label(span, format!("this expression has type `{expected_ty}`"));
|
err.span_label(span, format!("this expression has type `{expected_ty}`"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1545,7 +1544,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
(false, Mismatch::Fixed("existential projection"))
|
(false, Mismatch::Fixed("existential projection"))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let Some(vals) = self.values_str(values, cause) else {
|
let Some(vals) = self.values_str(values, cause, diag.long_ty_path()) else {
|
||||||
// Derived error. Cancel the emitter.
|
// Derived error. Cancel the emitter.
|
||||||
// NOTE(eddyb) this was `.cancel()`, but `diag`
|
// NOTE(eddyb) this was `.cancel()`, but `diag`
|
||||||
// is borrowed, so we can't fully defuse it.
|
// is borrowed, so we can't fully defuse it.
|
||||||
|
@ -1600,9 +1599,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut path = None;
|
if let Some((expected, found)) = expected_found {
|
||||||
if let Some((expected, found, p)) = expected_found {
|
|
||||||
path = p;
|
|
||||||
let (expected_label, found_label, exp_found) = match exp_found {
|
let (expected_label, found_label, exp_found) = match exp_found {
|
||||||
Mismatch::Variable(ef) => (
|
Mismatch::Variable(ef) => (
|
||||||
ef.expected.prefix_string(self.tcx),
|
ef.expected.prefix_string(self.tcx),
|
||||||
|
@ -1878,11 +1875,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
// It reads better to have the error origin as the final
|
// It reads better to have the error origin as the final
|
||||||
// thing.
|
// thing.
|
||||||
self.note_error_origin(diag, cause, exp_found, terr, param_env, &mut path);
|
self.note_error_origin(diag, cause, exp_found, terr, param_env);
|
||||||
if let Some(path) = path {
|
|
||||||
diag.note(format!("the full type name has been written to '{}'", path.display()));
|
|
||||||
diag.note("consider using `--verbose` to print the full type name to the console");
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!(?diag);
|
debug!(?diag);
|
||||||
}
|
}
|
||||||
|
@ -1891,6 +1884,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
trace: &TypeTrace<'tcx>,
|
trace: &TypeTrace<'tcx>,
|
||||||
terr: TypeError<'tcx>,
|
terr: TypeError<'tcx>,
|
||||||
|
path: &mut Option<PathBuf>,
|
||||||
) -> Vec<TypeErrorAdditionalDiags> {
|
) -> Vec<TypeErrorAdditionalDiags> {
|
||||||
let mut suggestions = Vec::new();
|
let mut suggestions = Vec::new();
|
||||||
let span = trace.cause.span;
|
let span = trace.cause.span;
|
||||||
|
@ -1969,7 +1963,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
| ObligationCauseCode::BlockTailExpression(.., source)) = code
|
| ObligationCauseCode::BlockTailExpression(.., source)) = code
|
||||||
&& let hir::MatchSource::TryDesugar(_) = source
|
&& let hir::MatchSource::TryDesugar(_) = source
|
||||||
&& let Some((expected_ty, found_ty, _)) = self.values_str(trace.values, &trace.cause)
|
&& let Some((expected_ty, found_ty)) = self.values_str(trace.values, &trace.cause, path)
|
||||||
{
|
{
|
||||||
suggestions.push(TypeErrorAdditionalDiags::TryCannotConvert {
|
suggestions.push(TypeErrorAdditionalDiags::TryCannotConvert {
|
||||||
found: found_ty.content(),
|
found: found_ty.content(),
|
||||||
|
@ -2048,12 +2042,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
|
debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
|
||||||
|
|
||||||
let span = trace.cause.span;
|
let span = trace.cause.span;
|
||||||
|
let mut path = None;
|
||||||
let failure_code = trace.cause.as_failure_code_diag(
|
let failure_code = trace.cause.as_failure_code_diag(
|
||||||
terr,
|
terr,
|
||||||
span,
|
span,
|
||||||
self.type_error_additional_suggestions(&trace, terr),
|
self.type_error_additional_suggestions(&trace, terr, &mut path),
|
||||||
);
|
);
|
||||||
let mut diag = self.dcx().create_err(failure_code);
|
let mut diag = self.dcx().create_err(failure_code);
|
||||||
|
*diag.long_ty_path() = path;
|
||||||
self.note_type_err(
|
self.note_type_err(
|
||||||
&mut diag,
|
&mut diag,
|
||||||
&trace.cause,
|
&trace.cause,
|
||||||
|
@ -2098,10 +2094,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
values: ValuePairs<'tcx>,
|
values: ValuePairs<'tcx>,
|
||||||
cause: &ObligationCause<'tcx>,
|
cause: &ObligationCause<'tcx>,
|
||||||
) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
|
file: &mut Option<PathBuf>,
|
||||||
|
) -> Option<(DiagStyledString, DiagStyledString)> {
|
||||||
match values {
|
match values {
|
||||||
ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found),
|
ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found),
|
||||||
ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found),
|
ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found, file),
|
||||||
ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found),
|
ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found),
|
||||||
ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
|
ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
|
||||||
ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
|
ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
|
||||||
|
@ -2111,7 +2108,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
found: exp_found.found.print_trait_sugared(),
|
found: exp_found.found.print_trait_sugared(),
|
||||||
};
|
};
|
||||||
match self.expected_found_str(pretty_exp_found) {
|
match self.expected_found_str(pretty_exp_found) {
|
||||||
Some((expected, found, _)) if expected == found => {
|
Some((expected, found)) if expected == found => {
|
||||||
self.expected_found_str(exp_found)
|
self.expected_found_str(exp_found)
|
||||||
}
|
}
|
||||||
ret => ret,
|
ret => ret,
|
||||||
|
@ -2133,9 +2130,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
(None, None)
|
(None, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (exp, fnd) =
|
Some(self.cmp_fn_sig(&exp_found.expected, fn_def1, &exp_found.found, fn_def2))
|
||||||
self.cmp_fn_sig(&exp_found.expected, fn_def1, &exp_found.found, fn_def2);
|
|
||||||
Some((exp, fnd, None))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2143,7 +2138,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
fn expected_found_str_term(
|
fn expected_found_str_term(
|
||||||
&self,
|
&self,
|
||||||
exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
|
exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
|
||||||
) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
|
path: &mut Option<PathBuf>,
|
||||||
|
) -> Option<(DiagStyledString, DiagStyledString)> {
|
||||||
let exp_found = self.resolve_vars_if_possible(exp_found);
|
let exp_found = self.resolve_vars_if_possible(exp_found);
|
||||||
if exp_found.references_error() {
|
if exp_found.references_error() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -2158,21 +2154,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
let len = self.tcx.sess().diagnostic_width() + 40;
|
let len = self.tcx.sess().diagnostic_width() + 40;
|
||||||
let exp_s = exp.content();
|
let exp_s = exp.content();
|
||||||
let fnd_s = fnd.content();
|
let fnd_s = fnd.content();
|
||||||
let mut path = None;
|
|
||||||
if exp_s.len() > len {
|
if exp_s.len() > len {
|
||||||
let exp_s = self.tcx.short_ty_string(expected, &mut path);
|
let exp_s = self.tcx.short_string(expected, path);
|
||||||
exp = DiagStyledString::highlighted(exp_s);
|
exp = DiagStyledString::highlighted(exp_s);
|
||||||
}
|
}
|
||||||
if fnd_s.len() > len {
|
if fnd_s.len() > len {
|
||||||
let fnd_s = self.tcx.short_ty_string(found, &mut path);
|
let fnd_s = self.tcx.short_string(found, path);
|
||||||
fnd = DiagStyledString::highlighted(fnd_s);
|
fnd = DiagStyledString::highlighted(fnd_s);
|
||||||
}
|
}
|
||||||
(exp, fnd, path)
|
(exp, fnd)
|
||||||
}
|
}
|
||||||
_ => (
|
_ => (
|
||||||
DiagStyledString::highlighted(exp_found.expected.to_string()),
|
DiagStyledString::highlighted(exp_found.expected.to_string()),
|
||||||
DiagStyledString::highlighted(exp_found.found.to_string()),
|
DiagStyledString::highlighted(exp_found.found.to_string()),
|
||||||
None,
|
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2181,7 +2175,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
fn expected_found_str<T: fmt::Display + TypeFoldable<TyCtxt<'tcx>>>(
|
fn expected_found_str<T: fmt::Display + TypeFoldable<TyCtxt<'tcx>>>(
|
||||||
&self,
|
&self,
|
||||||
exp_found: ty::error::ExpectedFound<T>,
|
exp_found: ty::error::ExpectedFound<T>,
|
||||||
) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
|
) -> Option<(DiagStyledString, DiagStyledString)> {
|
||||||
let exp_found = self.resolve_vars_if_possible(exp_found);
|
let exp_found = self.resolve_vars_if_possible(exp_found);
|
||||||
if exp_found.references_error() {
|
if exp_found.references_error() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -2190,7 +2184,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
Some((
|
Some((
|
||||||
DiagStyledString::highlighted(exp_found.expected.to_string()),
|
DiagStyledString::highlighted(exp_found.expected.to_string()),
|
||||||
DiagStyledString::highlighted(exp_found.found.to_string()),
|
DiagStyledString::highlighted(exp_found.found.to_string()),
|
||||||
None,
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -713,7 +713,7 @@ impl<'tcx> InferSourceKind<'tcx> {
|
||||||
if ty.is_closure() {
|
if ty.is_closure() {
|
||||||
("closure", closure_as_fn_str(infcx, ty), path)
|
("closure", closure_as_fn_str(infcx, ty), path)
|
||||||
} else if !ty.is_ty_or_numeric_infer() {
|
} else if !ty.is_ty_or_numeric_infer() {
|
||||||
("normal", infcx.tcx.short_ty_string(ty, &mut path), path)
|
("normal", infcx.tcx.short_string(ty, &mut path), path)
|
||||||
} else {
|
} else {
|
||||||
("other", String::new(), path)
|
("other", String::new(), path)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,422 +0,0 @@
|
||||||
use rustc_errors::{Diag, Subdiagnostic};
|
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
|
||||||
use rustc_middle::traits::ObligationCauseCode;
|
|
||||||
use rustc_middle::ty::error::TypeError;
|
|
||||||
use rustc_middle::ty::{self, IsSuggestable, Region, Ty};
|
|
||||||
use rustc_span::kw;
|
|
||||||
use tracing::debug;
|
|
||||||
|
|
||||||
use super::ObligationCauseAsDiagArg;
|
|
||||||
use crate::error_reporting::infer::{TypeErrCtxt, note_and_explain_region};
|
|
||||||
use crate::errors::{
|
|
||||||
FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent, RefLongerThanData,
|
|
||||||
RegionOriginNote, WhereClauseSuggestions, note_and_explain,
|
|
||||||
};
|
|
||||||
use crate::fluent_generated as fluent;
|
|
||||||
use crate::infer::{self, SubregionOrigin};
|
|
||||||
|
|
||||||
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|
||||||
pub(super) fn note_region_origin(&self, err: &mut Diag<'_>, origin: &SubregionOrigin<'tcx>) {
|
|
||||||
match *origin {
|
|
||||||
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
|
|
||||||
span: trace.cause.span,
|
|
||||||
requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
|
|
||||||
expected_found: self.values_str(trace.values).map(|(e, f, _)| (e, f)),
|
|
||||||
}
|
|
||||||
.add_to_diag(err),
|
|
||||||
infer::Reborrow(span) => {
|
|
||||||
RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diag(err)
|
|
||||||
}
|
|
||||||
infer::RelateObjectBound(span) => {
|
|
||||||
RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
|
|
||||||
.add_to_diag(err);
|
|
||||||
}
|
|
||||||
infer::ReferenceOutlivesReferent(ty, span) => {
|
|
||||||
RegionOriginNote::WithName {
|
|
||||||
span,
|
|
||||||
msg: fluent::infer_reference_outlives_referent,
|
|
||||||
name: &self.ty_to_string(ty),
|
|
||||||
continues: false,
|
|
||||||
}
|
|
||||||
.add_to_diag(err);
|
|
||||||
}
|
|
||||||
infer::RelateParamBound(span, ty, opt_span) => {
|
|
||||||
RegionOriginNote::WithName {
|
|
||||||
span,
|
|
||||||
msg: fluent::infer_relate_param_bound,
|
|
||||||
name: &self.ty_to_string(ty),
|
|
||||||
continues: opt_span.is_some(),
|
|
||||||
}
|
|
||||||
.add_to_diag(err);
|
|
||||||
if let Some(span) = opt_span {
|
|
||||||
RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
|
|
||||||
.add_to_diag(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
infer::RelateRegionParamBound(span, _) => {
|
|
||||||
RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
|
|
||||||
.add_to_diag(err);
|
|
||||||
}
|
|
||||||
infer::CompareImplItemObligation { span, .. } => {
|
|
||||||
RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
|
|
||||||
.add_to_diag(err);
|
|
||||||
}
|
|
||||||
infer::CheckAssociatedTypeBounds { ref parent, .. } => {
|
|
||||||
self.note_region_origin(err, parent);
|
|
||||||
}
|
|
||||||
infer::AscribeUserTypeProvePredicate(span) => {
|
|
||||||
RegionOriginNote::Plain {
|
|
||||||
span,
|
|
||||||
msg: fluent::infer_ascribe_user_type_prove_predicate,
|
|
||||||
}
|
|
||||||
.add_to_diag(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn report_concrete_failure(
|
|
||||||
&self,
|
|
||||||
generic_param_scope: LocalDefId,
|
|
||||||
origin: SubregionOrigin<'tcx>,
|
|
||||||
sub: Region<'tcx>,
|
|
||||||
sup: Region<'tcx>,
|
|
||||||
) -> Diag<'a> {
|
|
||||||
let mut err = match origin {
|
|
||||||
infer::Subtype(box trace) => {
|
|
||||||
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
|
|
||||||
let mut err = self.report_and_explain_type_error(trace, terr);
|
|
||||||
match (*sub, *sup) {
|
|
||||||
(ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
|
|
||||||
(ty::RePlaceholder(_), _) => {
|
|
||||||
note_and_explain_region(
|
|
||||||
self.tcx,
|
|
||||||
&mut err,
|
|
||||||
generic_param_scope,
|
|
||||||
"",
|
|
||||||
sup,
|
|
||||||
" doesn't meet the lifetime requirements",
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
(_, ty::RePlaceholder(_)) => {
|
|
||||||
note_and_explain_region(
|
|
||||||
self.tcx,
|
|
||||||
&mut err,
|
|
||||||
generic_param_scope,
|
|
||||||
"the required lifetime does not necessarily outlive ",
|
|
||||||
sub,
|
|
||||||
"",
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
note_and_explain_region(
|
|
||||||
self.tcx,
|
|
||||||
&mut err,
|
|
||||||
generic_param_scope,
|
|
||||||
"",
|
|
||||||
sup,
|
|
||||||
"...",
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
note_and_explain_region(
|
|
||||||
self.tcx,
|
|
||||||
&mut err,
|
|
||||||
generic_param_scope,
|
|
||||||
"...does not necessarily outlive ",
|
|
||||||
sub,
|
|
||||||
"",
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err
|
|
||||||
}
|
|
||||||
infer::Reborrow(span) => {
|
|
||||||
let reference_valid = note_and_explain::RegionExplanation::new(
|
|
||||||
self.tcx,
|
|
||||||
generic_param_scope,
|
|
||||||
sub,
|
|
||||||
None,
|
|
||||||
note_and_explain::PrefixKind::RefValidFor,
|
|
||||||
note_and_explain::SuffixKind::Continues,
|
|
||||||
);
|
|
||||||
let content_valid = note_and_explain::RegionExplanation::new(
|
|
||||||
self.tcx,
|
|
||||||
generic_param_scope,
|
|
||||||
sup,
|
|
||||||
None,
|
|
||||||
note_and_explain::PrefixKind::ContentValidFor,
|
|
||||||
note_and_explain::SuffixKind::Empty,
|
|
||||||
);
|
|
||||||
self.dcx().create_err(OutlivesContent {
|
|
||||||
span,
|
|
||||||
notes: reference_valid.into_iter().chain(content_valid).collect(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
infer::RelateObjectBound(span) => {
|
|
||||||
let object_valid = note_and_explain::RegionExplanation::new(
|
|
||||||
self.tcx,
|
|
||||||
generic_param_scope,
|
|
||||||
sub,
|
|
||||||
None,
|
|
||||||
note_and_explain::PrefixKind::TypeObjValidFor,
|
|
||||||
note_and_explain::SuffixKind::Empty,
|
|
||||||
);
|
|
||||||
let pointer_valid = note_and_explain::RegionExplanation::new(
|
|
||||||
self.tcx,
|
|
||||||
generic_param_scope,
|
|
||||||
sup,
|
|
||||||
None,
|
|
||||||
note_and_explain::PrefixKind::SourcePointerValidFor,
|
|
||||||
note_and_explain::SuffixKind::Empty,
|
|
||||||
);
|
|
||||||
self.dcx().create_err(OutlivesBound {
|
|
||||||
span,
|
|
||||||
notes: object_valid.into_iter().chain(pointer_valid).collect(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
infer::RelateParamBound(span, ty, opt_span) => {
|
|
||||||
let prefix = match *sub {
|
|
||||||
ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy,
|
|
||||||
_ => note_and_explain::PrefixKind::TypeOutlive,
|
|
||||||
};
|
|
||||||
let suffix = if opt_span.is_some() {
|
|
||||||
note_and_explain::SuffixKind::ReqByBinding
|
|
||||||
} else {
|
|
||||||
note_and_explain::SuffixKind::Empty
|
|
||||||
};
|
|
||||||
let note = note_and_explain::RegionExplanation::new(
|
|
||||||
self.tcx,
|
|
||||||
generic_param_scope,
|
|
||||||
sub,
|
|
||||||
opt_span,
|
|
||||||
prefix,
|
|
||||||
suffix,
|
|
||||||
);
|
|
||||||
self.dcx().create_err(FulfillReqLifetime {
|
|
||||||
span,
|
|
||||||
ty: self.resolve_vars_if_possible(ty),
|
|
||||||
note,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
infer::RelateRegionParamBound(span, _) => {
|
|
||||||
let param_instantiated = note_and_explain::RegionExplanation::new(
|
|
||||||
self.tcx,
|
|
||||||
generic_param_scope,
|
|
||||||
sup,
|
|
||||||
None,
|
|
||||||
note_and_explain::PrefixKind::LfParamInstantiatedWith,
|
|
||||||
note_and_explain::SuffixKind::Empty,
|
|
||||||
);
|
|
||||||
let param_must_outlive = note_and_explain::RegionExplanation::new(
|
|
||||||
self.tcx,
|
|
||||||
generic_param_scope,
|
|
||||||
sub,
|
|
||||||
None,
|
|
||||||
note_and_explain::PrefixKind::LfParamMustOutlive,
|
|
||||||
note_and_explain::SuffixKind::Empty,
|
|
||||||
);
|
|
||||||
self.dcx().create_err(LfBoundNotSatisfied {
|
|
||||||
span,
|
|
||||||
notes: param_instantiated.into_iter().chain(param_must_outlive).collect(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
infer::ReferenceOutlivesReferent(ty, span) => {
|
|
||||||
let pointer_valid = note_and_explain::RegionExplanation::new(
|
|
||||||
self.tcx,
|
|
||||||
generic_param_scope,
|
|
||||||
sub,
|
|
||||||
None,
|
|
||||||
note_and_explain::PrefixKind::PointerValidFor,
|
|
||||||
note_and_explain::SuffixKind::Empty,
|
|
||||||
);
|
|
||||||
let data_valid = note_and_explain::RegionExplanation::new(
|
|
||||||
self.tcx,
|
|
||||||
generic_param_scope,
|
|
||||||
sup,
|
|
||||||
None,
|
|
||||||
note_and_explain::PrefixKind::DataValidFor,
|
|
||||||
note_and_explain::SuffixKind::Empty,
|
|
||||||
);
|
|
||||||
self.dcx().create_err(RefLongerThanData {
|
|
||||||
span,
|
|
||||||
ty: self.resolve_vars_if_possible(ty),
|
|
||||||
notes: pointer_valid.into_iter().chain(data_valid).collect(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
|
|
||||||
let mut err = self.infcx.report_extra_impl_obligation(
|
|
||||||
span,
|
|
||||||
impl_item_def_id,
|
|
||||||
trait_item_def_id,
|
|
||||||
&format!("`{sup}: {sub}`"),
|
|
||||||
);
|
|
||||||
// We should only suggest rewriting the `where` clause if the predicate is within that `where` clause
|
|
||||||
if let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id)
|
|
||||||
&& generics.where_clause_span.contains(span)
|
|
||||||
{
|
|
||||||
self.suggest_copy_trait_method_bounds(
|
|
||||||
trait_item_def_id,
|
|
||||||
impl_item_def_id,
|
|
||||||
&mut err,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
err
|
|
||||||
}
|
|
||||||
infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
|
|
||||||
let mut err = self.report_concrete_failure(generic_param_scope, *parent, sub, sup);
|
|
||||||
|
|
||||||
// Don't mention the item name if it's an RPITIT, since that'll just confuse
|
|
||||||
// folks.
|
|
||||||
if !self.tcx.is_impl_trait_in_trait(impl_item_def_id.to_def_id()) {
|
|
||||||
let trait_item_span = self.tcx.def_span(trait_item_def_id);
|
|
||||||
let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
|
|
||||||
err.span_label(
|
|
||||||
trait_item_span,
|
|
||||||
format!("definition of `{item_name}` from trait"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.suggest_copy_trait_method_bounds(
|
|
||||||
trait_item_def_id,
|
|
||||||
impl_item_def_id,
|
|
||||||
&mut err,
|
|
||||||
);
|
|
||||||
err
|
|
||||||
}
|
|
||||||
infer::AscribeUserTypeProvePredicate(span) => {
|
|
||||||
let instantiated = note_and_explain::RegionExplanation::new(
|
|
||||||
self.tcx,
|
|
||||||
generic_param_scope,
|
|
||||||
sup,
|
|
||||||
None,
|
|
||||||
note_and_explain::PrefixKind::LfInstantiatedWith,
|
|
||||||
note_and_explain::SuffixKind::Empty,
|
|
||||||
);
|
|
||||||
let must_outlive = note_and_explain::RegionExplanation::new(
|
|
||||||
self.tcx,
|
|
||||||
generic_param_scope,
|
|
||||||
sub,
|
|
||||||
None,
|
|
||||||
note_and_explain::PrefixKind::LfMustOutlive,
|
|
||||||
note_and_explain::SuffixKind::Empty,
|
|
||||||
);
|
|
||||||
self.dcx().create_err(LfBoundNotSatisfied {
|
|
||||||
span,
|
|
||||||
notes: instantiated.into_iter().chain(must_outlive).collect(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if sub.is_error() || sup.is_error() {
|
|
||||||
err.downgrade_to_delayed_bug();
|
|
||||||
}
|
|
||||||
err
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn suggest_copy_trait_method_bounds(
|
|
||||||
&self,
|
|
||||||
trait_item_def_id: DefId,
|
|
||||||
impl_item_def_id: LocalDefId,
|
|
||||||
err: &mut Diag<'_>,
|
|
||||||
) {
|
|
||||||
// FIXME(compiler-errors): Right now this is only being used for region
|
|
||||||
// predicate mismatches. Ideally, we'd use it for *all* predicate mismatches,
|
|
||||||
// but right now it's not really very smart when it comes to implicit `Sized`
|
|
||||||
// predicates and bounds on the trait itself.
|
|
||||||
|
|
||||||
let Some(impl_def_id) = self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx)
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let trait_args = trait_ref
|
|
||||||
.instantiate_identity()
|
|
||||||
// Replace the explicit self type with `Self` for better suggestion rendering
|
|
||||||
.with_self_ty(self.tcx, Ty::new_param(self.tcx, 0, kw::SelfUpper))
|
|
||||||
.args;
|
|
||||||
let trait_item_args = ty::GenericArgs::identity_for_item(self.tcx, impl_item_def_id)
|
|
||||||
.rebase_onto(self.tcx, impl_def_id, trait_args);
|
|
||||||
|
|
||||||
let Ok(trait_predicates) =
|
|
||||||
self.tcx
|
|
||||||
.explicit_predicates_of(trait_item_def_id)
|
|
||||||
.instantiate_own(self.tcx, trait_item_args)
|
|
||||||
.map(|(pred, _)| {
|
|
||||||
if pred.is_suggestable(self.tcx, false) {
|
|
||||||
Ok(pred.to_string())
|
|
||||||
} else {
|
|
||||||
Err(())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, ()>>()
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let suggestion = if trait_predicates.is_empty() {
|
|
||||||
WhereClauseSuggestions::Remove { span: generics.where_clause_span }
|
|
||||||
} else {
|
|
||||||
let space = if generics.where_clause_span.is_empty() { " " } else { "" };
|
|
||||||
WhereClauseSuggestions::CopyPredicates {
|
|
||||||
span: generics.where_clause_span,
|
|
||||||
space,
|
|
||||||
trait_predicates: trait_predicates.join(", "),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
err.subdiagnostic(suggestion);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn report_placeholder_failure(
|
|
||||||
&self,
|
|
||||||
generic_param_scope: LocalDefId,
|
|
||||||
placeholder_origin: SubregionOrigin<'tcx>,
|
|
||||||
sub: Region<'tcx>,
|
|
||||||
sup: Region<'tcx>,
|
|
||||||
) -> Diag<'a> {
|
|
||||||
// I can't think how to do better than this right now. -nikomatsakis
|
|
||||||
debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
|
|
||||||
match placeholder_origin {
|
|
||||||
infer::Subtype(box ref trace)
|
|
||||||
if matches!(
|
|
||||||
&trace.cause.code().peel_derives(),
|
|
||||||
ObligationCauseCode::WhereClause(..)
|
|
||||||
| ObligationCauseCode::WhereClauseInExpr(..)
|
|
||||||
) =>
|
|
||||||
{
|
|
||||||
// Hack to get around the borrow checker because trace.cause has an `Rc`.
|
|
||||||
if let ObligationCauseCode::WhereClause(_, span)
|
|
||||||
| ObligationCauseCode::WhereClauseInExpr(_, span, ..) =
|
|
||||||
&trace.cause.code().peel_derives()
|
|
||||||
&& !span.is_dummy()
|
|
||||||
{
|
|
||||||
let span = *span;
|
|
||||||
self.report_concrete_failure(generic_param_scope, placeholder_origin, sub, sup)
|
|
||||||
.with_span_note(span, "the lifetime requirement is introduced here")
|
|
||||||
} else {
|
|
||||||
unreachable!(
|
|
||||||
"control flow ensures we have a `BindingObligation` or `WhereClauseInExpr` here..."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
infer::Subtype(box trace) => {
|
|
||||||
let terr = TypeError::RegionsPlaceholderMismatch;
|
|
||||||
return self.report_and_explain_type_error(trace, terr);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return self.report_concrete_failure(
|
|
||||||
generic_param_scope,
|
|
||||||
placeholder_origin,
|
|
||||||
sub,
|
|
||||||
sup,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -221,7 +221,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
|
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
|
||||||
span: trace.cause.span,
|
span: trace.cause.span,
|
||||||
requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
|
requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
|
||||||
expected_found: self.values_str(trace.values, &trace.cause).map(|(e, f, _)| (e, f)),
|
expected_found: self.values_str(trace.values, &trace.cause, err.long_ty_path()),
|
||||||
}
|
}
|
||||||
.add_to_diag(err),
|
.add_to_diag(err),
|
||||||
infer::Reborrow(span) => {
|
infer::Reborrow(span) => {
|
||||||
|
@ -946,10 +946,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
if let infer::Subtype(ref sup_trace) = sup_origin
|
if let infer::Subtype(ref sup_trace) = sup_origin
|
||||||
&& let infer::Subtype(ref sub_trace) = sub_origin
|
&& let infer::Subtype(ref sub_trace) = sub_origin
|
||||||
&& let Some((sup_expected, sup_found, _)) =
|
&& let Some((sup_expected, sup_found)) =
|
||||||
self.values_str(sup_trace.values, &sup_trace.cause)
|
self.values_str(sup_trace.values, &sup_trace.cause, err.long_ty_path())
|
||||||
&& let Some((sub_expected, sub_found, _)) =
|
&& let Some((sub_expected, sub_found)) =
|
||||||
self.values_str(sub_trace.values, &sup_trace.cause)
|
self.values_str(sub_trace.values, &sup_trace.cause, err.long_ty_path())
|
||||||
&& sub_expected == sup_expected
|
&& sub_expected == sup_expected
|
||||||
&& sub_found == sup_found
|
&& sub_found == sup_found
|
||||||
{
|
{
|
||||||
|
|
|
@ -163,6 +163,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
let predicate = self.resolve_vars_if_possible(obligation.predicate);
|
let predicate = self.resolve_vars_if_possible(obligation.predicate);
|
||||||
let span = obligation.cause.span;
|
let span = obligation.cause.span;
|
||||||
|
let mut file = None;
|
||||||
|
|
||||||
debug!(?predicate, obligation.cause.code = ?obligation.cause.code());
|
debug!(?predicate, obligation.cause.code = ?obligation.cause.code());
|
||||||
|
|
||||||
|
@ -245,7 +246,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
span,
|
span,
|
||||||
E0283,
|
E0283,
|
||||||
"type annotations needed: cannot satisfy `{}`",
|
"type annotations needed: cannot satisfy `{}`",
|
||||||
predicate,
|
self.tcx.short_string(predicate, &mut file),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -292,7 +293,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
err.cancel();
|
err.cancel();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
err.note(format!("cannot satisfy `{predicate}`"));
|
let pred = self.tcx.short_string(predicate, &mut file);
|
||||||
|
err.note(format!("cannot satisfy `{pred}`"));
|
||||||
let impl_candidates =
|
let impl_candidates =
|
||||||
self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap());
|
self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap());
|
||||||
if impl_candidates.len() < 40 {
|
if impl_candidates.len() < 40 {
|
||||||
|
@ -524,6 +526,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
.iter()
|
.iter()
|
||||||
.chain(Some(data.term.into_arg()))
|
.chain(Some(data.term.into_arg()))
|
||||||
.find(|g| g.has_non_region_infer());
|
.find(|g| g.has_non_region_infer());
|
||||||
|
let predicate = self.tcx.short_string(predicate, &mut file);
|
||||||
if let Some(arg) = arg {
|
if let Some(arg) = arg {
|
||||||
self.emit_inference_failure_err(
|
self.emit_inference_failure_err(
|
||||||
obligation.cause.body_id,
|
obligation.cause.body_id,
|
||||||
|
@ -539,8 +542,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
self.dcx(),
|
self.dcx(),
|
||||||
span,
|
span,
|
||||||
E0284,
|
E0284,
|
||||||
"type annotations needed: cannot satisfy `{}`",
|
"type annotations needed: cannot satisfy `{predicate}`",
|
||||||
predicate,
|
|
||||||
)
|
)
|
||||||
.with_span_label(span, format!("cannot satisfy `{predicate}`"))
|
.with_span_label(span, format!("cannot satisfy `{predicate}`"))
|
||||||
}
|
}
|
||||||
|
@ -565,12 +567,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
err
|
err
|
||||||
} else {
|
} else {
|
||||||
// If we can't find a generic parameter, just print a generic error
|
// If we can't find a generic parameter, just print a generic error
|
||||||
|
let predicate = self.tcx.short_string(predicate, &mut file);
|
||||||
struct_span_code_err!(
|
struct_span_code_err!(
|
||||||
self.dcx(),
|
self.dcx(),
|
||||||
span,
|
span,
|
||||||
E0284,
|
E0284,
|
||||||
"type annotations needed: cannot satisfy `{}`",
|
"type annotations needed: cannot satisfy `{predicate}`",
|
||||||
predicate,
|
|
||||||
)
|
)
|
||||||
.with_span_label(span, format!("cannot satisfy `{predicate}`"))
|
.with_span_label(span, format!("cannot satisfy `{predicate}`"))
|
||||||
}
|
}
|
||||||
|
@ -590,6 +592,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
if let Some(e) = self.tainted_by_errors() {
|
if let Some(e) = self.tainted_by_errors() {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
let alias = self.tcx.short_string(alias, &mut file);
|
||||||
struct_span_code_err!(
|
struct_span_code_err!(
|
||||||
self.dcx(),
|
self.dcx(),
|
||||||
span,
|
span,
|
||||||
|
@ -603,16 +606,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
if let Some(e) = self.tainted_by_errors() {
|
if let Some(e) = self.tainted_by_errors() {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
let predicate = self.tcx.short_string(predicate, &mut file);
|
||||||
struct_span_code_err!(
|
struct_span_code_err!(
|
||||||
self.dcx(),
|
self.dcx(),
|
||||||
span,
|
span,
|
||||||
E0284,
|
E0284,
|
||||||
"type annotations needed: cannot satisfy `{}`",
|
"type annotations needed: cannot satisfy `{predicate}`",
|
||||||
predicate,
|
|
||||||
)
|
)
|
||||||
.with_span_label(span, format!("cannot satisfy `{predicate}`"))
|
.with_span_label(span, format!("cannot satisfy `{predicate}`"))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
*err.long_ty_path() = file;
|
||||||
self.note_obligation_cause(&mut err, obligation);
|
self.note_obligation_cause(&mut err, obligation);
|
||||||
err.emit()
|
err.emit()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use core::ops::ControlFlow;
|
use core::ops::ControlFlow;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use rustc_ast::TraitObjectSyntax;
|
use rustc_ast::TraitObjectSyntax;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
@ -9,7 +10,6 @@ use rustc_errors::{
|
||||||
Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions,
|
Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions,
|
||||||
pluralize, struct_span_code_err,
|
pluralize, struct_span_code_err,
|
||||||
};
|
};
|
||||||
use rustc_hir::def::Namespace;
|
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::{self as hir, LangItem, Node};
|
use rustc_hir::{self as hir, LangItem, Node};
|
||||||
|
@ -20,8 +20,8 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
||||||
use rustc_middle::ty::print::{
|
use rustc_middle::ty::print::{
|
||||||
FmtPrinter, Print, PrintPolyTraitPredicateExt, PrintTraitPredicateExt as _,
|
PrintPolyTraitPredicateExt, PrintTraitPredicateExt as _, PrintTraitRefExt as _,
|
||||||
PrintTraitRefExt as _, with_forced_trimmed_paths,
|
with_forced_trimmed_paths,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast};
|
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
|
@ -60,6 +60,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
) -> ErrorGuaranteed {
|
) -> ErrorGuaranteed {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let mut span = obligation.cause.span;
|
let mut span = obligation.cause.span;
|
||||||
|
let mut long_ty_file = None;
|
||||||
|
|
||||||
let mut err = match *error {
|
let mut err = match *error {
|
||||||
SelectionError::Unimplemented => {
|
SelectionError::Unimplemented => {
|
||||||
|
@ -169,11 +170,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
if let Err(guar) = self.fn_arg_obligation(&obligation) {
|
if let Err(guar) = self.fn_arg_obligation(&obligation) {
|
||||||
return guar;
|
return guar;
|
||||||
}
|
}
|
||||||
let mut file = None;
|
|
||||||
let (post_message, pre_message, type_def) = self
|
let (post_message, pre_message, type_def) = self
|
||||||
.get_parent_trait_ref(obligation.cause.code())
|
.get_parent_trait_ref(obligation.cause.code())
|
||||||
.map(|(t, s)| {
|
.map(|(t, s)| {
|
||||||
let t = self.tcx.short_ty_string(t, &mut file);
|
let t = self.tcx.short_string(t, &mut long_ty_file);
|
||||||
(
|
(
|
||||||
format!(" in `{t}`"),
|
format!(" in `{t}`"),
|
||||||
format!("within `{t}`, "),
|
format!("within `{t}`, "),
|
||||||
|
@ -181,12 +181,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let file_note = file.as_ref().map(|file| format!(
|
|
||||||
"the full trait has been written to '{}'",
|
|
||||||
file.display(),
|
|
||||||
));
|
|
||||||
|
|
||||||
let mut long_ty_file = None;
|
|
||||||
|
|
||||||
let OnUnimplementedNote {
|
let OnUnimplementedNote {
|
||||||
message,
|
message,
|
||||||
|
@ -223,6 +217,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
None,
|
None,
|
||||||
append_const_msg,
|
append_const_msg,
|
||||||
post_message,
|
post_message,
|
||||||
|
&mut long_ty_file,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(main_trait_predicate.def_id(), LangItem::TransmuteTrait)
|
let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(main_trait_predicate.def_id(), LangItem::TransmuteTrait)
|
||||||
|
@ -251,14 +246,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut err = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
|
let mut err = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
|
||||||
|
*err.long_ty_path() = long_ty_file;
|
||||||
|
|
||||||
if let Some(long_ty_file) = long_ty_file {
|
|
||||||
err.note(format!(
|
|
||||||
"the full name for the type has been written to '{}'",
|
|
||||||
long_ty_file.display(),
|
|
||||||
));
|
|
||||||
err.note("consider using `--verbose` to print the full type name to the console");
|
|
||||||
}
|
|
||||||
let mut suggested = false;
|
let mut suggested = false;
|
||||||
if is_try_conversion {
|
if is_try_conversion {
|
||||||
suggested = self.try_conversion_context(&obligation, main_trait_predicate, &mut err);
|
suggested = self.try_conversion_context(&obligation, main_trait_predicate, &mut err);
|
||||||
|
@ -309,7 +298,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
return err.emit();
|
return err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
file_note.map(|note| err.note(note));
|
|
||||||
if let Some(s) = label {
|
if let Some(s) = label {
|
||||||
// If it has a custom `#[rustc_on_unimplemented]`
|
// If it has a custom `#[rustc_on_unimplemented]`
|
||||||
// error message, let's display it as the label!
|
// error message, let's display it as the label!
|
||||||
|
@ -762,14 +750,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
trait_ref: predicate.trait_ref,
|
trait_ref: predicate.trait_ref,
|
||||||
polarity: ty::PredicatePolarity::Positive,
|
polarity: ty::PredicatePolarity::Positive,
|
||||||
});
|
});
|
||||||
|
let mut file = None;
|
||||||
let err_msg = self.get_standard_error_message(
|
let err_msg = self.get_standard_error_message(
|
||||||
trait_ref,
|
trait_ref,
|
||||||
None,
|
None,
|
||||||
Some(predicate.constness()),
|
Some(predicate.constness()),
|
||||||
None,
|
None,
|
||||||
String::new(),
|
String::new(),
|
||||||
|
&mut file,
|
||||||
);
|
);
|
||||||
let mut diag = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
|
let mut diag = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
|
||||||
|
*diag.long_ty_path() = file;
|
||||||
if !self.predicate_may_hold(&Obligation::new(
|
if !self.predicate_may_hold(&Obligation::new(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy(),
|
||||||
|
@ -1381,6 +1372,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
_ => (None, error.err),
|
_ => (None, error.err),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut file = None;
|
||||||
let (msg, span, closure_span) = values
|
let (msg, span, closure_span) = values
|
||||||
.and_then(|(predicate, normalized_term, expected_term)| {
|
.and_then(|(predicate, normalized_term, expected_term)| {
|
||||||
self.maybe_detailed_projection_msg(
|
self.maybe_detailed_projection_msg(
|
||||||
|
@ -1388,24 +1380,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
predicate,
|
predicate,
|
||||||
normalized_term,
|
normalized_term,
|
||||||
expected_term,
|
expected_term,
|
||||||
|
&mut file,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
let mut cx = FmtPrinter::new_with_limit(
|
|
||||||
self.tcx,
|
|
||||||
Namespace::TypeNS,
|
|
||||||
rustc_session::Limit(10),
|
|
||||||
);
|
|
||||||
(
|
(
|
||||||
with_forced_trimmed_paths!(format!("type mismatch resolving `{}`", {
|
with_forced_trimmed_paths!(format!(
|
||||||
self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap();
|
"type mismatch resolving `{}`",
|
||||||
cx.into_buffer()
|
self.tcx
|
||||||
})),
|
.short_string(self.resolve_vars_if_possible(predicate), &mut file),
|
||||||
|
)),
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let mut diag = struct_span_code_err!(self.dcx(), span, E0271, "{msg}");
|
let mut diag = struct_span_code_err!(self.dcx(), span, E0271, "{msg}");
|
||||||
|
*diag.long_ty_path() = file;
|
||||||
if let Some(span) = closure_span {
|
if let Some(span) = closure_span {
|
||||||
// Mark the closure decl so that it is seen even if we are pointing at the return
|
// Mark the closure decl so that it is seen even if we are pointing at the return
|
||||||
// type or expression.
|
// type or expression.
|
||||||
|
@ -1471,15 +1461,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
ty.span,
|
ty.span,
|
||||||
with_forced_trimmed_paths!(Cow::from(format!(
|
with_forced_trimmed_paths!(Cow::from(format!(
|
||||||
"type mismatch resolving `{}`",
|
"type mismatch resolving `{}`",
|
||||||
{
|
self.tcx.short_string(
|
||||||
let mut cx = FmtPrinter::new_with_limit(
|
self.resolve_vars_if_possible(predicate),
|
||||||
self.tcx,
|
diag.long_ty_path()
|
||||||
Namespace::TypeNS,
|
),
|
||||||
rustc_session::Limit(5),
|
|
||||||
);
|
|
||||||
self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap();
|
|
||||||
cx.into_buffer()
|
|
||||||
}
|
|
||||||
))),
|
))),
|
||||||
true,
|
true,
|
||||||
)),
|
)),
|
||||||
|
@ -1512,6 +1497,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
projection_term: ty::AliasTerm<'tcx>,
|
projection_term: ty::AliasTerm<'tcx>,
|
||||||
normalized_ty: ty::Term<'tcx>,
|
normalized_ty: ty::Term<'tcx>,
|
||||||
expected_ty: ty::Term<'tcx>,
|
expected_ty: ty::Term<'tcx>,
|
||||||
|
file: &mut Option<PathBuf>,
|
||||||
) -> Option<(String, Span, Option<Span>)> {
|
) -> Option<(String, Span, Option<Span>)> {
|
||||||
let trait_def_id = projection_term.trait_def_id(self.tcx);
|
let trait_def_id = projection_term.trait_def_id(self.tcx);
|
||||||
let self_ty = projection_term.self_ty();
|
let self_ty = projection_term.self_ty();
|
||||||
|
@ -1552,7 +1538,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
let item = match self_ty.kind() {
|
let item = match self_ty.kind() {
|
||||||
ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
|
ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
|
||||||
_ => self_ty.to_string(),
|
_ => self.tcx.short_string(self_ty, file),
|
||||||
};
|
};
|
||||||
Some((format!(
|
Some((format!(
|
||||||
"expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \
|
"expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \
|
||||||
|
@ -1984,8 +1970,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
StringPart::normal(" implemented for `"),
|
StringPart::normal(" implemented for `"),
|
||||||
]);
|
]);
|
||||||
if types_content.0 == types_content.1 {
|
if types_content.0 == types_content.1 {
|
||||||
let ty =
|
let ty = self
|
||||||
self.tcx.short_ty_string(obligation_trait_ref.self_ty(), &mut None);
|
.tcx
|
||||||
|
.short_string(obligation_trait_ref.self_ty(), err.long_ty_path());
|
||||||
msg.push(StringPart::normal(ty));
|
msg.push(StringPart::normal(ty));
|
||||||
} else {
|
} else {
|
||||||
msg.extend(types.0.0);
|
msg.extend(types.0.0);
|
||||||
|
@ -2342,7 +2329,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
// First, attempt to add note to this error with an async-await-specific
|
// First, attempt to add note to this error with an async-await-specific
|
||||||
// message, and fall back to regular note otherwise.
|
// message, and fall back to regular note otherwise.
|
||||||
if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
|
if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
|
||||||
let mut long_ty_file = None;
|
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
obligation.cause.body_id,
|
obligation.cause.body_id,
|
||||||
err,
|
err,
|
||||||
|
@ -2351,15 +2337,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
obligation.cause.code(),
|
obligation.cause.code(),
|
||||||
&mut vec![],
|
&mut vec![],
|
||||||
&mut Default::default(),
|
&mut Default::default(),
|
||||||
&mut long_ty_file,
|
|
||||||
);
|
);
|
||||||
if let Some(file) = long_ty_file {
|
|
||||||
err.note(format!(
|
|
||||||
"the full name for the type has been written to '{}'",
|
|
||||||
file.display(),
|
|
||||||
));
|
|
||||||
err.note("consider using `--verbose` to print the full type name to the console");
|
|
||||||
}
|
|
||||||
self.suggest_unsized_bound_if_applicable(err, obligation);
|
self.suggest_unsized_bound_if_applicable(err, obligation);
|
||||||
if let Some(span) = err.span.primary_span()
|
if let Some(span) = err.span.primary_span()
|
||||||
&& let Some(mut diag) =
|
&& let Some(mut diag) =
|
||||||
|
@ -2403,6 +2381,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
predicate_constness: Option<ty::BoundConstness>,
|
predicate_constness: Option<ty::BoundConstness>,
|
||||||
append_const_msg: Option<AppendConstMessage>,
|
append_const_msg: Option<AppendConstMessage>,
|
||||||
post_message: String,
|
post_message: String,
|
||||||
|
long_ty_file: &mut Option<PathBuf>,
|
||||||
) -> String {
|
) -> String {
|
||||||
message
|
message
|
||||||
.and_then(|cannot_do_this| {
|
.and_then(|cannot_do_this| {
|
||||||
|
@ -2426,7 +2405,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
format!(
|
format!(
|
||||||
"the trait bound `{}` is not satisfied{post_message}",
|
"the trait bound `{}` is not satisfied{post_message}",
|
||||||
trait_predicate.print_with_bound_constness(predicate_constness)
|
self.tcx.short_string(
|
||||||
|
trait_predicate.print_with_bound_constness(predicate_constness),
|
||||||
|
long_ty_file,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,7 +306,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
if let ObligationCauseCode::WhereClause(..)
|
if let ObligationCauseCode::WhereClause(..)
|
||||||
| ObligationCauseCode::WhereClauseInExpr(..) = code
|
| ObligationCauseCode::WhereClauseInExpr(..) = code
|
||||||
{
|
{
|
||||||
let mut long_ty_file = None;
|
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
error.obligation.cause.body_id,
|
error.obligation.cause.body_id,
|
||||||
&mut diag,
|
&mut diag,
|
||||||
|
@ -315,17 +314,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
code,
|
code,
|
||||||
&mut vec![],
|
&mut vec![],
|
||||||
&mut Default::default(),
|
&mut Default::default(),
|
||||||
&mut long_ty_file,
|
|
||||||
);
|
);
|
||||||
if let Some(file) = long_ty_file {
|
|
||||||
diag.note(format!(
|
|
||||||
"the full name for the type has been written to '{}'",
|
|
||||||
file.display(),
|
|
||||||
));
|
|
||||||
diag.note(
|
|
||||||
"consider using `--verbose` to print the full type name to the console",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
diag.emit()
|
diag.emit()
|
||||||
}
|
}
|
||||||
|
|
|
@ -932,7 +932,7 @@ impl<'tcx> OnUnimplementedFormatString {
|
||||||
let value = match param.kind {
|
let value = match param.kind {
|
||||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
|
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
|
||||||
if let Some(ty) = trait_ref.args[param.index as usize].as_type() {
|
if let Some(ty) = trait_ref.args[param.index as usize].as_type() {
|
||||||
tcx.short_ty_string(ty, long_ty_file)
|
tcx.short_string(ty, long_ty_file)
|
||||||
} else {
|
} else {
|
||||||
trait_ref.args[param.index as usize].to_string()
|
trait_ref.args[param.index as usize].to_string()
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,7 +141,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
suggest_increasing_limit,
|
suggest_increasing_limit,
|
||||||
|err| {
|
|err| {
|
||||||
let mut long_ty_file = None;
|
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
obligation.cause.body_id,
|
obligation.cause.body_id,
|
||||||
err,
|
err,
|
||||||
|
@ -150,17 +149,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
obligation.cause.code(),
|
obligation.cause.code(),
|
||||||
&mut vec![],
|
&mut vec![],
|
||||||
&mut Default::default(),
|
&mut Default::default(),
|
||||||
&mut long_ty_file,
|
|
||||||
);
|
);
|
||||||
if let Some(file) = long_ty_file {
|
|
||||||
err.note(format!(
|
|
||||||
"the full name for the type has been written to '{}'",
|
|
||||||
file.display(),
|
|
||||||
));
|
|
||||||
err.note(
|
|
||||||
"consider using `--verbose` to print the full type name to the console",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
use std::assert_matches::debug_assert_matches;
|
use std::assert_matches::debug_assert_matches;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use itertools::{EitherOrBoth, Itertools};
|
use itertools::{EitherOrBoth, Itertools};
|
||||||
use rustc_abi::ExternAbi;
|
use rustc_abi::ExternAbi;
|
||||||
|
@ -1297,30 +1296,24 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
// Because of this, we modify the error to refer to the original obligation and
|
// Because of this, we modify the error to refer to the original obligation and
|
||||||
// return early in the caller.
|
// return early in the caller.
|
||||||
|
|
||||||
let msg = format!("the trait bound `{old_pred}` is not satisfied");
|
let msg = format!(
|
||||||
|
"the trait bound `{}` is not satisfied",
|
||||||
|
self.tcx.short_string(old_pred, err.long_ty_path()),
|
||||||
|
);
|
||||||
|
let self_ty_str =
|
||||||
|
self.tcx.short_string(old_pred.self_ty().skip_binder(), err.long_ty_path());
|
||||||
if has_custom_message {
|
if has_custom_message {
|
||||||
err.note(msg);
|
err.note(msg);
|
||||||
} else {
|
} else {
|
||||||
err.messages = vec![(rustc_errors::DiagMessage::from(msg), Style::NoStyle)];
|
err.messages = vec![(rustc_errors::DiagMessage::from(msg), Style::NoStyle)];
|
||||||
}
|
}
|
||||||
let mut file = None;
|
|
||||||
err.span_label(
|
err.span_label(
|
||||||
span,
|
span,
|
||||||
format!(
|
format!(
|
||||||
"the trait `{}` is not implemented for `{}`",
|
"the trait `{}` is not implemented for `{self_ty_str}`",
|
||||||
old_pred.print_modifiers_and_trait_path(),
|
old_pred.print_modifiers_and_trait_path()
|
||||||
self.tcx.short_ty_string(old_pred.self_ty().skip_binder(), &mut file),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if let Some(file) = file {
|
|
||||||
err.note(format!(
|
|
||||||
"the full type name has been written to '{}'",
|
|
||||||
file.display()
|
|
||||||
));
|
|
||||||
err.note(
|
|
||||||
"consider using `--verbose` to print full type name to the console",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred {
|
if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred {
|
||||||
err.span_suggestions(
|
err.span_suggestions(
|
||||||
|
@ -2689,7 +2682,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
// Add a note for the item obligation that remains - normally a note pointing to the
|
// Add a note for the item obligation that remains - normally a note pointing to the
|
||||||
// bound that introduced the obligation (e.g. `T: Send`).
|
// bound that introduced the obligation (e.g. `T: Send`).
|
||||||
debug!(?next_code);
|
debug!(?next_code);
|
||||||
let mut long_ty_file = None;
|
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
obligation.cause.body_id,
|
obligation.cause.body_id,
|
||||||
err,
|
err,
|
||||||
|
@ -2698,7 +2690,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
next_code.unwrap(),
|
next_code.unwrap(),
|
||||||
&mut Vec::new(),
|
&mut Vec::new(),
|
||||||
&mut Default::default(),
|
&mut Default::default(),
|
||||||
&mut long_ty_file,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2711,7 +2702,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
cause_code: &ObligationCauseCode<'tcx>,
|
cause_code: &ObligationCauseCode<'tcx>,
|
||||||
obligated_types: &mut Vec<Ty<'tcx>>,
|
obligated_types: &mut Vec<Ty<'tcx>>,
|
||||||
seen_requirements: &mut FxHashSet<DefId>,
|
seen_requirements: &mut FxHashSet<DefId>,
|
||||||
long_ty_file: &mut Option<PathBuf>,
|
|
||||||
) where
|
) where
|
||||||
T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
|
T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
|
||||||
{
|
{
|
||||||
|
@ -2965,9 +2955,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
ObligationCauseCode::Coercion { source, target } => {
|
ObligationCauseCode::Coercion { source, target } => {
|
||||||
let source =
|
let source =
|
||||||
tcx.short_ty_string(self.resolve_vars_if_possible(source), long_ty_file);
|
tcx.short_string(self.resolve_vars_if_possible(source), err.long_ty_path());
|
||||||
let target =
|
let target =
|
||||||
tcx.short_ty_string(self.resolve_vars_if_possible(target), long_ty_file);
|
tcx.short_string(self.resolve_vars_if_possible(target), err.long_ty_path());
|
||||||
err.note(with_forced_trimmed_paths!(format!(
|
err.note(with_forced_trimmed_paths!(format!(
|
||||||
"required for the cast from `{source}` to `{target}`",
|
"required for the cast from `{source}` to `{target}`",
|
||||||
)));
|
)));
|
||||||
|
@ -3252,7 +3242,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if !is_upvar_tys_infer_tuple {
|
if !is_upvar_tys_infer_tuple {
|
||||||
let ty_str = tcx.short_ty_string(ty, long_ty_file);
|
let ty_str = tcx.short_string(ty, err.long_ty_path());
|
||||||
let msg = format!("required because it appears within the type `{ty_str}`");
|
let msg = format!("required because it appears within the type `{ty_str}`");
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
ty::Adt(def, _) => match tcx.opt_item_ident(def.did()) {
|
ty::Adt(def, _) => match tcx.opt_item_ident(def.did()) {
|
||||||
|
@ -3330,7 +3320,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
&data.parent_code,
|
&data.parent_code,
|
||||||
obligated_types,
|
obligated_types,
|
||||||
seen_requirements,
|
seen_requirements,
|
||||||
long_ty_file,
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -3343,7 +3332,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
cause_code.peel_derives(),
|
cause_code.peel_derives(),
|
||||||
obligated_types,
|
obligated_types,
|
||||||
seen_requirements,
|
seen_requirements,
|
||||||
long_ty_file,
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3353,7 +3341,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
self.resolve_vars_if_possible(data.derived.parent_trait_pred);
|
self.resolve_vars_if_possible(data.derived.parent_trait_pred);
|
||||||
let parent_def_id = parent_trait_pred.def_id();
|
let parent_def_id = parent_trait_pred.def_id();
|
||||||
let self_ty_str =
|
let self_ty_str =
|
||||||
tcx.short_ty_string(parent_trait_pred.skip_binder().self_ty(), long_ty_file);
|
tcx.short_string(parent_trait_pred.skip_binder().self_ty(), err.long_ty_path());
|
||||||
let trait_name = parent_trait_pred.print_modifiers_and_trait_path().to_string();
|
let trait_name = parent_trait_pred.print_modifiers_and_trait_path().to_string();
|
||||||
let msg = format!("required for `{self_ty_str}` to implement `{trait_name}`");
|
let msg = format!("required for `{self_ty_str}` to implement `{trait_name}`");
|
||||||
let mut is_auto_trait = false;
|
let mut is_auto_trait = false;
|
||||||
|
@ -3449,8 +3437,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
count,
|
count,
|
||||||
pluralize!(count)
|
pluralize!(count)
|
||||||
));
|
));
|
||||||
let self_ty = tcx
|
let self_ty = tcx.short_string(
|
||||||
.short_ty_string(parent_trait_pred.skip_binder().self_ty(), long_ty_file);
|
parent_trait_pred.skip_binder().self_ty(),
|
||||||
|
err.long_ty_path(),
|
||||||
|
);
|
||||||
err.note(format!(
|
err.note(format!(
|
||||||
"required for `{self_ty}` to implement `{}`",
|
"required for `{self_ty}` to implement `{}`",
|
||||||
parent_trait_pred.print_modifiers_and_trait_path()
|
parent_trait_pred.print_modifiers_and_trait_path()
|
||||||
|
@ -3466,7 +3456,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
&data.parent_code,
|
&data.parent_code,
|
||||||
obligated_types,
|
obligated_types,
|
||||||
seen_requirements,
|
seen_requirements,
|
||||||
long_ty_file,
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3505,7 +3494,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
&data.derived.parent_code,
|
&data.derived.parent_code,
|
||||||
obligated_types,
|
obligated_types,
|
||||||
seen_requirements,
|
seen_requirements,
|
||||||
long_ty_file,
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3519,7 +3507,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
&data.parent_code,
|
&data.parent_code,
|
||||||
obligated_types,
|
obligated_types,
|
||||||
seen_requirements,
|
seen_requirements,
|
||||||
long_ty_file,
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3536,7 +3523,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
&data.parent_code,
|
&data.parent_code,
|
||||||
obligated_types,
|
obligated_types,
|
||||||
seen_requirements,
|
seen_requirements,
|
||||||
long_ty_file,
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3551,7 +3537,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
nested,
|
nested,
|
||||||
obligated_types,
|
obligated_types,
|
||||||
seen_requirements,
|
seen_requirements,
|
||||||
long_ty_file,
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let mut multispan = MultiSpan::from(span);
|
let mut multispan = MultiSpan::from(span);
|
||||||
|
@ -3582,7 +3567,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
parent_code,
|
parent_code,
|
||||||
obligated_types,
|
obligated_types,
|
||||||
seen_requirements,
|
seen_requirements,
|
||||||
long_ty_file,
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3622,7 +3606,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
ObligationCauseCode::OpaqueReturnType(expr_info) => {
|
ObligationCauseCode::OpaqueReturnType(expr_info) => {
|
||||||
let (expr_ty, expr) = if let Some((expr_ty, hir_id)) = expr_info {
|
let (expr_ty, expr) = if let Some((expr_ty, hir_id)) = expr_info {
|
||||||
let expr_ty = tcx.short_ty_string(expr_ty, long_ty_file);
|
let expr_ty = tcx.short_string(expr_ty, err.long_ty_path());
|
||||||
let expr = tcx.hir().expect_expr(hir_id);
|
let expr = tcx.hir().expect_expr(hir_id);
|
||||||
(expr_ty, expr)
|
(expr_ty, expr)
|
||||||
} else if let Some(body_id) = tcx.hir_node_by_def_id(body_id).body_id()
|
} else if let Some(body_id) = tcx.hir_node_by_def_id(body_id).body_id()
|
||||||
|
@ -3637,7 +3621,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
&& let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
|
&& let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
|
||||||
&& self.can_eq(param_env, pred.self_ty(), expr_ty)
|
&& self.can_eq(param_env, pred.self_ty(), expr_ty)
|
||||||
{
|
{
|
||||||
let expr_ty = tcx.short_ty_string(expr_ty, long_ty_file);
|
let expr_ty = tcx.short_string(expr_ty, err.long_ty_path());
|
||||||
(expr_ty, expr)
|
(expr_ty, expr)
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
@ -5231,7 +5215,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
|
||||||
format!(
|
format!(
|
||||||
"{pre_message}the trait `{}` is not implemented for{desc} `{}`",
|
"{pre_message}the trait `{}` is not implemented for{desc} `{}`",
|
||||||
trait_predicate.print_modifiers_and_trait_path(),
|
trait_predicate.print_modifiers_and_trait_path(),
|
||||||
tcx.short_ty_string(trait_predicate.self_ty().skip_binder(), &mut None),
|
tcx.short_string(trait_predicate.self_ty().skip_binder(), &mut None),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is
|
// "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is
|
||||||
|
|
|
@ -29,7 +29,7 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/coerce-expect-unsized-ascribed.rs:14:27
|
--> $DIR/coerce-expect-unsized-ascribed.rs:14:27
|
||||||
|
|
|
|
||||||
LL | let _ = type_ascribe!(Box::new( { |x| (x as u8) }), Box<dyn Fn(i32) -> _>);
|
LL | let _ = type_ascribe!(Box::new( { |x| (x as u8) }), Box<dyn Fn(i32) -> _>);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Fn(i32) -> u8>`, found `Box<{closure@coerce-expect-unsized-ascribed.rs:14:39}>`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Fn(i32) -> u8>`, found `Box<{closure@...}>`
|
||||||
|
|
|
|
||||||
= note: expected struct `Box<dyn Fn(i32) -> u8>`
|
= note: expected struct `Box<dyn Fn(i32) -> u8>`
|
||||||
found struct `Box<{closure@$DIR/coerce-expect-unsized-ascribed.rs:14:39: 14:42}>`
|
found struct `Box<{closure@$DIR/coerce-expect-unsized-ascribed.rs:14:39: 14:42}>`
|
||||||
|
@ -85,7 +85,7 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/coerce-expect-unsized-ascribed.rs:22:27
|
--> $DIR/coerce-expect-unsized-ascribed.rs:22:27
|
||||||
|
|
|
|
||||||
LL | let _ = type_ascribe!(&{ |x| (x as u8) }, &dyn Fn(i32) -> _);
|
LL | let _ = type_ascribe!(&{ |x| (x as u8) }, &dyn Fn(i32) -> _);
|
||||||
| ^^^^^^^^^^^^^^^^^^ expected `&dyn Fn(i32) -> u8`, found `&{closure@coerce-expect-unsized-ascribed.rs:22:30}`
|
| ^^^^^^^^^^^^^^^^^^ expected `&dyn Fn(i32) -> u8`, found `&{closure@...}`
|
||||||
|
|
|
|
||||||
= note: expected reference `&dyn Fn(i32) -> u8`
|
= note: expected reference `&dyn Fn(i32) -> u8`
|
||||||
found reference `&{closure@$DIR/coerce-expect-unsized-ascribed.rs:22:30: 22:33}`
|
found reference `&{closure@$DIR/coerce-expect-unsized-ascribed.rs:22:30: 22:33}`
|
||||||
|
@ -123,7 +123,7 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/coerce-expect-unsized-ascribed.rs:27:27
|
--> $DIR/coerce-expect-unsized-ascribed.rs:27:27
|
||||||
|
|
|
|
||||||
LL | let _ = type_ascribe!(Box::new(|x| (x as u8)), Box<dyn Fn(i32) -> _>);
|
LL | let _ = type_ascribe!(Box::new(|x| (x as u8)), Box<dyn Fn(i32) -> _>);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Fn(i32) -> u8>`, found `Box<{closure@coerce-expect-unsized-ascribed.rs:27:36}>`
|
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Fn(i32) -> u8>`, found `Box<{closure@...}>`
|
||||||
|
|
|
|
||||||
= note: expected struct `Box<dyn Fn(i32) -> u8>`
|
= note: expected struct `Box<dyn Fn(i32) -> u8>`
|
||||||
found struct `Box<{closure@$DIR/coerce-expect-unsized-ascribed.rs:27:36: 27:39}>`
|
found struct `Box<{closure@$DIR/coerce-expect-unsized-ascribed.rs:27:36: 27:39}>`
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0271]: type mismatch resolving `<Result<Result<(), Result<Result<(), Result<Result<(), Option<{integer}>>, ...>>, ...>>, ...> as Future>::Error == Foo`
|
error[E0271]: type mismatch resolving `<Result<..., ()> as Future>::Error == Foo`
|
||||||
--> $DIR/E0271.rs:20:5
|
--> $DIR/E0271.rs:20:5
|
||||||
|
|
|
|
||||||
LL | / Box::new(
|
LL | / Box::new(
|
||||||
|
@ -7,14 +7,16 @@ LL | | Err::<(), _>(
|
||||||
LL | | Ok::<_, ()>(
|
LL | | Ok::<_, ()>(
|
||||||
... |
|
... |
|
||||||
LL | | )
|
LL | | )
|
||||||
| |_____^ type mismatch resolving `<Result<Result<(), Result<Result<(), ...>, ...>>, ...> as Future>::Error == Foo`
|
| |_____^ type mismatch resolving `<Result<..., ()> as Future>::Error == Foo`
|
||||||
|
|
|
|
||||||
note: expected this to be `Foo`
|
note: expected this to be `Foo`
|
||||||
--> $DIR/E0271.rs:10:18
|
--> $DIR/E0271.rs:10:18
|
||||||
|
|
|
|
||||||
LL | type Error = E;
|
LL | type Error = E;
|
||||||
| ^
|
| ^
|
||||||
= note: required for the cast from `Box<Result<Result<(), Result<Result<(), Result<Result<(), Option<{integer}>>, ()>>, ()>>, ()>>` to `Box<(dyn Future<Error = Foo> + 'static)>`
|
= note: required for the cast from `Box<Result<..., ()>>` to `Box<...>`
|
||||||
|
= note: the full name for the type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271.ascii/E0271.long-type-hash.txt'
|
||||||
|
= note: consider using `--verbose` to print the full type name to the console
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//@ revisions: ascii unicode
|
//@ revisions: ascii unicode
|
||||||
//@[ascii] compile-flags: --diagnostic-width=40
|
//@[ascii] compile-flags: --diagnostic-width=40 -Zwrite-long-types-to-disk=yes
|
||||||
//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=40
|
//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=40 -Zwrite-long-types-to-disk=yes
|
||||||
//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
|
//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
|
||||||
trait Future {
|
trait Future {
|
||||||
type Error;
|
type Error;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0271]: type mismatch resolving `<Result<Result<(), Result<Result<(), Result<Result<(), Option<{integer}>>, ...>>, ...>>, ...> as Future>::Error == Foo`
|
error[E0271]: type mismatch resolving `<Result<..., ()> as Future>::Error == Foo`
|
||||||
╭▸ $DIR/E0271.rs:20:5
|
╭▸ $DIR/E0271.rs:20:5
|
||||||
│
|
│
|
||||||
LL │ ┏ Box::new(
|
LL │ ┏ Box::new(
|
||||||
|
@ -7,14 +7,16 @@ LL │ ┃ Err::<(), _>(
|
||||||
LL │ ┃ Ok::<_, ()>(
|
LL │ ┃ Ok::<_, ()>(
|
||||||
‡ ┃
|
‡ ┃
|
||||||
LL │ ┃ )
|
LL │ ┃ )
|
||||||
│ ┗━━━━━┛ type mismatch resolving `<Result<Result<(), Result<Result<(), ...>, ...>>, ...> as Future>::Error == Foo`
|
│ ┗━━━━━┛ type mismatch resolving `<Result<..., ()> as Future>::Error == Foo`
|
||||||
╰╴
|
╰╴
|
||||||
note: expected this to be `Foo`
|
note: expected this to be `Foo`
|
||||||
╭▸ $DIR/E0271.rs:10:18
|
╭▸ $DIR/E0271.rs:10:18
|
||||||
│
|
│
|
||||||
LL │ type Error = E;
|
LL │ type Error = E;
|
||||||
│ ━
|
│ ━
|
||||||
╰ note: required for the cast from `Box<Result<Result<(), Result<Result<(), Result<Result<(), Option<{integer}>>, ()>>, ()>>, ()>>` to `Box<(dyn Future<Error = Foo> + 'static)>`
|
├ note: required for the cast from `Box<Result<..., ()>>` to `Box<...>`
|
||||||
|
├ note: the full name for the type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271.unicode/E0271.long-type-hash.txt'
|
||||||
|
╰ note: consider using `--verbose` to print the full type name to the console
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,11 @@ LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok...
|
||||||
LL | | Ok("")
|
LL | | Ok("")
|
||||||
LL | | ))))))))))))))))))))))))))))))
|
LL | | ))))))))))))))))))))))))))))))
|
||||||
LL | | ))))))))))))))))))))))))))))));
|
LL | | ))))))))))))))))))))))))))))));
|
||||||
| |__________________________________^ expected `Atype<Btype<..., ...>, ...>`, found `Result<Result<..., ...>, ...>`
|
| |__________________________________^ expected `Atype<Btype<Ctype<..., i32>, i32>, i32>`, found `Result<Result<Result<..., _>, _>, _>`
|
||||||
|
|
|
|
||||||
= note: expected struct `Atype<Btype<..., ...>, ...>`
|
= note: expected struct `Atype<Btype<..., i32>, i32>`
|
||||||
found enum `Result<Result<..., ...>, ...>`
|
found enum `Result<Result<..., _>, _>`
|
||||||
= note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
= 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
|
= note: consider using `--verbose` to print the full type name to the console
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
|
@ -32,11 +32,11 @@ LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
|
||||||
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
||||||
LL | | ))))))))))))))))))))))))))))))
|
LL | | ))))))))))))))))))))))))))))))
|
||||||
LL | | ))))))))))))))))))))))));
|
LL | | ))))))))))))))))))))))));
|
||||||
| |____________________________^ expected `Option<Result<..., ...>>`, found `Result<Result<..., ...>, ...>`
|
| |____________________________^ expected `Option<Result<Option<Option<...>>, _>>`, found `Result<Result<Result<..., _>, _>, _>`
|
||||||
|
|
|
|
||||||
= note: expected enum `Option<Result<..., ...>>`
|
= note: expected enum `Option<Result<Option<...>, _>>`
|
||||||
found enum `Result<Result<..., ...>, ...>`
|
found enum `Result<Result<..., _>, _>`
|
||||||
= note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
= 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
|
= note: consider using `--verbose` to print the full type name to the console
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
|
@ -50,13 +50,13 @@ LL | | Atype<
|
||||||
... |
|
... |
|
||||||
LL | | i32
|
LL | | i32
|
||||||
LL | | > = ();
|
LL | | > = ();
|
||||||
| | - ^^ expected `Atype<Btype<..., ...>, ...>`, found `()`
|
| | - ^^ expected `Atype<Btype<Ctype<..., i32>, i32>, i32>`, found `()`
|
||||||
| |_____|
|
| |_____|
|
||||||
| expected due to this
|
| expected due to this
|
||||||
|
|
|
|
||||||
= note: expected struct `Atype<Btype<..., ...>, ...>`
|
= note: expected struct `Atype<Btype<..., i32>, i32>`
|
||||||
found unit type `()`
|
found unit type `()`
|
||||||
= note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
= 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
|
= note: consider using `--verbose` to print the full type name to the console
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
|
@ -70,11 +70,11 @@ LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
|
||||||
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
||||||
LL | | ))))))))))))))))))))))))))))))
|
LL | | ))))))))))))))))))))))))))))))
|
||||||
LL | | ))))))))))))))))))))))));
|
LL | | ))))))))))))))))))))))));
|
||||||
| |____________________________^ expected `()`, found `Result<Result<..., ...>, ...>`
|
| |____________________________^ expected `()`, found `Result<Result<Result<..., _>, _>, _>`
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found enum `Result<Result<..., ...>, ...>`
|
found enum `Result<Result<..., _>, _>`
|
||||||
= note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
= 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
|
= note: consider using `--verbose` to print the full type name to the console
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
|
@ -16,11 +16,11 @@ LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O…
|
||||||
LL │ ┃ Ok("")
|
LL │ ┃ Ok("")
|
||||||
LL │ ┃ ))))))))))))))))))))))))))))))
|
LL │ ┃ ))))))))))))))))))))))))))))))
|
||||||
LL │ ┃ ))))))))))))))))))))))))))))));
|
LL │ ┃ ))))))))))))))))))))))))))))));
|
||||||
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Atype<Btype<..., ...>, ...>`, found `Result<Result<..., ...>, ...>`
|
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Atype<Btype<Ctype<..., i32>, i32>, i32>`, found `Result<Result<Result<..., _>, _>, _>`
|
||||||
│
|
│
|
||||||
├ note: expected struct `Atype<Btype<..., ...>, ...>`
|
├ note: expected struct `Atype<Btype<..., i32>, i32>`
|
||||||
│ found enum `Result<Result<..., ...>, ...>`
|
│ found enum `Result<Result<..., _>, _>`
|
||||||
├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
├ 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
|
╰ note: consider using `--verbose` to print the full type name to the console
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
|
@ -32,11 +32,11 @@ LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok…
|
||||||
LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
||||||
LL │ ┃ ))))))))))))))))))))))))))))))
|
LL │ ┃ ))))))))))))))))))))))))))))))
|
||||||
LL │ ┃ ))))))))))))))))))))))));
|
LL │ ┃ ))))))))))))))))))))))));
|
||||||
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Option<Result<..., ...>>`, found `Result<Result<..., ...>, ...>`
|
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Option<Result<Option<Option<...>>, _>>`, found `Result<Result<Result<..., _>, _>, _>`
|
||||||
│
|
│
|
||||||
├ note: expected enum `Option<Result<..., ...>>`
|
├ note: expected enum `Option<Result<Option<...>, _>>`
|
||||||
│ found enum `Result<Result<..., ...>, ...>`
|
│ found enum `Result<Result<..., _>, _>`
|
||||||
├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
├ 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
|
╰ note: consider using `--verbose` to print the full type name to the console
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
|
@ -50,13 +50,13 @@ LL │ │ Atype<
|
||||||
‡ │
|
‡ │
|
||||||
LL │ │ i32
|
LL │ │ i32
|
||||||
LL │ │ > = ();
|
LL │ │ > = ();
|
||||||
│ │ │ ━━ expected `Atype<Btype<..., ...>, ...>`, found `()`
|
│ │ │ ━━ expected `Atype<Btype<Ctype<..., i32>, i32>, i32>`, found `()`
|
||||||
│ └─────┤
|
│ └─────┤
|
||||||
│ expected due to this
|
│ expected due to this
|
||||||
│
|
│
|
||||||
├ note: expected struct `Atype<Btype<..., ...>, ...>`
|
├ note: expected struct `Atype<Btype<..., i32>, i32>`
|
||||||
│ found unit type `()`
|
│ found unit type `()`
|
||||||
├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
├ 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
|
╰ note: consider using `--verbose` to print the full type name to the console
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
|
@ -70,11 +70,11 @@ LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok…
|
||||||
LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
||||||
LL │ ┃ ))))))))))))))))))))))))))))))
|
LL │ ┃ ))))))))))))))))))))))))))))))
|
||||||
LL │ ┃ ))))))))))))))))))))))));
|
LL │ ┃ ))))))))))))))))))))))));
|
||||||
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `()`, found `Result<Result<..., ...>, ...>`
|
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `()`, found `Result<Result<Result<..., _>, _>, _>`
|
||||||
│
|
│
|
||||||
├ note: expected unit type `()`
|
├ note: expected unit type `()`
|
||||||
│ found enum `Result<Result<..., ...>, ...>`
|
│ found enum `Result<Result<..., _>, _>`
|
||||||
├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
├ 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
|
╰ note: consider using `--verbose` to print the full type name to the console
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
15
tests/ui/diagnostic-width/long-e0277.rs
Normal file
15
tests/ui/diagnostic-width/long-e0277.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
//@ 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);
|
||||||
|
|
||||||
|
trait Trait {}
|
||||||
|
|
||||||
|
fn require_trait<T: Trait>() {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
require_trait::<D>(); //~ ERROR the trait bound `(...
|
||||||
|
}
|
23
tests/ui/diagnostic-width/long-e0277.stderr
Normal file
23
tests/ui/diagnostic-width/long-e0277.stderr
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
error[E0277]: the trait bound `(..., ..., ..., ...): Trait` is not satisfied
|
||||||
|
--> $DIR/long-e0277.rs:14:21
|
||||||
|
|
|
||||||
|
LL | require_trait::<D>();
|
||||||
|
| ^ unsatisfied trait bound
|
||||||
|
|
|
||||||
|
= help: the trait `Trait` is not implemented for `(..., ..., ..., ...)`
|
||||||
|
help: this trait has no implementations, consider adding one
|
||||||
|
--> $DIR/long-e0277.rs:9:1
|
||||||
|
|
|
||||||
|
LL | trait Trait {}
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
note: required by a bound in `require_trait`
|
||||||
|
--> $DIR/long-e0277.rs:11:21
|
||||||
|
|
|
||||||
|
LL | fn require_trait<T: Trait>() {}
|
||||||
|
| ^^^^^ required by this bound in `require_trait`
|
||||||
|
= 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 E0277`.
|
|
@ -2,13 +2,13 @@ error[E0382]: use of moved value: `x`
|
||||||
--> $DIR/non-copy-type-moved.rs:16:14
|
--> $DIR/non-copy-type-moved.rs:16:14
|
||||||
|
|
|
|
||||||
LL | fn foo(x: D) {
|
LL | fn foo(x: D) {
|
||||||
| - move occurs because `x` has type `((..., ..., ..., ...), ..., ..., ...)`, which does not implement the `Copy` trait
|
| - move occurs because `x` has type `(..., ..., ..., ...)`, which does not implement the `Copy` trait
|
||||||
LL | let _a = x;
|
LL | let _a = x;
|
||||||
| - value moved here
|
| - value moved here
|
||||||
LL | let _b = x;
|
LL | let _b = x;
|
||||||
| ^ value used here after move
|
| ^ value used here after move
|
||||||
|
|
|
|
||||||
= note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
= 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
|
= note: consider using `--verbose` to print the full type name to the console
|
||||||
help: consider cloning the value if the performance cost is acceptable
|
help: consider cloning the value if the performance cost is acceptable
|
||||||
|
|
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ fn foo(x: D) {
|
||||||
//~^ NOTE this expression has type `((...,
|
//~^ NOTE this expression has type `((...,
|
||||||
//~| NOTE expected `((...,
|
//~| NOTE expected `((...,
|
||||||
//~| NOTE expected tuple
|
//~| NOTE expected tuple
|
||||||
//~| NOTE the full type name has been written to
|
//~| NOTE the full name for the type has been written to
|
||||||
//~| NOTE consider using `--verbose` to print the full type name to the console
|
//~| NOTE consider using `--verbose` to print the full type name to the console
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ LL | let () = x;
|
||||||
|
|
|
|
||||||
= note: expected tuple `((..., ..., ..., ...), ..., ..., ...)`
|
= note: expected tuple `((..., ..., ..., ...), ..., ..., ...)`
|
||||||
found unit type `()`
|
found unit type `()`
|
||||||
= note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
= 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
|
= note: consider using `--verbose` to print the full type name to the console
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -11,7 +11,7 @@ LL | | ),
|
||||||
LL | | ) {
|
LL | | ) {
|
||||||
| |_- expected `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` because of return type
|
| |_- expected `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` because of return type
|
||||||
LL | f
|
LL | f
|
||||||
| ^ expected `&dyn Fn(&dyn Fn(&dyn Fn(&...)))`, found `&dyn Fn(u32)`
|
| ^ expected `&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&...))))`, found `&dyn Fn(u32)`
|
||||||
|
|
|
|
||||||
= note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))`
|
= note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))`
|
||||||
found reference `&dyn Fn(u32)`
|
found reference `&dyn Fn(u32)`
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/box-future-wrong-output.rs:20:39
|
--> $DIR/box-future-wrong-output.rs:20:39
|
||||||
|
|
|
|
||||||
LL | let _: BoxFuture<'static, bool> = async {}.boxed();
|
LL | let _: BoxFuture<'static, bool> = async {}.boxed();
|
||||||
| ------------------------ ^^^^^^^^^^^^^^^^ expected `bool`, found `()`
|
| ------------------------ ^^^^^^^^^^^^^^^^ expected `Pin<Box<...>>`, found `Pin<Box<dyn Future<Output = ()> + Send>>`
|
||||||
| |
|
| |
|
||||||
| expected due to this
|
| expected due to this
|
||||||
|
|
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ error[E0308]: mismatched types
|
||||||
LL | fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
LL | fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||||
| - found this type parameter
|
| - found this type parameter
|
||||||
LL | Pin::new(x)
|
LL | Pin::new(x)
|
||||||
| -------- ^ expected `Box<dyn Future<Output = ...> + Send>`, found type parameter `F`
|
| -------- ^ expected `Box<dyn Future<Output = i32> + Send>`, found type parameter `F`
|
||||||
| |
|
| |
|
||||||
| arguments to this function are incorrect
|
| arguments to this function are incorrect
|
||||||
| help: use `Box::pin` to pin and box this expression: `Box::pin`
|
| help: use `Box::pin` to pin and box this expression: `Box::pin`
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/issue-107860.rs:3:36
|
--> $DIR/issue-107860.rs:3:36
|
||||||
|
|
|
|
||||||
LL | async fn str<T>(T: &str) -> &str { &str }
|
LL | async fn str<T>(T: &str) -> &str { &str }
|
||||||
| ^^^^ expected `&str`, found `&fn(&str) -> ... {str::<...>}`
|
| ^^^^ expected `&str`, found `&fn(&str) -> ... {str::<_>}`
|
||||||
|
|
|
|
||||||
= note: expected reference `&str`
|
= note: expected reference `&str`
|
||||||
found reference `&for<'a> fn(&'a str) -> impl Future<Output = &'a str> {str::<_>}`
|
found reference `&for<'a> fn(&'a str) -> impl Future<Output = &'a str> {str::<_>}`
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0271]: type mismatch resolving `<dyn Pointee<Metadata = ()> as Pointee>::
|
||||||
--> $DIR/ice-with-dyn-pointee-errors.rs:9:33
|
--> $DIR/ice-with-dyn-pointee-errors.rs:9:33
|
||||||
|
|
|
|
||||||
LL | unknown_sized_object_ptr_in(x)
|
LL | unknown_sized_object_ptr_in(x)
|
||||||
| --------------------------- ^ expected `()`, found `DynMetadata<dyn Pointee<Metadata = ...>>`
|
| --------------------------- ^ expected `()`, found `DynMetadata<dyn Pointee<Metadata = ()>>`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/pretty.rs:36:79
|
--> $DIR/pretty.rs:36:79
|
||||||
|
|
|
|
||||||
LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x }
|
LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x }
|
||||||
| - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc2 = ...>`
|
| - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc2 = &u8>`
|
||||||
| |
|
| |
|
||||||
| help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>`
|
| help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>`
|
||||||
|
|
|
|
||||||
|
@ -132,7 +132,7 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/pretty.rs:38:73
|
--> $DIR/pretty.rs:38:73
|
||||||
|
|
|
|
||||||
LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x }
|
LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x }
|
||||||
| - ^ expected `()`, found `&dyn AnyDifferentBinders<Assoc = ...>`
|
| - ^ expected `()`, found `&dyn AnyDifferentBinders<Assoc = u8>`
|
||||||
| |
|
| |
|
||||||
| help: try adding a return type: `-> &dyn AnyDifferentBinders<Assoc = u8>`
|
| help: try adding a return type: `-> &dyn AnyDifferentBinders<Assoc = u8>`
|
||||||
|
|
|
|
||||||
|
|
|
@ -13,8 +13,6 @@ LL | | ))))))))))),
|
||||||
LL | | )))))))))))
|
LL | | )))))))))))
|
||||||
| |_______________- return type was inferred to be `Option<Option<Option<...>>>` here
|
| |_______________- return type was inferred to be `Option<Option<Option<...>>>` here
|
||||||
|
|
|
|
||||||
= 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
|
|
||||||
= help: the trait `std::fmt::Display` is not implemented for `Option<Option<Option<...>>>`
|
= help: the trait `std::fmt::Display` is not implemented for `Option<Option<Option<...>>>`
|
||||||
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
|
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
|
||||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||||
|
|
|
@ -6,7 +6,7 @@ LL | map.insert(1, Struct::do_something);
|
||||||
| |
|
| |
|
||||||
| ... which causes `map` to have type `HashMap<{integer}, fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
|
| ... which causes `map` to have type `HashMap<{integer}, fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
|
||||||
LL | Self { map }
|
LL | Self { map }
|
||||||
| ^^^ expected `HashMap<u16, fn(u8) -> Pin<...>>`, found `HashMap<{integer}, ...>`
|
| ^^^ expected `HashMap<u16, fn(u8) -> Pin<Box<...>>>`, found `HashMap<{integer}, ...>`
|
||||||
|
|
|
|
||||||
= note: expected struct `HashMap<u16, fn(_) -> Pin<Box<(dyn Future<Output = ()> + Send + 'static)>>>`
|
= note: expected struct `HashMap<u16, fn(_) -> Pin<Box<(dyn Future<Output = ()> + Send + 'static)>>>`
|
||||||
found struct `HashMap<{integer}, fn(_) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
|
found struct `HashMap<{integer}, fn(_) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
fn foo() { //~ HELP try adding a return type
|
fn foo() { //~ HELP try adding a return type
|
||||||
vec!['a'].iter().map(|c| c)
|
vec!['a'].iter().map(|c| c)
|
||||||
//~^ ERROR mismatched types [E0308]
|
//~^ ERROR mismatched types [E0308]
|
||||||
//~| NOTE expected `()`, found `Map<Iter<'_, char>, ...>`
|
//~| NOTE expected `()`, found `Map<Iter<'_, char>, {closure@...}>`
|
||||||
//~| NOTE expected unit type `()`
|
//~| NOTE expected unit type `()`
|
||||||
//~| HELP consider using a semicolon here
|
//~| HELP consider using a semicolon here
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/return_type_containing_closure.rs:3:5
|
--> $DIR/return_type_containing_closure.rs:3:5
|
||||||
|
|
|
|
||||||
LL | vec!['a'].iter().map(|c| c)
|
LL | vec!['a'].iter().map(|c| c)
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Map<Iter<'_, char>, ...>`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Map<Iter<'_, char>, {closure@...}>`
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found struct `Map<std::slice::Iter<'_, char>, {closure@$DIR/return_type_containing_closure.rs:3:26: 3:29}>`
|
found struct `Map<std::slice::Iter<'_, char>, {closure@$DIR/return_type_containing_closure.rs:3:26: 3:29}>`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue