Rollup merge of #140523 - compiler-errors:late-early-mismatch, r=jackh726
Better error message for late/early lifetime param mismatch Rework the way we report early-/late-bound lifetime param mismatches to equate the trait and impl signatures using region variables, so that we can detect when a late-bound param is present in the signature in place of an early-bound param, or vice versa. The diagnostic is a bit more technical, but it's more obviously clear to see what the problem is, even if it's not great at explaining how to fix it. I think this could be improved further, but I still think it's much better than what exists today. Note to reviewer(s): I'd appreciate if we didn't bikeshed *too* much about this verbiage, b/c I hope it's clear that the old message sucked a lot. I'm happy to file bugs for interested new contributors to improve the messaging further. Edit(fmease): Fixes https://github.com/rust-lang/rust/issues/33624.
This commit is contained in:
@@ -5,7 +5,7 @@ use std::iter;
|
|||||||
use hir::def_id::{DefId, DefIdMap, LocalDefId};
|
use hir::def_id::{DefId, DefIdMap, LocalDefId};
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
|
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err};
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::intravisit::VisitorExt;
|
use rustc_hir::intravisit::VisitorExt;
|
||||||
use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit};
|
use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit};
|
||||||
@@ -14,10 +14,10 @@ use rustc_infer::traits::util;
|
|||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, BottomUpFolder, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder,
|
self, BottomUpFolder, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder,
|
||||||
TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast,
|
TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
|
||||||
};
|
};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_span::Span;
|
use rustc_span::{DUMMY_SP, Span};
|
||||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
||||||
@@ -1137,7 +1137,14 @@ fn check_region_bounds_on_impl_item<'tcx>(
|
|||||||
// but found 0" it's confusing, because it looks like there
|
// but found 0" it's confusing, because it looks like there
|
||||||
// are zero. Since I don't quite know how to phrase things at
|
// are zero. Since I don't quite know how to phrase things at
|
||||||
// the moment, give a kind of vague error message.
|
// the moment, give a kind of vague error message.
|
||||||
if trait_params != impl_params {
|
if trait_params == impl_params {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !delay && let Some(guar) = check_region_late_boundedness(tcx, impl_m, trait_m) {
|
||||||
|
return Err(guar);
|
||||||
|
}
|
||||||
|
|
||||||
let span = tcx
|
let span = tcx
|
||||||
.hir_get_generics(impl_m.def_id.expect_local())
|
.hir_get_generics(impl_m.def_id.expect_local())
|
||||||
.expect("expected impl item to have generics or else we can't compare them")
|
.expect("expected impl item to have generics or else we can't compare them")
|
||||||
@@ -1146,6 +1153,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
|
|||||||
let mut generics_span = None;
|
let mut generics_span = None;
|
||||||
let mut bounds_span = vec![];
|
let mut bounds_span = vec![];
|
||||||
let mut where_span = None;
|
let mut where_span = None;
|
||||||
|
|
||||||
if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id)
|
if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id)
|
||||||
&& let Some(trait_generics) = trait_node.generics()
|
&& let Some(trait_generics) = trait_node.generics()
|
||||||
{
|
{
|
||||||
@@ -1153,26 +1161,46 @@ fn check_region_bounds_on_impl_item<'tcx>(
|
|||||||
// FIXME: we could potentially look at the impl's bounds to not point at bounds that
|
// FIXME: we could potentially look at the impl's bounds to not point at bounds that
|
||||||
// *are* present in the impl.
|
// *are* present in the impl.
|
||||||
for p in trait_generics.predicates {
|
for p in trait_generics.predicates {
|
||||||
if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind {
|
match p.kind {
|
||||||
for b in pred.bounds {
|
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
|
||||||
|
bounds,
|
||||||
|
..
|
||||||
|
})
|
||||||
|
| hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
|
||||||
|
bounds,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
for b in *bounds {
|
||||||
if let hir::GenericBound::Outlives(lt) = b {
|
if let hir::GenericBound::Outlives(lt) = b {
|
||||||
bounds_span.push(lt.ident.span);
|
bounds_span.push(lt.ident.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id)
|
if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id)
|
||||||
&& let Some(impl_generics) = impl_node.generics()
|
&& let Some(impl_generics) = impl_node.generics()
|
||||||
{
|
{
|
||||||
let mut impl_bounds = 0;
|
let mut impl_bounds = 0;
|
||||||
for p in impl_generics.predicates {
|
for p in impl_generics.predicates {
|
||||||
if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind {
|
match p.kind {
|
||||||
for b in pred.bounds {
|
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
|
||||||
|
bounds,
|
||||||
|
..
|
||||||
|
})
|
||||||
|
| hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
|
||||||
|
bounds,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
for b in *bounds {
|
||||||
if let hir::GenericBound::Outlives(_) = b {
|
if let hir::GenericBound::Outlives(_) = b {
|
||||||
impl_bounds += 1;
|
impl_bounds += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if impl_bounds == bounds_span.len() {
|
if impl_bounds == bounds_span.len() {
|
||||||
bounds_span = vec![];
|
bounds_span = vec![];
|
||||||
@@ -1181,6 +1209,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let reported = tcx
|
let reported = tcx
|
||||||
.dcx()
|
.dcx()
|
||||||
.create_err(LifetimesOrBoundsMismatchOnTrait {
|
.create_err(LifetimesOrBoundsMismatchOnTrait {
|
||||||
@@ -1192,10 +1221,235 @@ fn check_region_bounds_on_impl_item<'tcx>(
|
|||||||
where_span,
|
where_span,
|
||||||
})
|
})
|
||||||
.emit_unless(delay);
|
.emit_unless(delay);
|
||||||
return Err(reported);
|
|
||||||
|
Err(reported)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
enum LateEarlyMismatch<'tcx> {
|
||||||
|
EarlyInImpl(DefId, DefId, ty::Region<'tcx>),
|
||||||
|
LateInImpl(DefId, DefId, ty::Region<'tcx>),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_region_late_boundedness<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
impl_m: ty::AssocItem,
|
||||||
|
trait_m: ty::AssocItem,
|
||||||
|
) -> Option<ErrorGuaranteed> {
|
||||||
|
if !impl_m.is_fn() {
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
let (infcx, param_env) = tcx
|
||||||
|
.infer_ctxt()
|
||||||
|
.build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, impl_m.def_id));
|
||||||
|
|
||||||
|
let impl_m_args = infcx.fresh_args_for_item(DUMMY_SP, impl_m.def_id);
|
||||||
|
let impl_m_sig = tcx.fn_sig(impl_m.def_id).instantiate(tcx, impl_m_args);
|
||||||
|
let impl_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, impl_m_sig);
|
||||||
|
|
||||||
|
let trait_m_args = infcx.fresh_args_for_item(DUMMY_SP, trait_m.def_id);
|
||||||
|
let trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_args);
|
||||||
|
let trait_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_m_sig);
|
||||||
|
|
||||||
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
|
|
||||||
|
// Equate the signatures so that we can infer whether a late-bound param was present where
|
||||||
|
// an early-bound param was expected, since we replace the late-bound lifetimes with
|
||||||
|
// `ReLateParam`, and early-bound lifetimes with infer vars, so the early-bound args will
|
||||||
|
// resolve to `ReLateParam` if there is a mismatch.
|
||||||
|
let Ok(()) = ocx.eq(
|
||||||
|
&ObligationCause::dummy(),
|
||||||
|
param_env,
|
||||||
|
ty::Binder::dummy(trait_m_sig),
|
||||||
|
ty::Binder::dummy(impl_m_sig),
|
||||||
|
) else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let errors = ocx.select_where_possible();
|
||||||
|
if !errors.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut mismatched = vec![];
|
||||||
|
|
||||||
|
let impl_generics = tcx.generics_of(impl_m.def_id);
|
||||||
|
for (id_arg, arg) in
|
||||||
|
std::iter::zip(ty::GenericArgs::identity_for_item(tcx, impl_m.def_id), impl_m_args)
|
||||||
|
{
|
||||||
|
if let ty::GenericArgKind::Lifetime(r) = arg.unpack()
|
||||||
|
&& let ty::ReVar(vid) = r.kind()
|
||||||
|
&& let r = infcx
|
||||||
|
.inner
|
||||||
|
.borrow_mut()
|
||||||
|
.unwrap_region_constraints()
|
||||||
|
.opportunistic_resolve_var(tcx, vid)
|
||||||
|
&& let ty::ReLateParam(ty::LateParamRegion {
|
||||||
|
kind: ty::LateParamRegionKind::Named(trait_param_def_id, _),
|
||||||
|
..
|
||||||
|
}) = r.kind()
|
||||||
|
&& let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind()
|
||||||
|
{
|
||||||
|
mismatched.push(LateEarlyMismatch::EarlyInImpl(
|
||||||
|
impl_generics.region_param(ebr, tcx).def_id,
|
||||||
|
trait_param_def_id,
|
||||||
|
id_arg.expect_region(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let trait_generics = tcx.generics_of(trait_m.def_id);
|
||||||
|
for (id_arg, arg) in
|
||||||
|
std::iter::zip(ty::GenericArgs::identity_for_item(tcx, trait_m.def_id), trait_m_args)
|
||||||
|
{
|
||||||
|
if let ty::GenericArgKind::Lifetime(r) = arg.unpack()
|
||||||
|
&& let ty::ReVar(vid) = r.kind()
|
||||||
|
&& let r = infcx
|
||||||
|
.inner
|
||||||
|
.borrow_mut()
|
||||||
|
.unwrap_region_constraints()
|
||||||
|
.opportunistic_resolve_var(tcx, vid)
|
||||||
|
&& let ty::ReLateParam(ty::LateParamRegion {
|
||||||
|
kind: ty::LateParamRegionKind::Named(impl_param_def_id, _),
|
||||||
|
..
|
||||||
|
}) = r.kind()
|
||||||
|
&& let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind()
|
||||||
|
{
|
||||||
|
mismatched.push(LateEarlyMismatch::LateInImpl(
|
||||||
|
impl_param_def_id,
|
||||||
|
trait_generics.region_param(ebr, tcx).def_id,
|
||||||
|
id_arg.expect_region(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if mismatched.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let spans: Vec<_> = mismatched
|
||||||
|
.iter()
|
||||||
|
.map(|param| {
|
||||||
|
let (LateEarlyMismatch::EarlyInImpl(impl_param_def_id, ..)
|
||||||
|
| LateEarlyMismatch::LateInImpl(impl_param_def_id, ..)) = param;
|
||||||
|
tcx.def_span(impl_param_def_id)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut diag = tcx
|
||||||
|
.dcx()
|
||||||
|
.struct_span_err(spans, "lifetime parameters do not match the trait definition")
|
||||||
|
.with_note("lifetime parameters differ in whether they are early- or late-bound")
|
||||||
|
.with_code(E0195);
|
||||||
|
for mismatch in mismatched {
|
||||||
|
match mismatch {
|
||||||
|
LateEarlyMismatch::EarlyInImpl(
|
||||||
|
impl_param_def_id,
|
||||||
|
trait_param_def_id,
|
||||||
|
early_bound_region,
|
||||||
|
) => {
|
||||||
|
let mut multispan = MultiSpan::from_spans(vec![
|
||||||
|
tcx.def_span(impl_param_def_id),
|
||||||
|
tcx.def_span(trait_param_def_id),
|
||||||
|
]);
|
||||||
|
multispan
|
||||||
|
.push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl...");
|
||||||
|
multispan
|
||||||
|
.push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait...");
|
||||||
|
multispan.push_span_label(
|
||||||
|
tcx.def_span(impl_param_def_id),
|
||||||
|
format!("`{}` is early-bound", tcx.item_name(impl_param_def_id)),
|
||||||
|
);
|
||||||
|
multispan.push_span_label(
|
||||||
|
tcx.def_span(trait_param_def_id),
|
||||||
|
format!("`{}` is late-bound", tcx.item_name(trait_param_def_id)),
|
||||||
|
);
|
||||||
|
if let Some(span) =
|
||||||
|
find_region_in_predicates(tcx, impl_m.def_id, early_bound_region)
|
||||||
|
{
|
||||||
|
multispan.push_span_label(
|
||||||
|
span,
|
||||||
|
format!(
|
||||||
|
"this lifetime bound makes `{}` early-bound",
|
||||||
|
tcx.item_name(impl_param_def_id)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
diag.span_note(
|
||||||
|
multispan,
|
||||||
|
format!(
|
||||||
|
"`{}` differs between the trait and impl",
|
||||||
|
tcx.item_name(impl_param_def_id)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
LateEarlyMismatch::LateInImpl(
|
||||||
|
impl_param_def_id,
|
||||||
|
trait_param_def_id,
|
||||||
|
early_bound_region,
|
||||||
|
) => {
|
||||||
|
let mut multispan = MultiSpan::from_spans(vec![
|
||||||
|
tcx.def_span(impl_param_def_id),
|
||||||
|
tcx.def_span(trait_param_def_id),
|
||||||
|
]);
|
||||||
|
multispan
|
||||||
|
.push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl...");
|
||||||
|
multispan
|
||||||
|
.push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait...");
|
||||||
|
multispan.push_span_label(
|
||||||
|
tcx.def_span(impl_param_def_id),
|
||||||
|
format!("`{}` is late-bound", tcx.item_name(impl_param_def_id)),
|
||||||
|
);
|
||||||
|
multispan.push_span_label(
|
||||||
|
tcx.def_span(trait_param_def_id),
|
||||||
|
format!("`{}` is early-bound", tcx.item_name(trait_param_def_id)),
|
||||||
|
);
|
||||||
|
if let Some(span) =
|
||||||
|
find_region_in_predicates(tcx, trait_m.def_id, early_bound_region)
|
||||||
|
{
|
||||||
|
multispan.push_span_label(
|
||||||
|
span,
|
||||||
|
format!(
|
||||||
|
"this lifetime bound makes `{}` early-bound",
|
||||||
|
tcx.item_name(trait_param_def_id)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
diag.span_note(
|
||||||
|
multispan,
|
||||||
|
format!(
|
||||||
|
"`{}` differs between the trait and impl",
|
||||||
|
tcx.item_name(impl_param_def_id)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(diag.emit())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_region_in_predicates<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
|
early_bound_region: ty::Region<'tcx>,
|
||||||
|
) -> Option<Span> {
|
||||||
|
for (pred, span) in tcx.explicit_predicates_of(def_id).instantiate_identity(tcx) {
|
||||||
|
if pred.visit_with(&mut FindRegion(early_bound_region)).is_break() {
|
||||||
|
return Some(span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FindRegion<'tcx>(ty::Region<'tcx>);
|
||||||
|
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindRegion<'tcx> {
|
||||||
|
type Result = ControlFlow<()>;
|
||||||
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
|
||||||
|
if r == self.0 { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(infcx))]
|
#[instrument(level = "debug", skip(infcx))]
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ pub trait Foo<'a, 't> {
|
|||||||
|
|
||||||
impl<'a, 't> Foo<'a, 't> for &'a isize {
|
impl<'a, 't> Foo<'a, 't> for &'a isize {
|
||||||
fn no_bound<'b:'a>(self, b: Inv<'b>) {
|
fn no_bound<'b:'a>(self, b: Inv<'b>) {
|
||||||
//~^ ERROR lifetime parameters or bounds on method `no_bound` do not match
|
//~^ ERROR lifetime parameters do not match the trait definition
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_bound<'b>(self, b: Inv<'b>) {
|
fn has_bound<'b>(self, b: Inv<'b>) {
|
||||||
//~^ ERROR lifetime parameters or bounds on method `has_bound` do not match
|
//~^ ERROR lifetime parameters do not match the trait definition
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
|
fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
|
||||||
@@ -40,7 +40,7 @@ impl<'a, 't> Foo<'a, 't> for &'a isize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) {
|
fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) {
|
||||||
//~^ ERROR lifetime parameters or bounds on method `wrong_bound2` do not match the trait
|
//~^ ERROR lifetime parameters do not match the trait definition
|
||||||
}
|
}
|
||||||
|
|
||||||
fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) {
|
fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) {
|
||||||
|
|||||||
@@ -1,20 +1,48 @@
|
|||||||
error[E0195]: lifetime parameters or bounds on method `no_bound` do not match the trait declaration
|
error[E0195]: lifetime parameters do not match the trait definition
|
||||||
--> $DIR/regions-bound-missing-bound-in-impl.rs:19:16
|
--> $DIR/regions-bound-missing-bound-in-impl.rs:19:17
|
||||||
|
|
|
|
||||||
LL | fn no_bound<'b>(self, b: Inv<'b>);
|
|
||||||
| ---- lifetimes in impl do not match this method in trait
|
|
||||||
...
|
|
||||||
LL | fn no_bound<'b:'a>(self, b: Inv<'b>) {
|
LL | fn no_bound<'b:'a>(self, b: Inv<'b>) {
|
||||||
| ^^^^^^^ lifetimes do not match method in trait
|
| ^^
|
||||||
|
|
||||||
error[E0195]: lifetime parameters or bounds on method `has_bound` do not match the trait declaration
|
|
||||||
--> $DIR/regions-bound-missing-bound-in-impl.rs:23:17
|
|
||||||
|
|
|
|
||||||
|
= note: lifetime parameters differ in whether they are early- or late-bound
|
||||||
|
note: `'b` differs between the trait and impl
|
||||||
|
--> $DIR/regions-bound-missing-bound-in-impl.rs:10:17
|
||||||
|
|
|
||||||
|
LL | pub trait Foo<'a, 't> {
|
||||||
|
| --------------------- in this trait...
|
||||||
|
LL | fn no_bound<'b>(self, b: Inv<'b>);
|
||||||
|
| ^^ `'b` is late-bound
|
||||||
|
...
|
||||||
|
LL | impl<'a, 't> Foo<'a, 't> for &'a isize {
|
||||||
|
| -------------------------------------- in this impl...
|
||||||
|
LL | fn no_bound<'b:'a>(self, b: Inv<'b>) {
|
||||||
|
| ^^ -- this lifetime bound makes `'b` early-bound
|
||||||
|
| |
|
||||||
|
| `'b` is early-bound
|
||||||
|
|
||||||
|
error[E0195]: lifetime parameters do not match the trait definition
|
||||||
|
--> $DIR/regions-bound-missing-bound-in-impl.rs:23:18
|
||||||
|
|
|
||||||
|
LL | fn has_bound<'b>(self, b: Inv<'b>) {
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= note: lifetime parameters differ in whether they are early- or late-bound
|
||||||
|
note: `'b` differs between the trait and impl
|
||||||
|
--> $DIR/regions-bound-missing-bound-in-impl.rs:11:18
|
||||||
|
|
|
||||||
|
LL | pub trait Foo<'a, 't> {
|
||||||
|
| --------------------- in this trait...
|
||||||
|
LL | fn no_bound<'b>(self, b: Inv<'b>);
|
||||||
LL | fn has_bound<'b:'a>(self, b: Inv<'b>);
|
LL | fn has_bound<'b:'a>(self, b: Inv<'b>);
|
||||||
| ------- lifetimes in impl do not match this method in trait
|
| ^^ -- this lifetime bound makes `'b` early-bound
|
||||||
|
| |
|
||||||
|
| `'b` is early-bound
|
||||||
|
...
|
||||||
|
LL | impl<'a, 't> Foo<'a, 't> for &'a isize {
|
||||||
|
| -------------------------------------- in this impl...
|
||||||
...
|
...
|
||||||
LL | fn has_bound<'b>(self, b: Inv<'b>) {
|
LL | fn has_bound<'b>(self, b: Inv<'b>) {
|
||||||
| ^^^^ lifetimes do not match method in trait
|
| ^^ `'b` is late-bound
|
||||||
|
|
||||||
error[E0308]: method not compatible with trait
|
error[E0308]: method not compatible with trait
|
||||||
--> $DIR/regions-bound-missing-bound-in-impl.rs:27:5
|
--> $DIR/regions-bound-missing-bound-in-impl.rs:27:5
|
||||||
@@ -54,14 +82,45 @@ note: ...does not necessarily outlive the lifetime `'c` as defined here
|
|||||||
LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
|
LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration
|
error[E0195]: lifetime parameters do not match the trait definition
|
||||||
--> $DIR/regions-bound-missing-bound-in-impl.rs:42:20
|
--> $DIR/regions-bound-missing-bound-in-impl.rs:42:30
|
||||||
|
|
|
|
||||||
|
LL | fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) {
|
||||||
|
| ^^^ ^^^
|
||||||
|
|
|
||||||
|
= note: lifetime parameters differ in whether they are early- or late-bound
|
||||||
|
note: `'_` differs between the trait and impl
|
||||||
|
--> $DIR/regions-bound-missing-bound-in-impl.rs:13:21
|
||||||
|
|
|
||||||
|
LL | pub trait Foo<'a, 't> {
|
||||||
|
| --------------------- in this trait...
|
||||||
|
...
|
||||||
LL | fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
|
LL | fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
|
||||||
| ---------------- lifetimes in impl do not match this method in trait
|
| ^^ -- this lifetime bound makes `'b` early-bound
|
||||||
|
| |
|
||||||
|
| `'b` is early-bound
|
||||||
|
...
|
||||||
|
LL | impl<'a, 't> Foo<'a, 't> for &'a isize {
|
||||||
|
| -------------------------------------- in this impl...
|
||||||
...
|
...
|
||||||
LL | fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) {
|
LL | fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) {
|
||||||
| ^ lifetimes do not match method in trait
|
| ^^^ `'_` is late-bound
|
||||||
|
note: `'_` differs between the trait and impl
|
||||||
|
--> $DIR/regions-bound-missing-bound-in-impl.rs:13:27
|
||||||
|
|
|
||||||
|
LL | pub trait Foo<'a, 't> {
|
||||||
|
| --------------------- in this trait...
|
||||||
|
...
|
||||||
|
LL | fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
|
||||||
|
| ^^ -- this lifetime bound makes `'d` early-bound
|
||||||
|
| |
|
||||||
|
| `'d` is early-bound
|
||||||
|
...
|
||||||
|
LL | impl<'a, 't> Foo<'a, 't> for &'a isize {
|
||||||
|
| -------------------------------------- in this impl...
|
||||||
|
...
|
||||||
|
LL | fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) {
|
||||||
|
| ^^^ `'_` is late-bound
|
||||||
|
|
||||||
error[E0276]: impl has stricter requirements than trait
|
error[E0276]: impl has stricter requirements than trait
|
||||||
--> $DIR/regions-bound-missing-bound-in-impl.rs:49:26
|
--> $DIR/regions-bound-missing-bound-in-impl.rs:49:26
|
||||||
|
|||||||
@@ -1,13 +1,25 @@
|
|||||||
trait Trait {
|
trait Trait {
|
||||||
|
//~^ NOTE in this trait...
|
||||||
|
//~| NOTE in this trait...
|
||||||
fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
|
fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
|
||||||
//~^ NOTE lifetimes in impl do not match this associated function in trait
|
//~^ NOTE `'a` is early-bound
|
||||||
|
//~| NOTE this lifetime bound makes `'a` early-bound
|
||||||
|
//~| NOTE `'b` is early-bound
|
||||||
|
//~| NOTE this lifetime bound makes `'b` early-bound
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
impl Trait for Foo {
|
impl Trait for Foo {
|
||||||
fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195
|
//~^ NOTE in this impl...
|
||||||
//~^ NOTE lifetimes do not match associated function in trait
|
//~| NOTE in this impl...
|
||||||
|
fn bar<'a,'b>(x: &'a str, y: &'b str) {
|
||||||
|
//~^ ERROR E0195
|
||||||
|
//~| NOTE `'a` differs between the trait and impl
|
||||||
|
//~| NOTE `'a` is late-bound
|
||||||
|
//~| NOTE `'b` differs between the trait and impl
|
||||||
|
//~| NOTE `'b` is late-bound
|
||||||
|
//~| NOTE lifetime parameters differ in whether they are early- or late-bound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,42 @@
|
|||||||
error[E0195]: lifetime parameters or bounds on associated function `bar` do not match the trait declaration
|
error[E0195]: lifetime parameters do not match the trait definition
|
||||||
--> $DIR/E0195.rs:9:11
|
--> $DIR/E0195.rs:16:12
|
||||||
|
|
|
|
||||||
|
LL | fn bar<'a,'b>(x: &'a str, y: &'b str) {
|
||||||
|
| ^^ ^^
|
||||||
|
|
|
||||||
|
= note: lifetime parameters differ in whether they are early- or late-bound
|
||||||
|
note: `'a` differs between the trait and impl
|
||||||
|
--> $DIR/E0195.rs:4:12
|
||||||
|
|
|
||||||
|
LL | trait Trait {
|
||||||
|
| ----------- in this trait...
|
||||||
|
...
|
||||||
LL | fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
|
LL | fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
|
||||||
| ---------- lifetimes in impl do not match this associated function in trait
|
| ^^ -- this lifetime bound makes `'a` early-bound
|
||||||
|
| |
|
||||||
|
| `'a` is early-bound
|
||||||
|
...
|
||||||
|
LL | impl Trait for Foo {
|
||||||
|
| ------------------ in this impl...
|
||||||
...
|
...
|
||||||
LL | fn bar<'a,'b>(x: &'a str, y: &'b str) {
|
LL | fn bar<'a,'b>(x: &'a str, y: &'b str) {
|
||||||
| ^^^^^^^ lifetimes do not match associated function in trait
|
| ^^ `'a` is late-bound
|
||||||
|
note: `'b` differs between the trait and impl
|
||||||
|
--> $DIR/E0195.rs:4:15
|
||||||
|
|
|
||||||
|
LL | trait Trait {
|
||||||
|
| ----------- in this trait...
|
||||||
|
...
|
||||||
|
LL | fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
|
||||||
|
| ^^ -- this lifetime bound makes `'b` early-bound
|
||||||
|
| |
|
||||||
|
| `'b` is early-bound
|
||||||
|
...
|
||||||
|
LL | impl Trait for Foo {
|
||||||
|
| ------------------ in this impl...
|
||||||
|
...
|
||||||
|
LL | fn bar<'a,'b>(x: &'a str, y: &'b str) {
|
||||||
|
| ^^ `'b` is late-bound
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|||||||
@@ -10,26 +10,53 @@ LL | fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a;
|
|||||||
LL | fn foo<'a, K>(self, _: (), _: K) where {
|
LL | fn foo<'a, K>(self, _: (), _: K) where {
|
||||||
| ^^^^^^^ lifetimes do not match method in trait
|
| ^^^^^^^ lifetimes do not match method in trait
|
||||||
|
|
||||||
error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
|
error[E0195]: lifetime parameters do not match the trait definition
|
||||||
--> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:23:11
|
--> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:23:12
|
||||||
|
|
|
|
||||||
|
LL | fn foo<'a>(&self, state: &'a State) -> &'a T {
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= note: lifetime parameters differ in whether they are early- or late-bound
|
||||||
|
note: `'a` differs between the trait and impl
|
||||||
|
--> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:14:12
|
||||||
|
|
|
||||||
|
LL | trait Foo<T> {
|
||||||
|
| ------------ in this trait...
|
||||||
LL | fn foo<'a>(&self, state: &'a State) -> &'a T
|
LL | fn foo<'a>(&self, state: &'a State) -> &'a T
|
||||||
| ---- lifetimes in impl do not match this method in trait
|
| ^^ `'a` is early-bound
|
||||||
LL | where
|
LL | where
|
||||||
LL | T: 'a;
|
LL | T: 'a;
|
||||||
| -- this bound might be missing in the impl
|
| -- this lifetime bound makes `'a` early-bound
|
||||||
...
|
...
|
||||||
|
LL | / impl<F, T> Foo<T> for F
|
||||||
|
LL | | where
|
||||||
|
LL | | F: Fn(&State) -> &T,
|
||||||
|
| |________________________- in this impl...
|
||||||
|
LL | {
|
||||||
LL | fn foo<'a>(&self, state: &'a State) -> &'a T {
|
LL | fn foo<'a>(&self, state: &'a State) -> &'a T {
|
||||||
| ^^^^ lifetimes do not match method in trait
|
| ^^ `'a` is late-bound
|
||||||
|
|
||||||
error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
|
error[E0195]: lifetime parameters do not match the trait definition
|
||||||
--> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:33:11
|
--> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:33:12
|
||||||
|
|
|
|
||||||
LL | fn foo<'a>(&'a self) {}
|
|
||||||
| ---- lifetimes in impl do not match this method in trait
|
|
||||||
...
|
|
||||||
LL | fn foo<'a: 'a>(&'a self) {}
|
LL | fn foo<'a: 'a>(&'a self) {}
|
||||||
| ^^^^^^^^ lifetimes do not match method in trait
|
| ^^
|
||||||
|
|
|
||||||
|
= note: lifetime parameters differ in whether they are early- or late-bound
|
||||||
|
note: `'a` differs between the trait and impl
|
||||||
|
--> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:29:12
|
||||||
|
|
|
||||||
|
LL | trait Bar {
|
||||||
|
| --------- in this trait...
|
||||||
|
LL | fn foo<'a>(&'a self) {}
|
||||||
|
| ^^ `'a` is late-bound
|
||||||
|
...
|
||||||
|
LL | impl Bar for () {
|
||||||
|
| --------------- in this impl...
|
||||||
|
LL | fn foo<'a: 'a>(&'a self) {}
|
||||||
|
| ^^ -- this lifetime bound makes `'a` early-bound
|
||||||
|
| |
|
||||||
|
| `'a` is early-bound
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user