Rollup merge of #105005 - estebank:where-clause-lts, r=compiler-errors
On E0195 point at where clause lifetime bounds Fix #104733
This commit is contained in:
commit
be3ad5d6b0
5 changed files with 120 additions and 11 deletions
|
@ -17,6 +17,8 @@ hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
|
||||||
lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
|
lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
|
||||||
.label = lifetimes do not match {$item_kind} in trait
|
.label = lifetimes do not match {$item_kind} in trait
|
||||||
.generics_label = lifetimes in impl do not match this {$item_kind} in trait
|
.generics_label = lifetimes in impl do not match this {$item_kind} in trait
|
||||||
|
.where_label = this `where` clause might not match the one in the trait
|
||||||
|
.bounds_label = this bound might be missing in the impl
|
||||||
|
|
||||||
hir_analysis_drop_impl_on_wrong_item =
|
hir_analysis_drop_impl_on_wrong_item =
|
||||||
the `Drop` trait may only be implemented for local structs, enums, and unions
|
the `Drop` trait may only be implemented for local structs, enums, and unions
|
||||||
|
|
|
@ -751,17 +751,45 @@ fn check_region_bounds_on_impl_item<'tcx>(
|
||||||
.get_generics(impl_m.def_id.expect_local())
|
.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")
|
||||||
.span;
|
.span;
|
||||||
let generics_span = if let Some(local_def_id) = trait_m.def_id.as_local() {
|
|
||||||
Some(
|
|
||||||
tcx.hir()
|
|
||||||
.get_generics(local_def_id)
|
|
||||||
.expect("expected trait item to have generics or else we can't compare them")
|
|
||||||
.span,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
|
let mut generics_span = None;
|
||||||
|
let mut bounds_span = vec![];
|
||||||
|
let mut where_span = None;
|
||||||
|
if let Some(trait_node) = tcx.hir().get_if_local(trait_m.def_id)
|
||||||
|
&& let Some(trait_generics) = trait_node.generics()
|
||||||
|
{
|
||||||
|
generics_span = Some(trait_generics.span);
|
||||||
|
// FIXME: we could potentially look at the impl's bounds to not point at bounds that
|
||||||
|
// *are* present in the impl.
|
||||||
|
for p in trait_generics.predicates {
|
||||||
|
if let hir::WherePredicate::BoundPredicate(pred) = p {
|
||||||
|
for b in pred.bounds {
|
||||||
|
if let hir::GenericBound::Outlives(lt) = b {
|
||||||
|
bounds_span.push(lt.ident.span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(impl_node) = tcx.hir().get_if_local(impl_m.def_id)
|
||||||
|
&& let Some(impl_generics) = impl_node.generics()
|
||||||
|
{
|
||||||
|
let mut impl_bounds = 0;
|
||||||
|
for p in impl_generics.predicates {
|
||||||
|
if let hir::WherePredicate::BoundPredicate(pred) = p {
|
||||||
|
for b in pred.bounds {
|
||||||
|
if let hir::GenericBound::Outlives(_) = b {
|
||||||
|
impl_bounds += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if impl_bounds == bounds_span.len() {
|
||||||
|
bounds_span = vec![];
|
||||||
|
} else if impl_generics.has_where_clause_predicates {
|
||||||
|
where_span = Some(impl_generics.where_clause_span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
let reported = tcx
|
let reported = tcx
|
||||||
.sess
|
.sess
|
||||||
.create_err(LifetimesOrBoundsMismatchOnTrait {
|
.create_err(LifetimesOrBoundsMismatchOnTrait {
|
||||||
|
@ -769,9 +797,10 @@ fn check_region_bounds_on_impl_item<'tcx>(
|
||||||
item_kind: assoc_item_kind_str(impl_m),
|
item_kind: assoc_item_kind_str(impl_m),
|
||||||
ident: impl_m.ident(tcx),
|
ident: impl_m.ident(tcx),
|
||||||
generics_span,
|
generics_span,
|
||||||
|
bounds_span,
|
||||||
|
where_span,
|
||||||
})
|
})
|
||||||
.emit_unless(delay);
|
.emit_unless(delay);
|
||||||
|
|
||||||
return Err(reported);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,10 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[label(generics_label)]
|
#[label(generics_label)]
|
||||||
pub generics_span: Option<Span>,
|
pub generics_span: Option<Span>,
|
||||||
|
#[label(where_label)]
|
||||||
|
pub where_span: Option<Span>,
|
||||||
|
#[label(bounds_label)]
|
||||||
|
pub bounds_span: Vec<Span>,
|
||||||
pub item_kind: &'static str,
|
pub item_kind: &'static str,
|
||||||
pub ident: Ident,
|
pub ident: Ident,
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
trait Trait<T> {
|
||||||
|
fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait<()> for () {
|
||||||
|
fn foo<'a, K>(self, _: (), _: K) where { //~ ERROR E0195
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct State;
|
||||||
|
|
||||||
|
trait Foo<T> {
|
||||||
|
fn foo<'a>(&self, state: &'a State) -> &'a T
|
||||||
|
where
|
||||||
|
T: 'a;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, T> Foo<T> for F
|
||||||
|
where
|
||||||
|
F: Fn(&State) -> &T,
|
||||||
|
{
|
||||||
|
fn foo<'a>(&self, state: &'a State) -> &'a T { //~ ERROR E0195
|
||||||
|
self(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Bar {
|
||||||
|
fn foo<'a>(&'a self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bar for () {
|
||||||
|
fn foo<'a: 'a>(&'a self) {} //~ ERROR E0195
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
().foo((), ());
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
|
||||||
|
--> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:6:11
|
||||||
|
|
|
||||||
|
LL | fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a;
|
||||||
|
| ------- -- -- this bound might be missing in the impl
|
||||||
|
| | |
|
||||||
|
| | this bound might be missing in the impl
|
||||||
|
| lifetimes in impl do not match this method in trait
|
||||||
|
...
|
||||||
|
LL | fn foo<'a, K>(self, _: (), _: K) where {
|
||||||
|
| ^^^^^^^ lifetimes do not match method in trait
|
||||||
|
|
||||||
|
error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
|
||||||
|
--> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:23:11
|
||||||
|
|
|
||||||
|
LL | fn foo<'a>(&self, state: &'a State) -> &'a T
|
||||||
|
| ---- lifetimes in impl do not match this method in trait
|
||||||
|
LL | where
|
||||||
|
LL | T: 'a;
|
||||||
|
| -- this bound might be missing in the impl
|
||||||
|
...
|
||||||
|
LL | fn foo<'a>(&self, state: &'a State) -> &'a T {
|
||||||
|
| ^^^^ lifetimes do not match method in trait
|
||||||
|
|
||||||
|
error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
|
||||||
|
--> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:33:11
|
||||||
|
|
|
||||||
|
LL | fn foo<'a>(&'a self) {}
|
||||||
|
| ---- lifetimes in impl do not match this method in trait
|
||||||
|
...
|
||||||
|
LL | fn foo<'a: 'a>(&'a self) {}
|
||||||
|
| ^^^^^^^^ lifetimes do not match method in trait
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0195`.
|
Loading…
Add table
Add a link
Reference in a new issue