Migrate placeholder_error.rs
This commit is contained in:
parent
8360a40a8a
commit
2118ff401f
3 changed files with 191 additions and 131 deletions
|
@ -183,3 +183,31 @@ infer_explicit_lifetime_required_sugg = add explicit lifetime `{$named}` to {$id
|
||||||
[ident] the type of `{$simple_ident}`
|
[ident] the type of `{$simple_ident}`
|
||||||
*[param_type] type
|
*[param_type] type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
infer_actual_impl_expl_1 = {$leading_ellipsis ->
|
||||||
|
[true] ...
|
||||||
|
*[false] {""}
|
||||||
|
}{$kind ->
|
||||||
|
[signature] closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
|
||||||
|
[passive] `{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`
|
||||||
|
*[other] `{$ty_or_sig}` must implement `{$trait_path}`
|
||||||
|
}{$lt_kind ->
|
||||||
|
[two] , for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
|
||||||
|
[any] , for any lifetime `'{$lifetime_1}`...
|
||||||
|
[some] , for some specific lifetime `'{lifetime_1}`...
|
||||||
|
*[nothing] {""}
|
||||||
|
}
|
||||||
|
|
||||||
|
infer_actual_impl_expl_2 = {$kind_2 ->
|
||||||
|
[implements_trait] ...but it actually implements `{$trait_path_2}`
|
||||||
|
[implemented_for_ty] ...but `{$trait_path_2}` is actually implemented for the type `{$ty}`
|
||||||
|
*[ty_implements] ...but `{$ty}` actually implements `{$trait_path_2}`
|
||||||
|
}{$has_lifetime ->
|
||||||
|
[true] , for some specific lifetime `'{$lifetime}`
|
||||||
|
*[false] {""}
|
||||||
|
}
|
||||||
|
|
||||||
|
infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
|
||||||
|
.label_satisfy = doesn't satisfy where-clause
|
||||||
|
.label_where = due to a where-clause on `{$def_id}`...
|
||||||
|
.label_dup = implementation of `{$trait_def_id}` is not general enough
|
||||||
|
|
|
@ -540,3 +540,44 @@ pub struct ExplicitLifetimeRequired<'a> {
|
||||||
#[skip_arg]
|
#[skip_arg]
|
||||||
pub new_ty: Ty<'a>,
|
pub new_ty: Ty<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(SessionSubdiagnostic)]
|
||||||
|
pub enum ActualImplExplNotes {
|
||||||
|
// Field names have to be different across all variants
|
||||||
|
#[note(infer::actual_impl_expl_1)]
|
||||||
|
NoteOne {
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
kind: &'static str,
|
||||||
|
ty_or_sig: String,
|
||||||
|
trait_path: String,
|
||||||
|
lt_kind: &'static str,
|
||||||
|
lifetime_1: usize,
|
||||||
|
lifetime_2: usize,
|
||||||
|
},
|
||||||
|
#[note(infer::actual_impl_expl_2)]
|
||||||
|
NoteTwo {
|
||||||
|
kind_2: &'static str,
|
||||||
|
trait_path_2: String,
|
||||||
|
has_lifetime: bool,
|
||||||
|
lifetime: usize,
|
||||||
|
ty: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[diag(infer::trait_placeholder_mismatch)]
|
||||||
|
pub struct TraitPlaceholderMismatch {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[label(infer::label_satisfy)]
|
||||||
|
pub satisfy_span: Option<Span>,
|
||||||
|
#[label(infer::label_where)]
|
||||||
|
pub where_span: Option<Span>,
|
||||||
|
#[label(infer::label_dup)]
|
||||||
|
pub dup_span: Option<Span>,
|
||||||
|
pub def_id: String,
|
||||||
|
pub trait_def_id: String,
|
||||||
|
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub actual_impl_expl_notes: Vec<ActualImplExplNotes>,
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
use crate::errors::{ActualImplExplNotes, TraitPlaceholderMismatch};
|
||||||
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||||
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
||||||
use crate::infer::ValuePairs;
|
use crate::infer::ValuePairs;
|
||||||
use crate::infer::{SubregionOrigin, TypeTrace};
|
use crate::infer::{SubregionOrigin, TypeTrace};
|
||||||
use crate::traits::{ObligationCause, ObligationCauseCode};
|
use crate::traits::{ObligationCause, ObligationCauseCode};
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
|
||||||
use rustc_hir::def::Namespace;
|
use rustc_hir::def::Namespace;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::ty::error::ExpectedFound;
|
use rustc_middle::ty::error::ExpectedFound;
|
||||||
|
@ -12,7 +13,7 @@ use rustc_middle::ty::print::{FmtPrinter, Print, RegionHighlightMode};
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_middle::ty::{self, RePlaceholder, ReVar, Region, TyCtxt};
|
use rustc_middle::ty::{self, RePlaceholder, ReVar, Region, TyCtxt};
|
||||||
|
|
||||||
use std::fmt::{self, Write};
|
use std::fmt;
|
||||||
|
|
||||||
impl<'tcx> NiceRegionError<'_, 'tcx> {
|
impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
/// When given a `ConcreteFailure` for a function with arguments containing a named region and
|
/// When given a `ConcreteFailure` for a function with arguments containing a named region and
|
||||||
|
@ -205,25 +206,20 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
actual_substs: SubstsRef<'tcx>,
|
actual_substs: SubstsRef<'tcx>,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
let span = cause.span();
|
let span = cause.span();
|
||||||
let msg = format!(
|
|
||||||
"implementation of `{}` is not general enough",
|
|
||||||
self.tcx().def_path_str(trait_def_id),
|
|
||||||
);
|
|
||||||
let mut err = self.tcx().sess.struct_span_err(span, &msg);
|
|
||||||
|
|
||||||
let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id)
|
let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) =
|
||||||
| ObligationCauseCode::ExprItemObligation(def_id, ..) =
|
if let ObligationCauseCode::ItemObligation(def_id)
|
||||||
*cause.code()
|
| ObligationCauseCode::ExprItemObligation(def_id, ..) = *cause.code()
|
||||||
{
|
{
|
||||||
err.span_label(span, "doesn't satisfy where-clause");
|
(
|
||||||
err.span_label(
|
true,
|
||||||
self.tcx().def_span(def_id),
|
Some(span),
|
||||||
&format!("due to a where-clause on `{}`...", self.tcx().def_path_str(def_id)),
|
Some(self.tcx().def_span(def_id)),
|
||||||
);
|
None,
|
||||||
true
|
self.tcx().def_path_str(def_id),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
err.span_label(span, &msg);
|
(false, None, None, Some(span), String::new())
|
||||||
false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let expected_trait_ref = self
|
let expected_trait_ref = self
|
||||||
|
@ -284,8 +280,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
?expected_self_ty_has_vid,
|
?expected_self_ty_has_vid,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.explain_actual_impl_that_was_found(
|
let actual_impl_expl_notes = self.explain_actual_impl_that_was_found(
|
||||||
&mut err,
|
|
||||||
sub_placeholder,
|
sub_placeholder,
|
||||||
sup_placeholder,
|
sup_placeholder,
|
||||||
has_sub,
|
has_sub,
|
||||||
|
@ -299,7 +294,17 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
leading_ellipsis,
|
leading_ellipsis,
|
||||||
);
|
);
|
||||||
|
|
||||||
err
|
let diag = TraitPlaceholderMismatch {
|
||||||
|
span,
|
||||||
|
satisfy_span,
|
||||||
|
where_span,
|
||||||
|
dup_span,
|
||||||
|
def_id,
|
||||||
|
trait_def_id: self.tcx().def_path_str(trait_def_id),
|
||||||
|
actual_impl_expl_notes,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.tcx().sess.create_err(diag)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add notes with details about the expected and actual trait refs, with attention to cases
|
/// Add notes with details about the expected and actual trait refs, with attention to cases
|
||||||
|
@ -309,7 +314,6 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
/// due to the number of combinations we have to deal with.
|
/// due to the number of combinations we have to deal with.
|
||||||
fn explain_actual_impl_that_was_found(
|
fn explain_actual_impl_that_was_found(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
|
||||||
sub_placeholder: Option<Region<'tcx>>,
|
sub_placeholder: Option<Region<'tcx>>,
|
||||||
sup_placeholder: Option<Region<'tcx>>,
|
sup_placeholder: Option<Region<'tcx>>,
|
||||||
has_sub: Option<usize>,
|
has_sub: Option<usize>,
|
||||||
|
@ -321,7 +325,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
actual_has_vid: Option<usize>,
|
actual_has_vid: Option<usize>,
|
||||||
any_self_ty_has_vid: bool,
|
any_self_ty_has_vid: bool,
|
||||||
leading_ellipsis: bool,
|
leading_ellipsis: bool,
|
||||||
) {
|
) -> Vec<ActualImplExplNotes> {
|
||||||
// HACK(eddyb) maybe move this in a more central location.
|
// HACK(eddyb) maybe move this in a more central location.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct Highlighted<'tcx, T> {
|
struct Highlighted<'tcx, T> {
|
||||||
|
@ -380,7 +384,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
|
let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
|
||||||
expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
|
expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
|
||||||
expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
|
expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
|
||||||
err.note(&{
|
|
||||||
let passive_voice = match (has_sub, has_sup) {
|
let passive_voice = match (has_sub, has_sup) {
|
||||||
(Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
|
(Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
|
||||||
(None, None) => {
|
(None, None) => {
|
||||||
|
@ -392,7 +396,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut note = if same_self_type {
|
let (kind, ty_or_sig, trait_path) = if same_self_type {
|
||||||
let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty());
|
let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty());
|
||||||
self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);
|
self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);
|
||||||
|
|
||||||
|
@ -409,91 +413,78 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
bug!("type is not longer closure");
|
bug!("type is not longer closure");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
(
|
||||||
format!(
|
"signature",
|
||||||
"{}closure with signature `{}` must implement `{}`",
|
closure_sig.to_string(),
|
||||||
if leading_ellipsis { "..." } else { "" },
|
expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(),
|
||||||
closure_sig,
|
|
||||||
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
format!(
|
(
|
||||||
"{}`{}` must implement `{}`",
|
"other",
|
||||||
if leading_ellipsis { "..." } else { "" },
|
self_ty.to_string(),
|
||||||
self_ty,
|
expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(),
|
||||||
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if passive_voice {
|
} else if passive_voice {
|
||||||
format!(
|
(
|
||||||
"{}`{}` would have to be implemented for the type `{}`",
|
"passive",
|
||||||
if leading_ellipsis { "..." } else { "" },
|
expected_trait_ref.map(|tr| tr.self_ty()).to_string(),
|
||||||
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
|
expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(),
|
||||||
expected_trait_ref.map(|tr| tr.self_ty()),
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
format!(
|
(
|
||||||
"{}`{}` must implement `{}`",
|
"other",
|
||||||
if leading_ellipsis { "..." } else { "" },
|
expected_trait_ref.map(|tr| tr.self_ty()).to_string(),
|
||||||
expected_trait_ref.map(|tr| tr.self_ty()),
|
expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(),
|
||||||
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
|
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
match (has_sub, has_sup) {
|
let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) {
|
||||||
(Some(n1), Some(n2)) => {
|
(Some(n1), Some(n2)) => ("two", std::cmp::min(n1, n2), std::cmp::max(n1, n2)),
|
||||||
let _ = write!(
|
(Some(n), _) | (_, Some(n)) => ("any", n, 0),
|
||||||
note,
|
|
||||||
", for any two lifetimes `'{}` and `'{}`...",
|
|
||||||
std::cmp::min(n1, n2),
|
|
||||||
std::cmp::max(n1, n2),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
(Some(n), _) | (_, Some(n)) => {
|
|
||||||
let _ = write!(note, ", for any lifetime `'{}`...", n,);
|
|
||||||
}
|
|
||||||
(None, None) => {
|
(None, None) => {
|
||||||
if let Some(n) = expected_has_vid {
|
if let Some(n) = expected_has_vid {
|
||||||
let _ = write!(note, ", for some specific lifetime `'{}`...", n,);
|
("some", n, 0)
|
||||||
}
|
} else {
|
||||||
|
("nothing", 0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
note
|
let note_1 = ActualImplExplNotes::NoteOne {
|
||||||
});
|
leading_ellipsis,
|
||||||
|
kind,
|
||||||
|
ty_or_sig,
|
||||||
|
trait_path,
|
||||||
|
lt_kind,
|
||||||
|
lifetime_1,
|
||||||
|
lifetime_2,
|
||||||
|
};
|
||||||
|
|
||||||
let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
|
let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
|
||||||
actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
|
actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
|
||||||
err.note(&{
|
|
||||||
let passive_voice = match actual_has_vid {
|
let passive_voice = match actual_has_vid {
|
||||||
Some(_) => any_self_ty_has_vid,
|
Some(_) => any_self_ty_has_vid,
|
||||||
None => true,
|
None => true,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut note = if same_self_type {
|
let trait_path_2 = actual_trait_ref.map(|tr| tr.print_only_trait_path()).to_string();
|
||||||
format!(
|
let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string();
|
||||||
"...but it actually implements `{}`",
|
let kind_2 = if same_self_type {
|
||||||
actual_trait_ref.map(|tr| tr.print_only_trait_path()),
|
"implements_trait"
|
||||||
)
|
|
||||||
} else if passive_voice {
|
} else if passive_voice {
|
||||||
format!(
|
"implemented_for_ty"
|
||||||
"...but `{}` is actually implemented for the type `{}`",
|
|
||||||
actual_trait_ref.map(|tr| tr.print_only_trait_path()),
|
|
||||||
actual_trait_ref.map(|tr| tr.self_ty()),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
format!(
|
"ty_implements"
|
||||||
"...but `{}` actually implements `{}`",
|
|
||||||
actual_trait_ref.map(|tr| tr.self_ty()),
|
|
||||||
actual_trait_ref.map(|tr| tr.print_only_trait_path()),
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(n) = actual_has_vid {
|
let has_lifetime = actual_has_vid.is_some();
|
||||||
let _ = write!(note, ", for some specific lifetime `'{}`", n);
|
let lifetime = actual_has_vid.unwrap_or_default();
|
||||||
}
|
|
||||||
|
|
||||||
note
|
let note_2 =
|
||||||
});
|
ActualImplExplNotes::NoteTwo { kind_2, trait_path_2, ty, has_lifetime, lifetime };
|
||||||
|
|
||||||
|
vec![note_1, note_2]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue