mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #57901 - lqd:issue_57362, r=nikomatsakis
Add information to higher-ranked lifetimes conflicts error messages Make these errors go through the new "placeholder error" code path, to have self tys displayed and make them hopefully less confusing. Should fix #57362. r? @nikomatsakis — so we can iterate on the specific wording you wanted.
This commit is contained in:
commit
7425663011
@ -46,9 +46,9 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
let (span, sub, sup) = self.get_regions();
|
||||
|
||||
// Determine whether the sub and sup consist of both anonymous (elided) regions.
|
||||
let anon_reg_sup = self.tcx.is_suitable_region(sup)?;
|
||||
let anon_reg_sup = self.tcx().is_suitable_region(sup)?;
|
||||
|
||||
let anon_reg_sub = self.tcx.is_suitable_region(sub)?;
|
||||
let anon_reg_sub = self.tcx().is_suitable_region(sub)?;
|
||||
let scope_def_id_sup = anon_reg_sup.def_id;
|
||||
let bregion_sup = anon_reg_sup.boundregion;
|
||||
let scope_def_id_sub = anon_reg_sub.def_id;
|
||||
@ -138,7 +138,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
|
||||
struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch")
|
||||
struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch")
|
||||
.span_label(span_1, main_label)
|
||||
.span_label(span_2, String::new())
|
||||
.span_label(span, span_label)
|
||||
|
@ -26,10 +26,10 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
region: Region<'tcx>,
|
||||
br: &ty::BoundRegion,
|
||||
) -> Option<(&hir::Ty, &hir::FnDecl)> {
|
||||
if let Some(anon_reg) = self.tcx.is_suitable_region(region) {
|
||||
if let Some(anon_reg) = self.tcx().is_suitable_region(region) {
|
||||
let def_id = anon_reg.def_id;
|
||||
if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) {
|
||||
let fndecl = match self.tcx.hir().get(node_id) {
|
||||
if let Some(node_id) = self.tcx().hir().as_local_node_id(def_id) {
|
||||
let fndecl = match self.tcx().hir().get(node_id) {
|
||||
Node::Item(&hir::Item {
|
||||
node: hir::ItemKind::Fn(ref fndecl, ..),
|
||||
..
|
||||
@ -64,7 +64,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
br: &ty::BoundRegion,
|
||||
) -> Option<(&'gcx hir::Ty)> {
|
||||
let mut nested_visitor = FindNestedTypeVisitor {
|
||||
tcx: self.tcx,
|
||||
tcx: self.tcx(),
|
||||
bound_region: *br,
|
||||
found_type: None,
|
||||
current_index: ty::INNERMOST,
|
||||
|
@ -22,15 +22,15 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
||||
|
||||
if let Some(tables) = self.in_progress_tables {
|
||||
let tables = tables.borrow();
|
||||
NiceRegionError::new(self.tcx, error.clone(), Some(&tables)).try_report().is_some()
|
||||
NiceRegionError::new(self, error.clone(), Some(&tables)).try_report().is_some()
|
||||
} else {
|
||||
NiceRegionError::new(self.tcx, error.clone(), None).try_report().is_some()
|
||||
NiceRegionError::new(self, error.clone(), None).try_report().is_some()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NiceRegionError<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
|
||||
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
|
||||
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
|
||||
error: Option<RegionResolutionError<'tcx>>,
|
||||
regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>,
|
||||
tables: Option<&'cx ty::TypeckTables<'tcx>>,
|
||||
@ -38,21 +38,25 @@ pub struct NiceRegionError<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
|
||||
|
||||
impl<'cx, 'gcx, 'tcx> NiceRegionError<'cx, 'gcx, 'tcx> {
|
||||
pub fn new(
|
||||
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
|
||||
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
|
||||
error: RegionResolutionError<'tcx>,
|
||||
tables: Option<&'cx ty::TypeckTables<'tcx>>,
|
||||
) -> Self {
|
||||
Self { tcx, error: Some(error), regions: None, tables }
|
||||
Self { infcx, error: Some(error), regions: None, tables }
|
||||
}
|
||||
|
||||
pub fn new_from_span(
|
||||
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
|
||||
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
|
||||
span: Span,
|
||||
sub: ty::Region<'tcx>,
|
||||
sup: ty::Region<'tcx>,
|
||||
tables: Option<&'cx ty::TypeckTables<'tcx>>,
|
||||
) -> Self {
|
||||
Self { tcx, error: None, regions: Some((span, sub, sup)), tables }
|
||||
Self { infcx, error: None, regions: Some((span, sub, sup)), tables }
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
pub fn try_report_from_nll(&self) -> Option<ErrorReported> {
|
||||
|
@ -24,23 +24,23 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
// version new_ty of its type where the anonymous region is replaced
|
||||
// with the named one.//scope_def_id
|
||||
let (named, anon, anon_arg_info, region_info) = if self.is_named_region(sub)
|
||||
&& self.tcx.is_suitable_region(sup).is_some()
|
||||
&& self.tcx().is_suitable_region(sup).is_some()
|
||||
&& self.find_arg_with_region(sup, sub).is_some()
|
||||
{
|
||||
(
|
||||
sub,
|
||||
sup,
|
||||
self.find_arg_with_region(sup, sub).unwrap(),
|
||||
self.tcx.is_suitable_region(sup).unwrap(),
|
||||
self.tcx().is_suitable_region(sup).unwrap(),
|
||||
)
|
||||
} else if self.is_named_region(sup) && self.tcx.is_suitable_region(sub).is_some()
|
||||
} else if self.is_named_region(sup) && self.tcx().is_suitable_region(sub).is_some()
|
||||
&& self.find_arg_with_region(sub, sup).is_some()
|
||||
{
|
||||
(
|
||||
sup,
|
||||
sub,
|
||||
self.find_arg_with_region(sub, sup).unwrap(),
|
||||
self.tcx.is_suitable_region(sub).unwrap(),
|
||||
self.tcx().is_suitable_region(sub).unwrap(),
|
||||
)
|
||||
} else {
|
||||
return None; // inapplicable
|
||||
@ -97,7 +97,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
struct_span_err!(
|
||||
self.tcx.sess,
|
||||
self.tcx().sess,
|
||||
span,
|
||||
E0621,
|
||||
"explicit lifetime required in {}",
|
||||
|
@ -47,7 +47,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
// closure, provide a specific message pointing this out.
|
||||
if let (&SubregionOrigin::BindingTypeIsNotValidAtDecl(ref external_span),
|
||||
&RegionKind::ReFree(ref free_region)) = (&sub_origin, sup_region) {
|
||||
let hir = &self.tcx.hir();
|
||||
let hir = &self.tcx().hir();
|
||||
if let Some(node_id) = hir.as_local_node_id(free_region.scope) {
|
||||
if let Node::Expr(Expr {
|
||||
node: Closure(_, _, _, closure_span, None),
|
||||
@ -55,7 +55,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
}) = hir.get(node_id) {
|
||||
let sup_sp = sup_origin.span();
|
||||
let origin_sp = origin.span();
|
||||
let mut err = self.tcx.sess.struct_span_err(
|
||||
let mut err = self.tcx().sess.struct_span_err(
|
||||
sup_sp,
|
||||
"borrowed data cannot be stored outside of its closure");
|
||||
err.span_label(sup_sp, "cannot be stored outside of its closure");
|
||||
|
@ -1,3 +1,4 @@
|
||||
use errors::DiagnosticBuilder;
|
||||
use hir::def_id::DefId;
|
||||
use infer::error_reporting::nice_region_error::NiceRegionError;
|
||||
use infer::lexical_region_resolve::RegionResolutionError;
|
||||
@ -12,7 +13,7 @@ use util::ppaux::RegionHighlightMode;
|
||||
|
||||
impl NiceRegionError<'me, 'gcx, 'tcx> {
|
||||
/// When given a `ConcreteFailure` for a function with arguments containing a named region and
|
||||
/// an anonymous region, emit an descriptive diagnostic error.
|
||||
/// an anonymous region, emit a descriptive diagnostic error.
|
||||
pub(super) fn try_report_placeholder_conflict(&self) -> Option<ErrorReported> {
|
||||
match &self.error {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -34,19 +35,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
|
||||
sub_placeholder @ ty::RePlaceholder(_),
|
||||
_,
|
||||
sup_placeholder @ ty::RePlaceholder(_),
|
||||
))
|
||||
if expected.def_id == found.def_id =>
|
||||
{
|
||||
Some(self.try_report_placeholders_trait(
|
||||
Some(self.tcx.mk_region(ty::ReVar(*vid))),
|
||||
cause,
|
||||
Some(sub_placeholder),
|
||||
Some(sup_placeholder),
|
||||
expected.def_id,
|
||||
expected.substs,
|
||||
found.substs,
|
||||
))
|
||||
}
|
||||
)) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
|
||||
Some(self.tcx().mk_region(ty::ReVar(*vid))),
|
||||
cause,
|
||||
Some(sub_placeholder),
|
||||
Some(sup_placeholder),
|
||||
expected.def_id,
|
||||
expected.substs,
|
||||
found.substs,
|
||||
)),
|
||||
|
||||
Some(RegionResolutionError::SubSupConflict(
|
||||
vid,
|
||||
@ -58,19 +55,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
|
||||
sub_placeholder @ ty::RePlaceholder(_),
|
||||
_,
|
||||
_,
|
||||
))
|
||||
if expected.def_id == found.def_id =>
|
||||
{
|
||||
Some(self.try_report_placeholders_trait(
|
||||
Some(self.tcx.mk_region(ty::ReVar(*vid))),
|
||||
cause,
|
||||
Some(sub_placeholder),
|
||||
None,
|
||||
expected.def_id,
|
||||
expected.substs,
|
||||
found.substs,
|
||||
))
|
||||
}
|
||||
)) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
|
||||
Some(self.tcx().mk_region(ty::ReVar(*vid))),
|
||||
cause,
|
||||
Some(sub_placeholder),
|
||||
None,
|
||||
expected.def_id,
|
||||
expected.substs,
|
||||
found.substs,
|
||||
)),
|
||||
|
||||
Some(RegionResolutionError::SubSupConflict(
|
||||
vid,
|
||||
@ -82,19 +75,35 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
|
||||
_,
|
||||
_,
|
||||
sup_placeholder @ ty::RePlaceholder(_),
|
||||
))
|
||||
if expected.def_id == found.def_id =>
|
||||
{
|
||||
Some(self.try_report_placeholders_trait(
|
||||
Some(self.tcx.mk_region(ty::ReVar(*vid))),
|
||||
)) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
|
||||
Some(self.tcx().mk_region(ty::ReVar(*vid))),
|
||||
cause,
|
||||
None,
|
||||
Some(*sup_placeholder),
|
||||
expected.def_id,
|
||||
expected.substs,
|
||||
found.substs,
|
||||
)),
|
||||
|
||||
Some(RegionResolutionError::SubSupConflict(
|
||||
vid,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
SubregionOrigin::Subtype(TypeTrace {
|
||||
cause,
|
||||
None,
|
||||
Some(*sup_placeholder),
|
||||
expected.def_id,
|
||||
expected.substs,
|
||||
found.substs,
|
||||
))
|
||||
}
|
||||
values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
|
||||
}),
|
||||
sup_placeholder @ ty::RePlaceholder(_),
|
||||
)) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
|
||||
Some(self.tcx().mk_region(ty::ReVar(*vid))),
|
||||
cause,
|
||||
None,
|
||||
Some(*sup_placeholder),
|
||||
expected.def_id,
|
||||
expected.substs,
|
||||
found.substs,
|
||||
)),
|
||||
|
||||
Some(RegionResolutionError::ConcreteFailure(
|
||||
SubregionOrigin::Subtype(TypeTrace {
|
||||
@ -103,19 +112,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
|
||||
}),
|
||||
sub_region @ ty::RePlaceholder(_),
|
||||
sup_region @ ty::RePlaceholder(_),
|
||||
))
|
||||
if expected.def_id == found.def_id =>
|
||||
{
|
||||
Some(self.try_report_placeholders_trait(
|
||||
None,
|
||||
cause,
|
||||
Some(*sub_region),
|
||||
Some(*sup_region),
|
||||
expected.def_id,
|
||||
expected.substs,
|
||||
found.substs,
|
||||
))
|
||||
}
|
||||
)) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
|
||||
None,
|
||||
cause,
|
||||
Some(*sub_region),
|
||||
Some(*sup_region),
|
||||
expected.def_id,
|
||||
expected.substs,
|
||||
found.substs,
|
||||
)),
|
||||
|
||||
Some(RegionResolutionError::ConcreteFailure(
|
||||
SubregionOrigin::Subtype(TypeTrace {
|
||||
@ -124,19 +129,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
|
||||
}),
|
||||
sub_region @ ty::RePlaceholder(_),
|
||||
sup_region,
|
||||
))
|
||||
if expected.def_id == found.def_id =>
|
||||
{
|
||||
Some(self.try_report_placeholders_trait(
|
||||
Some(sup_region),
|
||||
cause,
|
||||
Some(*sub_region),
|
||||
None,
|
||||
expected.def_id,
|
||||
expected.substs,
|
||||
found.substs,
|
||||
))
|
||||
}
|
||||
)) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
|
||||
Some(sup_region),
|
||||
cause,
|
||||
Some(*sub_region),
|
||||
None,
|
||||
expected.def_id,
|
||||
expected.substs,
|
||||
found.substs,
|
||||
)),
|
||||
|
||||
Some(RegionResolutionError::ConcreteFailure(
|
||||
SubregionOrigin::Subtype(TypeTrace {
|
||||
@ -145,19 +146,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
|
||||
}),
|
||||
sub_region,
|
||||
sup_region @ ty::RePlaceholder(_),
|
||||
))
|
||||
if expected.def_id == found.def_id =>
|
||||
{
|
||||
Some(self.try_report_placeholders_trait(
|
||||
Some(sub_region),
|
||||
cause,
|
||||
None,
|
||||
Some(*sup_region),
|
||||
expected.def_id,
|
||||
expected.substs,
|
||||
found.substs,
|
||||
))
|
||||
}
|
||||
)) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait(
|
||||
Some(sub_region),
|
||||
cause,
|
||||
None,
|
||||
Some(*sup_region),
|
||||
expected.def_id,
|
||||
expected.substs,
|
||||
found.substs,
|
||||
)),
|
||||
|
||||
_ => None,
|
||||
}
|
||||
@ -182,11 +179,22 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
|
||||
expected_substs: &'tcx Substs<'tcx>,
|
||||
actual_substs: &'tcx Substs<'tcx>,
|
||||
) -> ErrorReported {
|
||||
let mut err = self.tcx.sess.struct_span_err(
|
||||
cause.span(&self.tcx),
|
||||
debug!(
|
||||
"try_report_placeholders_trait(\
|
||||
vid={:?}, \
|
||||
sub_placeholder={:?}, \
|
||||
sup_placeholder={:?}, \
|
||||
trait_def_id={:?}, \
|
||||
expected_substs={:?}, \
|
||||
actual_substs={:?})",
|
||||
vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs
|
||||
);
|
||||
|
||||
let mut err = self.tcx().sess.struct_span_err(
|
||||
cause.span(&self.tcx()),
|
||||
&format!(
|
||||
"implementation of `{}` is not general enough",
|
||||
self.tcx.item_path_str(trait_def_id),
|
||||
self.tcx().item_path_str(trait_def_id),
|
||||
),
|
||||
);
|
||||
|
||||
@ -194,20 +202,20 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
|
||||
ObligationCauseCode::ItemObligation(def_id) => {
|
||||
err.note(&format!(
|
||||
"Due to a where-clause on `{}`,",
|
||||
self.tcx.item_path_str(def_id),
|
||||
self.tcx().item_path_str(def_id),
|
||||
));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let expected_trait_ref = ty::TraitRef {
|
||||
let expected_trait_ref = self.infcx.resolve_type_vars_if_possible(&ty::TraitRef {
|
||||
def_id: trait_def_id,
|
||||
substs: expected_substs,
|
||||
};
|
||||
let actual_trait_ref = ty::TraitRef {
|
||||
});
|
||||
let actual_trait_ref = self.infcx.resolve_type_vars_if_possible(&ty::TraitRef {
|
||||
def_id: trait_def_id,
|
||||
substs: actual_substs,
|
||||
};
|
||||
});
|
||||
|
||||
// Search the expected and actual trait references to see (a)
|
||||
// whether the sub/sup placeholders appear in them (sometimes
|
||||
@ -218,9 +226,11 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
|
||||
let mut counter = 0;
|
||||
let mut has_sub = None;
|
||||
let mut has_sup = None;
|
||||
let mut has_vid = None;
|
||||
|
||||
self.tcx.for_each_free_region(&expected_trait_ref, |r| {
|
||||
let mut actual_has_vid = None;
|
||||
let mut expected_has_vid = None;
|
||||
|
||||
self.tcx().for_each_free_region(&expected_trait_ref, |r| {
|
||||
if Some(r) == sub_placeholder && has_sub.is_none() {
|
||||
has_sub = Some(counter);
|
||||
counter += 1;
|
||||
@ -228,80 +238,207 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
|
||||
has_sup = Some(counter);
|
||||
counter += 1;
|
||||
}
|
||||
});
|
||||
|
||||
self.tcx.for_each_free_region(&actual_trait_ref, |r| {
|
||||
if Some(r) == vid && has_vid.is_none() {
|
||||
has_vid = Some(counter);
|
||||
if Some(r) == vid && expected_has_vid.is_none() {
|
||||
expected_has_vid = Some(counter);
|
||||
counter += 1;
|
||||
}
|
||||
});
|
||||
|
||||
let self_ty_has_vid = self
|
||||
.tcx
|
||||
self.tcx().for_each_free_region(&actual_trait_ref, |r| {
|
||||
if Some(r) == vid && actual_has_vid.is_none() {
|
||||
actual_has_vid = Some(counter);
|
||||
counter += 1;
|
||||
}
|
||||
});
|
||||
|
||||
let actual_self_ty_has_vid = self
|
||||
.tcx()
|
||||
.any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid);
|
||||
|
||||
let expected_self_ty_has_vid = self
|
||||
.tcx()
|
||||
.any_free_region_meets(&expected_trait_ref.self_ty(), |r| Some(r) == vid);
|
||||
|
||||
let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid;
|
||||
|
||||
debug!(
|
||||
"try_report_placeholders_trait: actual_has_vid={:?}",
|
||||
actual_has_vid
|
||||
);
|
||||
debug!(
|
||||
"try_report_placeholders_trait: expected_has_vid={:?}",
|
||||
expected_has_vid
|
||||
);
|
||||
debug!("try_report_placeholders_trait: has_sub={:?}", has_sub);
|
||||
debug!("try_report_placeholders_trait: has_sup={:?}", has_sup);
|
||||
debug!(
|
||||
"try_report_placeholders_trait: actual_self_ty_has_vid={:?}",
|
||||
actual_self_ty_has_vid
|
||||
);
|
||||
debug!(
|
||||
"try_report_placeholders_trait: expected_self_ty_has_vid={:?}",
|
||||
expected_self_ty_has_vid
|
||||
);
|
||||
|
||||
self.explain_actual_impl_that_was_found(
|
||||
&mut err,
|
||||
sub_placeholder,
|
||||
sup_placeholder,
|
||||
has_sub,
|
||||
has_sup,
|
||||
expected_trait_ref,
|
||||
actual_trait_ref,
|
||||
vid,
|
||||
expected_has_vid,
|
||||
actual_has_vid,
|
||||
any_self_ty_has_vid,
|
||||
);
|
||||
|
||||
err.emit();
|
||||
ErrorReported
|
||||
}
|
||||
|
||||
/// Add notes with details about the expected and actual trait refs, with attention to cases
|
||||
/// when placeholder regions are involved: either the trait or the self type containing
|
||||
/// them needs to be mentioned the closest to the placeholders.
|
||||
/// This makes the error messages read better, however at the cost of some complexity
|
||||
/// due to the number of combinations we have to deal with.
|
||||
fn explain_actual_impl_that_was_found(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
sub_placeholder: Option<ty::Region<'tcx>>,
|
||||
sup_placeholder: Option<ty::Region<'tcx>>,
|
||||
has_sub: Option<usize>,
|
||||
has_sup: Option<usize>,
|
||||
expected_trait_ref: ty::TraitRef<'_>,
|
||||
actual_trait_ref: ty::TraitRef<'_>,
|
||||
vid: Option<ty::Region<'tcx>>,
|
||||
expected_has_vid: Option<usize>,
|
||||
actual_has_vid: Option<usize>,
|
||||
any_self_ty_has_vid: bool,
|
||||
) {
|
||||
// The weird thing here with the `maybe_highlighting_region` calls and the
|
||||
// the match inside is meant to be like this:
|
||||
//
|
||||
// - The match checks whether the given things (placeholders, etc) appear
|
||||
// in the types are about to print
|
||||
// - Meanwhile, the `maybe_highlighting_region` calls set up
|
||||
// highlights so that, if they do appear, we will replace
|
||||
// them `'0` and whatever. (This replacement takes place
|
||||
// inside the closure given to `maybe_highlighting_region`.)
|
||||
//
|
||||
// There is some duplication between the calls -- i.e., the
|
||||
// `maybe_highlighting_region` checks if (e.g.) `has_sub` is
|
||||
// None, an then we check again inside the closure, but this
|
||||
// setup sort of minimized the number of calls and so form.
|
||||
|
||||
RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || {
|
||||
RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || {
|
||||
match (has_sub, has_sup) {
|
||||
(Some(n1), Some(n2)) => {
|
||||
err.note(&format!(
|
||||
"`{}` must implement `{}` \
|
||||
for any two lifetimes `'{}` and `'{}`",
|
||||
expected_trait_ref.self_ty(),
|
||||
expected_trait_ref,
|
||||
std::cmp::min(n1, n2),
|
||||
std::cmp::max(n1, n2),
|
||||
));
|
||||
if any_self_ty_has_vid {
|
||||
err.note(&format!(
|
||||
"`{}` would have to be implemented for the type `{}`, \
|
||||
for any two lifetimes `'{}` and `'{}`",
|
||||
expected_trait_ref,
|
||||
expected_trait_ref.self_ty(),
|
||||
std::cmp::min(n1, n2),
|
||||
std::cmp::max(n1, n2),
|
||||
));
|
||||
} else {
|
||||
err.note(&format!(
|
||||
"`{}` must implement `{}`, \
|
||||
for any two lifetimes `'{}` and `'{}`",
|
||||
expected_trait_ref.self_ty(),
|
||||
expected_trait_ref,
|
||||
std::cmp::min(n1, n2),
|
||||
std::cmp::max(n1, n2),
|
||||
));
|
||||
}
|
||||
}
|
||||
(Some(n), _) | (_, Some(n)) => {
|
||||
err.note(&format!(
|
||||
"`{}` must implement `{}` \
|
||||
for any lifetime `'{}`",
|
||||
expected_trait_ref.self_ty(),
|
||||
expected_trait_ref,
|
||||
n,
|
||||
));
|
||||
}
|
||||
(None, None) => {
|
||||
err.note(&format!(
|
||||
"`{}` must implement `{}`",
|
||||
expected_trait_ref.self_ty(),
|
||||
expected_trait_ref,
|
||||
));
|
||||
if any_self_ty_has_vid {
|
||||
err.note(&format!(
|
||||
"`{}` would have to be implemented for the type `{}`, \
|
||||
for any lifetime `'{}`",
|
||||
expected_trait_ref,
|
||||
expected_trait_ref.self_ty(),
|
||||
n,
|
||||
));
|
||||
} else {
|
||||
err.note(&format!(
|
||||
"`{}` must implement `{}`, for any lifetime `'{}`",
|
||||
expected_trait_ref.self_ty(),
|
||||
expected_trait_ref,
|
||||
n,
|
||||
));
|
||||
}
|
||||
}
|
||||
(None, None) => RegionHighlightMode::maybe_highlighting_region(
|
||||
vid,
|
||||
expected_has_vid,
|
||||
|| {
|
||||
if let Some(n) = expected_has_vid {
|
||||
err.note(&format!(
|
||||
"`{}` would have to be implemented for the type `{}`, \
|
||||
for some specific lifetime `'{}`",
|
||||
expected_trait_ref,
|
||||
expected_trait_ref.self_ty(),
|
||||
n,
|
||||
));
|
||||
} else {
|
||||
if any_self_ty_has_vid {
|
||||
err.note(&format!(
|
||||
"`{}` would have to be implemented for the type `{}`",
|
||||
expected_trait_ref,
|
||||
expected_trait_ref.self_ty(),
|
||||
));
|
||||
} else {
|
||||
err.note(&format!(
|
||||
"`{}` must implement `{}`",
|
||||
expected_trait_ref.self_ty(),
|
||||
expected_trait_ref,
|
||||
));
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
RegionHighlightMode::maybe_highlighting_region(vid, has_vid, || match has_vid {
|
||||
Some(n) => {
|
||||
if self_ty_has_vid {
|
||||
RegionHighlightMode::maybe_highlighting_region(
|
||||
vid,
|
||||
actual_has_vid,
|
||||
|| match actual_has_vid {
|
||||
Some(n) => {
|
||||
if any_self_ty_has_vid {
|
||||
err.note(&format!(
|
||||
"but `{}` is actually implemented for the type `{}`, \
|
||||
for some specific lifetime `'{}`",
|
||||
actual_trait_ref,
|
||||
actual_trait_ref.self_ty(),
|
||||
n
|
||||
));
|
||||
} else {
|
||||
err.note(&format!(
|
||||
"but `{}` actually implements `{}`, for some specific lifetime `'{}`",
|
||||
actual_trait_ref.self_ty(),
|
||||
actual_trait_ref,
|
||||
n
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
err.note(&format!(
|
||||
"but `{}` only implements `{}` for the lifetime `'{}`",
|
||||
actual_trait_ref.self_ty(),
|
||||
"but `{}` is actually implemented for the type `{}`",
|
||||
actual_trait_ref,
|
||||
n
|
||||
));
|
||||
} else {
|
||||
err.note(&format!(
|
||||
"but `{}` only implements `{}` for some lifetime `'{}`",
|
||||
actual_trait_ref.self_ty(),
|
||||
actual_trait_ref,
|
||||
n
|
||||
));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
err.note(&format!(
|
||||
"but `{}` only implements `{}`",
|
||||
actual_trait_ref.self_ty(),
|
||||
actual_trait_ref,
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
err.emit();
|
||||
ErrorReported
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -19,13 +19,13 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
sup_r,
|
||||
) = error.clone()
|
||||
{
|
||||
let anon_reg_sup = self.tcx.is_suitable_region(sup_r)?;
|
||||
let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?;
|
||||
if sub_r == &RegionKind::ReStatic &&
|
||||
self.tcx.return_type_impl_trait(anon_reg_sup.def_id).is_some()
|
||||
self.tcx().return_type_impl_trait(anon_reg_sup.def_id).is_some()
|
||||
{
|
||||
let sp = var_origin.span();
|
||||
let return_sp = sub_origin.span();
|
||||
let mut err = self.tcx.sess.struct_span_err(
|
||||
let mut err = self.tcx().sess.struct_span_err(
|
||||
sp,
|
||||
"cannot infer an appropriate lifetime",
|
||||
);
|
||||
@ -38,7 +38,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
"...but this borrow...",
|
||||
);
|
||||
|
||||
let (lifetime, lt_sp_opt) = self.tcx.msg_span_from_free_region(sup_r);
|
||||
let (lifetime, lt_sp_opt) = self.tcx().msg_span_from_free_region(sup_r);
|
||||
if let Some(lifetime_sp) = lt_sp_opt {
|
||||
err.span_note(
|
||||
lifetime_sp,
|
||||
@ -52,7 +52,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
}) => name.to_string(),
|
||||
_ => "'_".to_owned(),
|
||||
};
|
||||
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(return_sp) {
|
||||
if let Ok(snippet) = self.tcx().sess.source_map().span_to_snippet(return_sp) {
|
||||
err.span_suggestion(
|
||||
return_sp,
|
||||
&format!(
|
||||
|
@ -44,13 +44,13 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
let (id, bound_region) = match *anon_region {
|
||||
ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
|
||||
ty::ReEarlyBound(ref ebr) => (
|
||||
self.tcx.parent_def_id(ebr.def_id).unwrap(),
|
||||
self.tcx().parent_def_id(ebr.def_id).unwrap(),
|
||||
ty::BoundRegion::BrNamed(ebr.def_id, ebr.name),
|
||||
),
|
||||
_ => return None, // not a free region
|
||||
};
|
||||
|
||||
let hir = &self.tcx.hir();
|
||||
let hir = &self.tcx().hir();
|
||||
if let Some(node_id) = hir.as_local_node_id(id) {
|
||||
if let Some(body_id) = hir.maybe_body_owned_by(node_id) {
|
||||
let body = hir.body(body_id);
|
||||
@ -66,7 +66,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
let arg_ty_span = hir.span(hir.hir_to_node_id(ty_hir_id));
|
||||
let ty = tables.node_id_to_type_opt(arg.hir_id)?;
|
||||
let mut found_anon_region = false;
|
||||
let new_arg_ty = self.tcx.fold_regions(&ty, &mut false, |r, _| {
|
||||
let new_arg_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| {
|
||||
if *r == *anon_region {
|
||||
found_anon_region = true;
|
||||
replace_region
|
||||
@ -108,10 +108,10 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
br: ty::BoundRegion,
|
||||
decl: &hir::FnDecl,
|
||||
) -> Option<Span> {
|
||||
let ret_ty = self.tcx.type_of(scope_def_id);
|
||||
let ret_ty = self.tcx().type_of(scope_def_id);
|
||||
if let ty::FnDef(_, _) = ret_ty.sty {
|
||||
let sig = ret_ty.fn_sig(self.tcx);
|
||||
let late_bound_regions = self.tcx
|
||||
let sig = ret_ty.fn_sig(self.tcx());
|
||||
let late_bound_regions = self.tcx()
|
||||
.collect_referenced_late_bound_regions(&sig.output());
|
||||
if late_bound_regions.iter().any(|r| *r == br) {
|
||||
return Some(decl.output.span());
|
||||
@ -126,7 +126,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
// enable E0621 for it.
|
||||
pub(super) fn is_self_anon(&self, is_first: bool, scope_def_id: DefId) -> bool {
|
||||
is_first
|
||||
&& self.tcx
|
||||
&& self.tcx()
|
||||
.opt_associated_item(scope_def_id)
|
||||
.map(|i| i.method_has_self_argument) == Some(true)
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// Check if we can use one of the "nice region errors".
|
||||
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
|
||||
let tables = infcx.tcx.typeck_tables_of(mir_def_id);
|
||||
let nice = NiceRegionError::new_from_span(infcx.tcx, span, o, f, Some(tables));
|
||||
let nice = NiceRegionError::new_from_span(infcx, span, o, f, Some(tables));
|
||||
if let Some(_error_reported) = nice.try_report_from_nll() {
|
||||
return;
|
||||
}
|
||||
|
@ -41,8 +41,8 @@ LL | tuple_one::<Tuple>();
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: Due to a where-clause on `tuple_one`,
|
||||
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1`
|
||||
= note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2`
|
||||
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`
|
||||
= note: but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
|
||||
|
||||
error: implementation of `TheTrait` is not general enough
|
||||
--> $DIR/associated-types-eq-hr.rs:96:5
|
||||
@ -51,8 +51,8 @@ LL | tuple_two::<Tuple>();
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: Due to a where-clause on `tuple_two`,
|
||||
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1`
|
||||
= note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2`
|
||||
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`
|
||||
= note: but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
|
||||
|
||||
error: implementation of `TheTrait` is not general enough
|
||||
--> $DIR/associated-types-eq-hr.rs:105:5
|
||||
@ -61,8 +61,8 @@ LL | tuple_four::<Tuple>();
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: Due to a where-clause on `tuple_four`,
|
||||
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1`
|
||||
= note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2`
|
||||
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`
|
||||
= note: but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
error[E0308]: mismatched types
|
||||
error: implementation of `Mirror` is not general enough
|
||||
--> $DIR/higher-ranked-projection.rs:25:5
|
||||
|
|
||||
LL | foo(());
|
||||
| ^^^ one type is more general than the other
|
||||
| ^^^
|
||||
|
|
||||
= note: expected type `Mirror`
|
||||
found type `Mirror`
|
||||
= note: Due to a where-clause on `foo`,
|
||||
= note: `Mirror` would have to be implemented for the type `&'0 ()`, for any lifetime `'0`
|
||||
= note: but `Mirror` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -3,7 +3,7 @@ error: compilation successful
|
||||
|
|
||||
LL | / fn main() { //[good]~ ERROR compilation successful
|
||||
LL | | foo(());
|
||||
LL | | //[bad]~^ ERROR E0308
|
||||
LL | | //[bad]~^ ERROR not general enough
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
|
@ -23,5 +23,5 @@ fn foo<U, T>(_t: T)
|
||||
#[rustc_error]
|
||||
fn main() { //[good]~ ERROR compilation successful
|
||||
foo(());
|
||||
//[bad]~^ ERROR E0308
|
||||
//[bad]~^ ERROR not general enough
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ error: implementation of `Foo` is not general enough
|
||||
LL | assert_foo(gen);
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: `&'0 OnlyFooIfStaticRef` must implement `Foo` for any lifetime `'0`
|
||||
= note: but `&'1 OnlyFooIfStaticRef` only implements `Foo` for the lifetime `'1`
|
||||
= note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0`
|
||||
= note: but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1`
|
||||
|
||||
error: implementation of `Foo` is not general enough
|
||||
--> $DIR/auto-trait-regions.rs:48:5
|
||||
@ -13,8 +13,8 @@ error: implementation of `Foo` is not general enough
|
||||
LL | assert_foo(gen);
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: `A<'0, '1>` must implement `Foo` for any two lifetimes `'0` and `'1`
|
||||
= note: but `A<'_, '2>` only implements `Foo` for the lifetime `'2`
|
||||
= note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`
|
||||
= note: but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -4,8 +4,8 @@ error: implementation of `Deserialize` is not general enough
|
||||
LL | assert_deserialize_owned::<&'static str>(); //~ ERROR
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `&'static str` must implement `Deserialize<'0>` for any lifetime `'0`
|
||||
= note: but `&str` only implements `Deserialize<'1>` for some lifetime `'1`
|
||||
= note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`
|
||||
= note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -5,8 +5,8 @@ LL | fn b() { want_foo2::<SomeStruct>(); } //~ ERROR
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: Due to a where-clause on `want_foo2`,
|
||||
= note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1`
|
||||
= note: but `SomeStruct` only implements `Foo<(&'2 isize, &'2 isize)>` for some lifetime `'2`
|
||||
= note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`
|
||||
= note: but `SomeStruct` actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -6,7 +6,7 @@ LL | foo::<()>(); //~ ERROR not general enough
|
||||
|
|
||||
= note: Due to a where-clause on `foo`,
|
||||
= note: `()` must implement `Trait<for<'b> fn(std::cell::Cell<&'b u32>)>`
|
||||
= note: but `()` only implements `Trait<fn(std::cell::Cell<&'0 u32>)>` for some lifetime `'0`
|
||||
= note: but `()` actually implements `Trait<fn(std::cell::Cell<&'0 u32>)>`, for some specific lifetime `'0`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -5,8 +5,8 @@ LL | want_hrtb::<StaticInt>() //~ ERROR
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: Due to a where-clause on `want_hrtb`,
|
||||
= note: `StaticInt` must implement `Foo<&'0 isize>` for any lifetime `'0`
|
||||
= note: but `StaticInt` only implements `Foo<&'1 isize>` for some lifetime `'1`
|
||||
= note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`
|
||||
= note: but `StaticInt` actually implements `Foo<&'1 isize>`, for some specific lifetime `'1`
|
||||
|
||||
error: implementation of `Foo` is not general enough
|
||||
--> $DIR/hrtb-just-for-static.rs:30:5
|
||||
@ -15,8 +15,8 @@ LL | want_hrtb::<&'a u32>() //~ ERROR
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: Due to a where-clause on `want_hrtb`,
|
||||
= note: `&'a u32` must implement `Foo<&'0 isize>` for any lifetime `'0`
|
||||
= note: but `&'1 u32` only implements `Foo<&'1 isize>` for the lifetime `'1`
|
||||
= note: `Foo<&'0 isize>` would have to be implemented for the type `&'a u32`, for any lifetime `'0`
|
||||
= note: but `Foo<&'1 isize>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -43,7 +43,7 @@ fn foo_hrtb_bar_not<'b,T>(mut t: T)
|
||||
// be implemented. Thus to satisfy `&mut T : for<'a> Foo<&'a
|
||||
// isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where
|
||||
// clause only specifies `T : Bar<&'b isize>`.
|
||||
foo_hrtb_bar_not(&mut t); //~ ERROR E0308
|
||||
foo_hrtb_bar_not(&mut t); //~ ERROR not general enough
|
||||
}
|
||||
|
||||
fn foo_hrtb_bar_hrtb<T>(mut t: T)
|
||||
|
@ -1,12 +1,12 @@
|
||||
error[E0308]: mismatched types
|
||||
error: implementation of `Foo` is not general enough
|
||||
--> $DIR/hrtb-perfect-forwarding.rs:46:5
|
||||
|
|
||||
LL | foo_hrtb_bar_not(&mut t); //~ ERROR E0308
|
||||
| ^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
LL | foo_hrtb_bar_not(&mut t); //~ ERROR not general enough
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected type `Foo<&'a isize>`
|
||||
found type `Foo<&isize>`
|
||||
= note: Due to a where-clause on `foo_hrtb_bar_not`,
|
||||
= note: `&mut T` must implement `Foo<&'0 isize>`, for any lifetime `'0`
|
||||
= note: but `&mut T` actually implements `Foo<&'1 isize>`, for some specific lifetime `'1`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -4,8 +4,8 @@ error: implementation of `Foo` is not general enough
|
||||
LL | <u32 as RefFoo<u32>>::ref_foo(a)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `&'0 u32` must implement `Foo<'static, u32>` for any lifetime `'0`
|
||||
= note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1`
|
||||
= note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`
|
||||
= note: but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
|
||||
|
||||
error: implementation of `Foo` is not general enough
|
||||
--> $DIR/issue-54302-cases.rs:69:5
|
||||
@ -13,8 +13,8 @@ error: implementation of `Foo` is not general enough
|
||||
LL | <i32 as RefFoo<i32>>::ref_foo(a)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `&'0 i32` must implement `Foo<'static, i32>` for any lifetime `'0`
|
||||
= note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1`
|
||||
= note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`
|
||||
= note: but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1`
|
||||
|
||||
error: implementation of `Foo` is not general enough
|
||||
--> $DIR/issue-54302-cases.rs:75:5
|
||||
@ -22,8 +22,8 @@ error: implementation of `Foo` is not general enough
|
||||
LL | <u64 as RefFoo<u64>>::ref_foo(a)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `&'0 u64` must implement `Foo<'static, u64>` for any lifetime `'0`
|
||||
= note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1`
|
||||
= note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`
|
||||
= note: but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1`
|
||||
|
||||
error: implementation of `Foo` is not general enough
|
||||
--> $DIR/issue-54302-cases.rs:81:5
|
||||
@ -31,8 +31,8 @@ error: implementation of `Foo` is not general enough
|
||||
LL | <i64 as RefFoo<i64>>::ref_foo(a)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `&'0 i64` must implement `Foo<'static, i64>` for any lifetime `'0`
|
||||
= note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1`
|
||||
= note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`
|
||||
= note: but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -4,8 +4,8 @@ error: implementation of `Deserialize` is not general enough
|
||||
LL | assert_deserialize_owned::<&'static str>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `&'static str` must implement `Deserialize<'0>` for any lifetime `'0`
|
||||
= note: but `&str` only implements `Deserialize<'1>` for some lifetime `'1`
|
||||
= note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`
|
||||
= note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
23
src/test/ui/issues/issue-57362-1.rs
Normal file
23
src/test/ui/issues/issue-57362-1.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// Test for issue #57362, ensuring that the self ty is shown in cases of higher-ranked lifetimes
|
||||
// conflicts: the `expected` and `found` trait refs would otherwise be printed the same, leading
|
||||
// to confusing notes such as:
|
||||
// = note: expected type `Trait`
|
||||
// found type `Trait`
|
||||
|
||||
// from issue #57362
|
||||
trait Trait {
|
||||
fn f(self);
|
||||
}
|
||||
|
||||
impl<T> Trait for fn(&T) {
|
||||
fn f(self) {
|
||||
println!("f");
|
||||
}
|
||||
}
|
||||
|
||||
fn f() {
|
||||
let a: fn(_) = |_: &u8| {};
|
||||
a.f(); //~ ERROR not general enough
|
||||
}
|
||||
|
||||
fn main() {}
|
11
src/test/ui/issues/issue-57362-1.stderr
Normal file
11
src/test/ui/issues/issue-57362-1.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error: implementation of `Trait` is not general enough
|
||||
--> $DIR/issue-57362-1.rs:20:7
|
||||
|
|
||||
LL | a.f(); //~ ERROR not general enough
|
||||
| ^
|
||||
|
|
||||
= note: `Trait` would have to be implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0`
|
||||
= note: but `Trait` is actually implemented for the type `for<'r> fn(&'r u8)`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
25
src/test/ui/issues/issue-57362-2.rs
Normal file
25
src/test/ui/issues/issue-57362-2.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// Test for issue #57362, ensuring that the self ty is shown in cases of higher-ranked lifetimes
|
||||
// conflicts: the `expected` and `found` trait refs would otherwise be printed the same, leading
|
||||
// to confusing notes such as:
|
||||
// = note: expected type `Trait`
|
||||
// found type `Trait`
|
||||
|
||||
// extracted from a similar issue: #57642
|
||||
trait X {
|
||||
type G;
|
||||
fn make_g() -> Self::G;
|
||||
}
|
||||
|
||||
impl<'a> X for fn(&'a ()) {
|
||||
type G = &'a ();
|
||||
|
||||
fn make_g() -> Self::G {
|
||||
&()
|
||||
}
|
||||
}
|
||||
|
||||
fn g() {
|
||||
let x = <fn (&())>::make_g(); //~ ERROR not general enough
|
||||
}
|
||||
|
||||
fn main() {}
|
11
src/test/ui/issues/issue-57362-2.stderr
Normal file
11
src/test/ui/issues/issue-57362-2.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error: implementation of `X` is not general enough
|
||||
--> $DIR/issue-57362-2.rs:22:13
|
||||
|
|
||||
LL | let x = <fn (&())>::make_g(); //~ ERROR not general enough
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `X` would have to be implemented for the type `for<'r> fn(&'r ())`
|
||||
= note: but `X` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -5,8 +5,8 @@ LL | foo(&X); //~ ERROR implementation of `Bar` is not general enough
|
||||
| ^^^
|
||||
|
|
||||
= note: Due to a where-clause on `foo`,
|
||||
= note: `&'0 _` must implement `Bar` for any lifetime `'0`
|
||||
= note: but `&'1 u32` only implements `Bar` for the lifetime `'1`
|
||||
= note: `Bar` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`
|
||||
= note: but `Bar` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user