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
|
@ -435,7 +435,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
|
||||
terr: TypeError<'tcx>,
|
||||
param_env: Option<ParamEnv<'tcx>>,
|
||||
path: &mut Option<PathBuf>,
|
||||
) {
|
||||
match *cause.code() {
|
||||
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)),
|
||||
);
|
||||
} 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}`"));
|
||||
}
|
||||
}
|
||||
|
@ -1545,7 +1544,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
(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.
|
||||
// NOTE(eddyb) this was `.cancel()`, but `diag`
|
||||
// is borrowed, so we can't fully defuse it.
|
||||
|
@ -1600,9 +1599,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut path = None;
|
||||
if let Some((expected, found, p)) = expected_found {
|
||||
path = p;
|
||||
if let Some((expected, found)) = expected_found {
|
||||
let (expected_label, found_label, exp_found) = match exp_found {
|
||||
Mismatch::Variable(ef) => (
|
||||
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
|
||||
// thing.
|
||||
self.note_error_origin(diag, cause, exp_found, terr, param_env, &mut path);
|
||||
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");
|
||||
}
|
||||
self.note_error_origin(diag, cause, exp_found, terr, param_env);
|
||||
|
||||
debug!(?diag);
|
||||
}
|
||||
|
@ -1891,6 +1884,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&self,
|
||||
trace: &TypeTrace<'tcx>,
|
||||
terr: TypeError<'tcx>,
|
||||
path: &mut Option<PathBuf>,
|
||||
) -> Vec<TypeErrorAdditionalDiags> {
|
||||
let mut suggestions = Vec::new();
|
||||
let span = trace.cause.span;
|
||||
|
@ -1969,7 +1963,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
})
|
||||
| ObligationCauseCode::BlockTailExpression(.., source)) = code
|
||||
&& 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 {
|
||||
found: found_ty.content(),
|
||||
|
@ -2048,12 +2042,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
|
||||
|
||||
let span = trace.cause.span;
|
||||
let mut path = None;
|
||||
let failure_code = trace.cause.as_failure_code_diag(
|
||||
terr,
|
||||
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);
|
||||
*diag.long_ty_path() = path;
|
||||
self.note_type_err(
|
||||
&mut diag,
|
||||
&trace.cause,
|
||||
|
@ -2098,10 +2094,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&self,
|
||||
values: ValuePairs<'tcx>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
|
||||
file: &mut Option<PathBuf>,
|
||||
) -> Option<(DiagStyledString, DiagStyledString)> {
|
||||
match values {
|
||||
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::ExistentialTraitRef(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(),
|
||||
};
|
||||
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)
|
||||
}
|
||||
ret => ret,
|
||||
|
@ -2133,9 +2130,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
(None, None)
|
||||
};
|
||||
|
||||
let (exp, fnd) =
|
||||
self.cmp_fn_sig(&exp_found.expected, fn_def1, &exp_found.found, fn_def2);
|
||||
Some((exp, fnd, None))
|
||||
Some(self.cmp_fn_sig(&exp_found.expected, fn_def1, &exp_found.found, fn_def2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2143,7 +2138,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
fn expected_found_str_term(
|
||||
&self,
|
||||
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);
|
||||
if exp_found.references_error() {
|
||||
return None;
|
||||
|
@ -2158,21 +2154,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
let len = self.tcx.sess().diagnostic_width() + 40;
|
||||
let exp_s = exp.content();
|
||||
let fnd_s = fnd.content();
|
||||
let mut path = None;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
(exp, fnd, path)
|
||||
(exp, fnd)
|
||||
}
|
||||
_ => (
|
||||
DiagStyledString::highlighted(exp_found.expected.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>>>(
|
||||
&self,
|
||||
exp_found: ty::error::ExpectedFound<T>,
|
||||
) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
|
||||
) -> Option<(DiagStyledString, DiagStyledString)> {
|
||||
let exp_found = self.resolve_vars_if_possible(exp_found);
|
||||
if exp_found.references_error() {
|
||||
return None;
|
||||
|
@ -2190,7 +2184,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
Some((
|
||||
DiagStyledString::highlighted(exp_found.expected.to_string()),
|
||||
DiagStyledString::highlighted(exp_found.found.to_string()),
|
||||
None,
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
@ -713,7 +713,7 @@ impl<'tcx> InferSourceKind<'tcx> {
|
|||
if ty.is_closure() {
|
||||
("closure", closure_as_fn_str(infcx, ty), path)
|
||||
} 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 {
|
||||
("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 {
|
||||
span: trace.cause.span,
|
||||
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),
|
||||
infer::Reborrow(span) => {
|
||||
|
@ -946,10 +946,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
|
||||
if let infer::Subtype(ref sup_trace) = sup_origin
|
||||
&& let infer::Subtype(ref sub_trace) = sub_origin
|
||||
&& let Some((sup_expected, sup_found, _)) =
|
||||
self.values_str(sup_trace.values, &sup_trace.cause)
|
||||
&& let Some((sub_expected, sub_found, _)) =
|
||||
self.values_str(sub_trace.values, &sup_trace.cause)
|
||||
&& let Some((sup_expected, sup_found)) =
|
||||
self.values_str(sup_trace.values, &sup_trace.cause, err.long_ty_path())
|
||||
&& let Some((sub_expected, sub_found)) =
|
||||
self.values_str(sub_trace.values, &sup_trace.cause, err.long_ty_path())
|
||||
&& sub_expected == sup_expected
|
||||
&& sub_found == sup_found
|
||||
{
|
||||
|
|
|
@ -163,6 +163,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
|
||||
let predicate = self.resolve_vars_if_possible(obligation.predicate);
|
||||
let span = obligation.cause.span;
|
||||
let mut file = None;
|
||||
|
||||
debug!(?predicate, obligation.cause.code = ?obligation.cause.code());
|
||||
|
||||
|
@ -245,7 +246,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
span,
|
||||
E0283,
|
||||
"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();
|
||||
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 =
|
||||
self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap());
|
||||
if impl_candidates.len() < 40 {
|
||||
|
@ -524,6 +526,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
.iter()
|
||||
.chain(Some(data.term.into_arg()))
|
||||
.find(|g| g.has_non_region_infer());
|
||||
let predicate = self.tcx.short_string(predicate, &mut file);
|
||||
if let Some(arg) = arg {
|
||||
self.emit_inference_failure_err(
|
||||
obligation.cause.body_id,
|
||||
|
@ -539,8 +542,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
self.dcx(),
|
||||
span,
|
||||
E0284,
|
||||
"type annotations needed: cannot satisfy `{}`",
|
||||
predicate,
|
||||
"type annotations needed: cannot satisfy `{predicate}`",
|
||||
)
|
||||
.with_span_label(span, format!("cannot satisfy `{predicate}`"))
|
||||
}
|
||||
|
@ -565,12 +567,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
err
|
||||
} else {
|
||||
// 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!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0284,
|
||||
"type annotations needed: cannot satisfy `{}`",
|
||||
predicate,
|
||||
"type annotations needed: 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() {
|
||||
return e;
|
||||
}
|
||||
let alias = self.tcx.short_string(alias, &mut file);
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
|
@ -603,16 +606,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
if let Some(e) = self.tainted_by_errors() {
|
||||
return e;
|
||||
}
|
||||
let predicate = self.tcx.short_string(predicate, &mut file);
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0284,
|
||||
"type annotations needed: cannot satisfy `{}`",
|
||||
predicate,
|
||||
"type annotations needed: cannot satisfy `{predicate}`",
|
||||
)
|
||||
.with_span_label(span, format!("cannot satisfy `{predicate}`"))
|
||||
}
|
||||
};
|
||||
*err.long_ty_path() = file;
|
||||
self.note_obligation_cause(&mut err, obligation);
|
||||
err.emit()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use core::ops::ControlFlow;
|
||||
use std::borrow::Cow;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use rustc_ast::TraitObjectSyntax;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
@ -9,7 +10,6 @@ use rustc_errors::{
|
|||
Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions,
|
||||
pluralize, struct_span_code_err,
|
||||
};
|
||||
use rustc_hir::def::Namespace;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
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::fold::{TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::print::{
|
||||
FmtPrinter, Print, PrintPolyTraitPredicateExt, PrintTraitPredicateExt as _,
|
||||
PrintTraitRefExt as _, with_forced_trimmed_paths,
|
||||
PrintPolyTraitPredicateExt, PrintTraitPredicateExt as _, PrintTraitRefExt as _,
|
||||
with_forced_trimmed_paths,
|
||||
};
|
||||
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
|
@ -60,6 +60,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
) -> ErrorGuaranteed {
|
||||
let tcx = self.tcx;
|
||||
let mut span = obligation.cause.span;
|
||||
let mut long_ty_file = None;
|
||||
|
||||
let mut err = match *error {
|
||||
SelectionError::Unimplemented => {
|
||||
|
@ -169,11 +170,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
if let Err(guar) = self.fn_arg_obligation(&obligation) {
|
||||
return guar;
|
||||
}
|
||||
let mut file = None;
|
||||
let (post_message, pre_message, type_def) = self
|
||||
.get_parent_trait_ref(obligation.cause.code())
|
||||
.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!("within `{t}`, "),
|
||||
|
@ -181,12 +181,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
)
|
||||
})
|
||||
.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 {
|
||||
message,
|
||||
|
@ -223,6 +217,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
None,
|
||||
append_const_msg,
|
||||
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)
|
||||
|
@ -251,14 +246,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
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;
|
||||
if is_try_conversion {
|
||||
suggested = self.try_conversion_context(&obligation, main_trait_predicate, &mut err);
|
||||
|
@ -309,7 +298,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
return err.emit();
|
||||
}
|
||||
|
||||
file_note.map(|note| err.note(note));
|
||||
if let Some(s) = label {
|
||||
// If it has a custom `#[rustc_on_unimplemented]`
|
||||
// error message, let's display it as the label!
|
||||
|
@ -762,14 +750,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
trait_ref: predicate.trait_ref,
|
||||
polarity: ty::PredicatePolarity::Positive,
|
||||
});
|
||||
let mut file = None;
|
||||
let err_msg = self.get_standard_error_message(
|
||||
trait_ref,
|
||||
None,
|
||||
Some(predicate.constness()),
|
||||
None,
|
||||
String::new(),
|
||||
&mut file,
|
||||
);
|
||||
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(
|
||||
self.tcx,
|
||||
ObligationCause::dummy(),
|
||||
|
@ -1381,6 +1372,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
_ => (None, error.err),
|
||||
};
|
||||
|
||||
let mut file = None;
|
||||
let (msg, span, closure_span) = values
|
||||
.and_then(|(predicate, normalized_term, expected_term)| {
|
||||
self.maybe_detailed_projection_msg(
|
||||
|
@ -1388,24 +1380,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
predicate,
|
||||
normalized_term,
|
||||
expected_term,
|
||||
&mut file,
|
||||
)
|
||||
})
|
||||
.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 `{}`", {
|
||||
self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap();
|
||||
cx.into_buffer()
|
||||
})),
|
||||
with_forced_trimmed_paths!(format!(
|
||||
"type mismatch resolving `{}`",
|
||||
self.tcx
|
||||
.short_string(self.resolve_vars_if_possible(predicate), &mut file),
|
||||
)),
|
||||
obligation.cause.span,
|
||||
None,
|
||||
)
|
||||
});
|
||||
let mut diag = struct_span_code_err!(self.dcx(), span, E0271, "{msg}");
|
||||
*diag.long_ty_path() = file;
|
||||
if let Some(span) = closure_span {
|
||||
// Mark the closure decl so that it is seen even if we are pointing at the return
|
||||
// type or expression.
|
||||
|
@ -1471,15 +1461,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
ty.span,
|
||||
with_forced_trimmed_paths!(Cow::from(format!(
|
||||
"type mismatch resolving `{}`",
|
||||
{
|
||||
let mut cx = FmtPrinter::new_with_limit(
|
||||
self.tcx,
|
||||
Namespace::TypeNS,
|
||||
rustc_session::Limit(5),
|
||||
);
|
||||
self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap();
|
||||
cx.into_buffer()
|
||||
}
|
||||
self.tcx.short_string(
|
||||
self.resolve_vars_if_possible(predicate),
|
||||
diag.long_ty_path()
|
||||
),
|
||||
))),
|
||||
true,
|
||||
)),
|
||||
|
@ -1512,6 +1497,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
projection_term: ty::AliasTerm<'tcx>,
|
||||
normalized_ty: ty::Term<'tcx>,
|
||||
expected_ty: ty::Term<'tcx>,
|
||||
file: &mut Option<PathBuf>,
|
||||
) -> Option<(String, Span, Option<Span>)> {
|
||||
let trait_def_id = projection_term.trait_def_id(self.tcx);
|
||||
let self_ty = projection_term.self_ty();
|
||||
|
@ -1552,7 +1538,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
};
|
||||
let item = match self_ty.kind() {
|
||||
ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
|
||||
_ => self_ty.to_string(),
|
||||
_ => self.tcx.short_string(self_ty, file),
|
||||
};
|
||||
Some((format!(
|
||||
"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 `"),
|
||||
]);
|
||||
if types_content.0 == types_content.1 {
|
||||
let ty =
|
||||
self.tcx.short_ty_string(obligation_trait_ref.self_ty(), &mut None);
|
||||
let ty = self
|
||||
.tcx
|
||||
.short_string(obligation_trait_ref.self_ty(), err.long_ty_path());
|
||||
msg.push(StringPart::normal(ty));
|
||||
} else {
|
||||
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
|
||||
// message, and fall back to regular note otherwise.
|
||||
if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
|
||||
let mut long_ty_file = None;
|
||||
self.note_obligation_cause_code(
|
||||
obligation.cause.body_id,
|
||||
err,
|
||||
|
@ -2351,15 +2337,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
obligation.cause.code(),
|
||||
&mut vec![],
|
||||
&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);
|
||||
if let Some(span) = err.span.primary_span()
|
||||
&& let Some(mut diag) =
|
||||
|
@ -2403,6 +2381,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
predicate_constness: Option<ty::BoundConstness>,
|
||||
append_const_msg: Option<AppendConstMessage>,
|
||||
post_message: String,
|
||||
long_ty_file: &mut Option<PathBuf>,
|
||||
) -> String {
|
||||
message
|
||||
.and_then(|cannot_do_this| {
|
||||
|
@ -2426,7 +2405,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
.unwrap_or_else(|| {
|
||||
format!(
|
||||
"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(..)
|
||||
| ObligationCauseCode::WhereClauseInExpr(..) = code
|
||||
{
|
||||
let mut long_ty_file = None;
|
||||
self.note_obligation_cause_code(
|
||||
error.obligation.cause.body_id,
|
||||
&mut diag,
|
||||
|
@ -315,17 +314,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
code,
|
||||
&mut vec![],
|
||||
&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()
|
||||
}
|
||||
|
|
|
@ -932,7 +932,7 @@ impl<'tcx> OnUnimplementedFormatString {
|
|||
let value = match param.kind {
|
||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
|
||||
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 {
|
||||
trait_ref.args[param.index as usize].to_string()
|
||||
}
|
||||
|
|
|
@ -141,7 +141,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
obligation.cause.span,
|
||||
suggest_increasing_limit,
|
||||
|err| {
|
||||
let mut long_ty_file = None;
|
||||
self.note_obligation_cause_code(
|
||||
obligation.cause.body_id,
|
||||
err,
|
||||
|
@ -150,17 +149,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
obligation.cause.code(),
|
||||
&mut vec![],
|
||||
&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::borrow::Cow;
|
||||
use std::iter;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use itertools::{EitherOrBoth, Itertools};
|
||||
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
|
||||
// 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 {
|
||||
err.note(msg);
|
||||
} else {
|
||||
err.messages = vec![(rustc_errors::DiagMessage::from(msg), Style::NoStyle)];
|
||||
}
|
||||
let mut file = None;
|
||||
err.span_label(
|
||||
span,
|
||||
format!(
|
||||
"the trait `{}` is not implemented for `{}`",
|
||||
old_pred.print_modifiers_and_trait_path(),
|
||||
self.tcx.short_ty_string(old_pred.self_ty().skip_binder(), &mut file),
|
||||
"the trait `{}` is not implemented for `{self_ty_str}`",
|
||||
old_pred.print_modifiers_and_trait_path()
|
||||
),
|
||||
);
|
||||
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 {
|
||||
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
|
||||
// bound that introduced the obligation (e.g. `T: Send`).
|
||||
debug!(?next_code);
|
||||
let mut long_ty_file = None;
|
||||
self.note_obligation_cause_code(
|
||||
obligation.cause.body_id,
|
||||
err,
|
||||
|
@ -2698,7 +2690,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
next_code.unwrap(),
|
||||
&mut Vec::new(),
|
||||
&mut Default::default(),
|
||||
&mut long_ty_file,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2711,7 +2702,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
cause_code: &ObligationCauseCode<'tcx>,
|
||||
obligated_types: &mut Vec<Ty<'tcx>>,
|
||||
seen_requirements: &mut FxHashSet<DefId>,
|
||||
long_ty_file: &mut Option<PathBuf>,
|
||||
) where
|
||||
T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
|
||||
{
|
||||
|
@ -2965,9 +2955,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
}
|
||||
ObligationCauseCode::Coercion { source, target } => {
|
||||
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 =
|
||||
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!(
|
||||
"required for the cast from `{source}` to `{target}`",
|
||||
)));
|
||||
|
@ -3252,7 +3242,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
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}`");
|
||||
match ty.kind() {
|
||||
ty::Adt(def, _) => match tcx.opt_item_ident(def.did()) {
|
||||
|
@ -3330,7 +3320,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&data.parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
} else {
|
||||
|
@ -3343,7 +3332,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
cause_code.peel_derives(),
|
||||
obligated_types,
|
||||
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);
|
||||
let parent_def_id = parent_trait_pred.def_id();
|
||||
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 msg = format!("required for `{self_ty_str}` to implement `{trait_name}`");
|
||||
let mut is_auto_trait = false;
|
||||
|
@ -3449,8 +3437,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
count,
|
||||
pluralize!(count)
|
||||
));
|
||||
let self_ty = tcx
|
||||
.short_ty_string(parent_trait_pred.skip_binder().self_ty(), long_ty_file);
|
||||
let self_ty = tcx.short_string(
|
||||
parent_trait_pred.skip_binder().self_ty(),
|
||||
err.long_ty_path(),
|
||||
);
|
||||
err.note(format!(
|
||||
"required for `{self_ty}` to implement `{}`",
|
||||
parent_trait_pred.print_modifiers_and_trait_path()
|
||||
|
@ -3466,7 +3456,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&data.parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
@ -3505,7 +3494,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&data.derived.parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
@ -3519,7 +3507,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&data.parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
@ -3536,7 +3523,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&data.parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
@ -3551,7 +3537,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
nested,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
let mut multispan = MultiSpan::from(span);
|
||||
|
@ -3582,7 +3567,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
@ -3622,7 +3606,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
}
|
||||
ObligationCauseCode::OpaqueReturnType(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);
|
||||
(expr_ty, expr)
|
||||
} 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()
|
||||
&& 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)
|
||||
} else {
|
||||
return;
|
||||
|
@ -5231,7 +5215,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
|
|||
format!(
|
||||
"{pre_message}the trait `{}` is not implemented for{desc} `{}`",
|
||||
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 {
|
||||
// "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue