Skip to content

Commit

Permalink
Rollup merge of rust-lang#105005 - estebank:where-clause-lts, r=compi…
Browse files Browse the repository at this point in the history
…ler-errors

On E0195 point at where clause lifetime bounds

Fix rust-lang#104733
  • Loading branch information
matthiaskrgr authored Dec 6, 2022
2 parents 7b2f2a8 + 9ffd086 commit 33bbb02
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 11 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
.label = lifetimes do not match {$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 =
the `Drop` trait may only be implemented for local structs, enums, and unions
Expand Down
51 changes: 40 additions & 11 deletions compiler/rustc_hir_analysis/src/check/compare_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -751,27 +751,56 @@ fn check_region_bounds_on_impl_item<'tcx>(
.get_generics(impl_m.def_id.expect_local())
.expect("expected impl item to have generics or else we can't compare them")
.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
.sess
.create_err(LifetimesOrBoundsMismatchOnTrait {
span,
item_kind: assoc_item_kind_str(impl_m),
ident: impl_m.ident(tcx),
generics_span,
bounds_span,
where_span,
})
.emit_unless(delay);

return Err(reported);
}

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
pub span: Span,
#[label(generics_label)]
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 ident: Ident,
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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((), ());
}
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 33bbb02

Please sign in to comment.