diagnostics: do not warn when a lifetime bound infers itself
This commit is contained in:
parent
ca5d25e2c4
commit
4dc13c5471
12 changed files with 97 additions and 6 deletions
|
@ -1924,14 +1924,13 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN
|
|||
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 @@ impl ExplicitOutlivesRequirements {
|
|||
}
|
||||
|
||||
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 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
|
|||
(
|
||||
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 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
|
|||
};
|
||||
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,
|
||||
|
|
|
@ -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() {}
|
|
@ -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() {}
|
Loading…
Add table
Reference in a new issue