diagnostics: do not warn when a lifetime bound infers itself

This commit is contained in:
Michael Howell 2024-08-09 16:15:40 -07:00
parent ca5d25e2c4
commit 4dc13c5471
12 changed files with 97 additions and 6 deletions

View File

@ -1924,14 +1924,13 @@ fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
impl ExplicitOutlivesRequirements {
fn lifetimes_outliving_lifetime<'tcx>(
tcx: TyCtxt<'tcx>,
inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)],
inferred_outlives: impl Iterator<Item = &'tcx (ty::Clause<'tcx>, Span)>,
item: DefId,
lifetime: DefId,
) -> Vec<ty::Region<'tcx>> {
let item_generics = tcx.generics_of(item);
inferred_outlives
.iter()
.filter_map(|(clause, _)| match clause.kind().skip_binder() {
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
ty::ReEarlyParam(ebr)
@ -1947,11 +1946,10 @@ fn lifetimes_outliving_lifetime<'tcx>(
}
fn lifetimes_outliving_type<'tcx>(
inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)],
inferred_outlives: impl Iterator<Item = &'tcx (ty::Clause<'tcx>, Span)>,
index: u32,
) -> Vec<ty::Region<'tcx>> {
inferred_outlives
.iter()
.filter_map(|(clause, _)| match clause.kind().skip_binder() {
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
a.is_param(index).then_some(b)
@ -2094,7 +2092,11 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
(
Self::lifetimes_outliving_lifetime(
cx.tcx,
inferred_outlives,
// don't warn if the inferred span actually came from the predicate we're looking at
// this happens if the type is recursively defined
inferred_outlives
.iter()
.filter(|(_, span)| !predicate.span.contains(*span)),
item.owner_id.to_def_id(),
region_def_id,
),
@ -2116,7 +2118,14 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
};
let index = ty_generics.param_def_id_to_index[&def_id];
(
Self::lifetimes_outliving_type(inferred_outlives, index),
Self::lifetimes_outliving_type(
// don't warn if the inferred span actually came from the predicate we're looking at
// this happens if the type is recursively defined
inferred_outlives.iter().filter(|(_, span)| {
!predicate.span.contains(*span)
}),
index,
),
&predicate.bounds,
predicate.span,
predicate.origin == PredicateOrigin::WhereClause,

View File

@ -0,0 +1,41 @@
//@ run-rustfix
//@ check-pass
#![deny(explicit_outlives_requirements)]
pub trait TypeCx {
type Ty;
}
pub struct Pat<Cx: TypeCx> {
pub ty: Cx::Ty,
}
// Simple recursive case: no warning
pub struct MyTypeContextSimpleRecursive<'thir, 'tcx: 'thir> {
pub pat: Pat<MyTypeContextSimpleRecursive<'thir, 'tcx>>,
}
impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextSimpleRecursive<'thir, 'tcx> {
type Ty = ();
}
// Non-recursive case: we want a warning
pub struct MyTypeContextNotRecursive<'thir, 'tcx: 'thir> {
pub tcx: &'tcx (),
pub thir: &'thir (),
}
impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextNotRecursive<'thir, 'tcx> {
type Ty = ();
}
// Mixed-recursive case: we want a warning
pub struct MyTypeContextMixedRecursive<'thir, 'tcx: 'thir> {
pub pat: Pat<MyTypeContextMixedRecursive<'thir, 'tcx>>,
pub tcx: &'tcx (),
pub thir: &'thir (),
}
impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextMixedRecursive<'thir, 'tcx> {
type Ty = ();
}
fn main() {}

View File

@ -0,0 +1,41 @@
//@ run-rustfix
//@ check-pass
#![deny(explicit_outlives_requirements)]
pub trait TypeCx {
type Ty;
}
pub struct Pat<Cx: TypeCx> {
pub ty: Cx::Ty,
}
// Simple recursive case: no warning
pub struct MyTypeContextSimpleRecursive<'thir, 'tcx: 'thir> {
pub pat: Pat<MyTypeContextSimpleRecursive<'thir, 'tcx>>,
}
impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextSimpleRecursive<'thir, 'tcx> {
type Ty = ();
}
// Non-recursive case: we want a warning
pub struct MyTypeContextNotRecursive<'thir, 'tcx: 'thir> {
pub tcx: &'tcx (),
pub thir: &'thir (),
}
impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextNotRecursive<'thir, 'tcx> {
type Ty = ();
}
// Mixed-recursive case: we want a warning
pub struct MyTypeContextMixedRecursive<'thir, 'tcx: 'thir> {
pub pat: Pat<MyTypeContextMixedRecursive<'thir, 'tcx>>,
pub tcx: &'tcx (),
pub thir: &'thir (),
}
impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextMixedRecursive<'thir, 'tcx> {
type Ty = ();
}
fn main() {}