Point out region bound mismatches in check_region_bounds_on_impl_item

This commit is contained in:
Michael Goulet
2025-04-30 15:38:24 +00:00
parent 3ef8e64ce9
commit b27d630f89
4 changed files with 79 additions and 45 deletions

View File

@@ -1137,7 +1137,10 @@ fn check_region_bounds_on_impl_item<'tcx>(
// but found 0" it's confusing, because it looks like there
// are zero. Since I don't quite know how to phrase things at
// the moment, give a kind of vague error message.
if trait_params != impl_params {
if trait_params == impl_params {
return Ok(());
}
let span = tcx
.hir_get_generics(impl_m.def_id.expect_local())
.expect("expected impl item to have generics or else we can't compare them")
@@ -1146,6 +1149,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
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()
{
@@ -1153,26 +1157,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
// *are* present in the impl.
for p in trait_generics.predicates {
if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind {
for b in pred.bounds {
match p.kind {
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
bounds,
..
})
| hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
bounds,
..
}) => {
for b in *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::WherePredicateKind::BoundPredicate(pred) = p.kind {
for b in pred.bounds {
match p.kind {
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
bounds,
..
})
| hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
bounds,
..
}) => {
for b in *bounds {
if let hir::GenericBound::Outlives(_) = b {
impl_bounds += 1;
}
}
}
_ => {}
}
}
if impl_bounds == bounds_span.len() {
bounds_span = vec![];
@@ -1181,6 +1205,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
}
}
}
let reported = tcx
.dcx()
.create_err(LifetimesOrBoundsMismatchOnTrait {
@@ -1192,10 +1217,8 @@ fn check_region_bounds_on_impl_item<'tcx>(
where_span,
})
.emit_unless(delay);
return Err(reported);
}
Ok(())
Err(reported)
}
#[instrument(level = "debug", skip(infcx))]

View File

@@ -11,7 +11,10 @@ error[E0195]: lifetime parameters or bounds on method `has_bound` do not match t
--> $DIR/regions-bound-missing-bound-in-impl.rs:23:17
|
LL | fn has_bound<'b:'a>(self, b: Inv<'b>);
| ------- lifetimes in impl do not match this method in trait
| -------
| | |
| | this bound might be missing in the impl
| lifetimes in impl do not match this method in trait
...
LL | fn has_bound<'b>(self, b: Inv<'b>) {
| ^^^^ lifetimes do not match method in trait
@@ -58,7 +61,11 @@ error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not matc
--> $DIR/regions-bound-missing-bound-in-impl.rs:42:20
|
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 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 wrong_bound2(self, b: Inv, c: Inv, d: Inv) {
| ^ lifetimes do not match method in trait

View File

@@ -8,6 +8,7 @@ struct Foo;
impl Trait for Foo {
fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195
//~^ NOTE lifetimes do not match associated function in trait
//~| NOTE this bound might be missing in the impl
}
}

View File

@@ -2,7 +2,10 @@ error[E0195]: lifetime parameters or bounds on associated function `bar` do not
--> $DIR/E0195.rs:9:11
|
LL | fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
| ---------- lifetimes in impl do not match this associated function in trait
| ----------
| | |
| | this bound might be missing in the impl
| lifetimes in impl do not match this associated function in trait
...
LL | fn bar<'a,'b>(x: &'a str, y: &'b str) {
| ^^^^^^^ lifetimes do not match associated function in trait