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 {
|
impl ExplicitOutlivesRequirements {
|
||||||
fn lifetimes_outliving_lifetime<'tcx>(
|
fn lifetimes_outliving_lifetime<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)],
|
inferred_outlives: impl Iterator<Item = &'tcx (ty::Clause<'tcx>, Span)>,
|
||||||
item: DefId,
|
item: DefId,
|
||||||
lifetime: DefId,
|
lifetime: DefId,
|
||||||
) -> Vec<ty::Region<'tcx>> {
|
) -> Vec<ty::Region<'tcx>> {
|
||||||
let item_generics = tcx.generics_of(item);
|
let item_generics = tcx.generics_of(item);
|
||||||
|
|
||||||
inferred_outlives
|
inferred_outlives
|
||||||
.iter()
|
|
||||||
.filter_map(|(clause, _)| match clause.kind().skip_binder() {
|
.filter_map(|(clause, _)| match clause.kind().skip_binder() {
|
||||||
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
|
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
|
||||||
ty::ReEarlyParam(ebr)
|
ty::ReEarlyParam(ebr)
|
||||||
|
@ -1947,11 +1946,10 @@ impl ExplicitOutlivesRequirements {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lifetimes_outliving_type<'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,
|
index: u32,
|
||||||
) -> Vec<ty::Region<'tcx>> {
|
) -> Vec<ty::Region<'tcx>> {
|
||||||
inferred_outlives
|
inferred_outlives
|
||||||
.iter()
|
|
||||||
.filter_map(|(clause, _)| match clause.kind().skip_binder() {
|
.filter_map(|(clause, _)| match clause.kind().skip_binder() {
|
||||||
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
|
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
|
||||||
a.is_param(index).then_some(b)
|
a.is_param(index).then_some(b)
|
||||||
|
@ -2094,7 +2092,11 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
|
||||||
(
|
(
|
||||||
Self::lifetimes_outliving_lifetime(
|
Self::lifetimes_outliving_lifetime(
|
||||||
cx.tcx,
|
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(),
|
item.owner_id.to_def_id(),
|
||||||
region_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];
|
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.bounds,
|
||||||
predicate.span,
|
predicate.span,
|
||||||
predicate.origin == PredicateOrigin::WhereClause,
|
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