Skip to content

Commit be3ad5d

Browse files
authored
Rollup merge of #105005 - estebank:where-clause-lts, r=compiler-errors
On E0195 point at where clause lifetime bounds Fix #104733
2 parents e5a01b9 + 9ffd086 commit be3ad5d

File tree

5 files changed

+120
-11
lines changed

5 files changed

+120
-11
lines changed

compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
1717
lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
1818
.label = lifetimes do not match {$item_kind} in trait
1919
.generics_label = lifetimes in impl do not match this {$item_kind} in trait
20+
.where_label = this `where` clause might not match the one in the trait
21+
.bounds_label = this bound might be missing in the impl
2022
2123
hir_analysis_drop_impl_on_wrong_item =
2224
the `Drop` trait may only be implemented for local structs, enums, and unions

compiler/rustc_hir_analysis/src/check/compare_method.rs

+40-11
Original file line numberDiff line numberDiff line change
@@ -751,27 +751,56 @@ fn check_region_bounds_on_impl_item<'tcx>(
751751
.get_generics(impl_m.def_id.expect_local())
752752
.expect("expected impl item to have generics or else we can't compare them")
753753
.span;
754-
let generics_span = if let Some(local_def_id) = trait_m.def_id.as_local() {
755-
Some(
756-
tcx.hir()
757-
.get_generics(local_def_id)
758-
.expect("expected trait item to have generics or else we can't compare them")
759-
.span,
760-
)
761-
} else {
762-
None
763-
};
764754

755+
let mut generics_span = None;
756+
let mut bounds_span = vec![];
757+
let mut where_span = None;
758+
if let Some(trait_node) = tcx.hir().get_if_local(trait_m.def_id)
759+
&& let Some(trait_generics) = trait_node.generics()
760+
{
761+
generics_span = Some(trait_generics.span);
762+
// FIXME: we could potentially look at the impl's bounds to not point at bounds that
763+
// *are* present in the impl.
764+
for p in trait_generics.predicates {
765+
if let hir::WherePredicate::BoundPredicate(pred) = p {
766+
for b in pred.bounds {
767+
if let hir::GenericBound::Outlives(lt) = b {
768+
bounds_span.push(lt.ident.span);
769+
}
770+
}
771+
}
772+
}
773+
if let Some(impl_node) = tcx.hir().get_if_local(impl_m.def_id)
774+
&& let Some(impl_generics) = impl_node.generics()
775+
{
776+
let mut impl_bounds = 0;
777+
for p in impl_generics.predicates {
778+
if let hir::WherePredicate::BoundPredicate(pred) = p {
779+
for b in pred.bounds {
780+
if let hir::GenericBound::Outlives(_) = b {
781+
impl_bounds += 1;
782+
}
783+
}
784+
}
785+
}
786+
if impl_bounds == bounds_span.len() {
787+
bounds_span = vec![];
788+
} else if impl_generics.has_where_clause_predicates {
789+
where_span = Some(impl_generics.where_clause_span);
790+
}
791+
}
792+
}
765793
let reported = tcx
766794
.sess
767795
.create_err(LifetimesOrBoundsMismatchOnTrait {
768796
span,
769797
item_kind: assoc_item_kind_str(impl_m),
770798
ident: impl_m.ident(tcx),
771799
generics_span,
800+
bounds_span,
801+
where_span,
772802
})
773803
.emit_unless(delay);
774-
775804
return Err(reported);
776805
}
777806

compiler/rustc_hir_analysis/src/errors.rs

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
4343
pub span: Span,
4444
#[label(generics_label)]
4545
pub generics_span: Option<Span>,
46+
#[label(where_label)]
47+
pub where_span: Option<Span>,
48+
#[label(bounds_label)]
49+
pub bounds_span: Vec<Span>,
4650
pub item_kind: &'static str,
4751
pub ident: Ident,
4852
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
trait Trait<T> {
2+
fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a;
3+
}
4+
5+
impl Trait<()> for () {
6+
fn foo<'a, K>(self, _: (), _: K) where { //~ ERROR E0195
7+
todo!();
8+
}
9+
}
10+
11+
struct State;
12+
13+
trait Foo<T> {
14+
fn foo<'a>(&self, state: &'a State) -> &'a T
15+
where
16+
T: 'a;
17+
}
18+
19+
impl<F, T> Foo<T> for F
20+
where
21+
F: Fn(&State) -> &T,
22+
{
23+
fn foo<'a>(&self, state: &'a State) -> &'a T { //~ ERROR E0195
24+
self(state)
25+
}
26+
}
27+
28+
trait Bar {
29+
fn foo<'a>(&'a self) {}
30+
}
31+
32+
impl Bar for () {
33+
fn foo<'a: 'a>(&'a self) {} //~ ERROR E0195
34+
}
35+
36+
fn main() {
37+
().foo((), ());
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
2+
--> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:6:11
3+
|
4+
LL | fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a;
5+
| ------- -- -- this bound might be missing in the impl
6+
| | |
7+
| | this bound might be missing in the impl
8+
| lifetimes in impl do not match this method in trait
9+
...
10+
LL | fn foo<'a, K>(self, _: (), _: K) where {
11+
| ^^^^^^^ lifetimes do not match method in trait
12+
13+
error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
14+
--> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:23:11
15+
|
16+
LL | fn foo<'a>(&self, state: &'a State) -> &'a T
17+
| ---- lifetimes in impl do not match this method in trait
18+
LL | where
19+
LL | T: 'a;
20+
| -- this bound might be missing in the impl
21+
...
22+
LL | fn foo<'a>(&self, state: &'a State) -> &'a T {
23+
| ^^^^ lifetimes do not match method in trait
24+
25+
error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
26+
--> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:33:11
27+
|
28+
LL | fn foo<'a>(&'a self) {}
29+
| ---- lifetimes in impl do not match this method in trait
30+
...
31+
LL | fn foo<'a: 'a>(&'a self) {}
32+
| ^^^^^^^^ lifetimes do not match method in trait
33+
34+
error: aborting due to 3 previous errors
35+
36+
For more information about this error, try `rustc --explain E0195`.

0 commit comments

Comments
 (0)