diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d8674817cb5eb..6b36944b20889 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -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, Span)>, item: DefId, lifetime: DefId, ) -> Vec> { 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, Span)>, index: u32, ) -> Vec> { 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, diff --git a/tests/ui/rust-2018/auxiliary/edition-lint-infer-outlives-macro.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/auxiliary/edition-lint-infer-outlives-macro.rs similarity index 100% rename from tests/ui/rust-2018/auxiliary/edition-lint-infer-outlives-macro.rs rename to tests/ui/rust-2018/edition-lint-inter-outlives/auxiliary/edition-lint-infer-outlives-macro.rs diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-macro.fixed b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.fixed similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives-macro.fixed rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.fixed diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-macro.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.rs similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives-macro.rs rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.rs diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-macro.stderr b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.stderr similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives-macro.stderr rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.stderr diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.rs similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.rs diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.stderr similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.stderr diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.fixed b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.fixed similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives.fixed rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.fixed diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.rs similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives.rs rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.rs diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.stderr b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.stderr similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives.stderr rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.stderr diff --git a/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.fixed b/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.fixed new file mode 100644 index 0000000000000..7b9fac8f408af --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.fixed @@ -0,0 +1,41 @@ +//@ run-rustfix +//@ check-pass +#![deny(explicit_outlives_requirements)] + +pub trait TypeCx { + type Ty; +} + +pub struct Pat { + pub ty: Cx::Ty, +} + +// Simple recursive case: no warning +pub struct MyTypeContextSimpleRecursive<'thir, 'tcx: 'thir> { + pub pat: Pat>, +} +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>, + pub tcx: &'tcx (), + pub thir: &'thir (), +} +impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextMixedRecursive<'thir, 'tcx> { + type Ty = (); +} + +fn main() {} diff --git a/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.rs new file mode 100644 index 0000000000000..7b9fac8f408af --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.rs @@ -0,0 +1,41 @@ +//@ run-rustfix +//@ check-pass +#![deny(explicit_outlives_requirements)] + +pub trait TypeCx { + type Ty; +} + +pub struct Pat { + pub ty: Cx::Ty, +} + +// Simple recursive case: no warning +pub struct MyTypeContextSimpleRecursive<'thir, 'tcx: 'thir> { + pub pat: Pat>, +} +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>, + pub tcx: &'tcx (), + pub thir: &'thir (), +} +impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextMixedRecursive<'thir, 'tcx> { + type Ty = (); +} + +fn main() {}