From 0135ccdaeab4681f22b339b8897aa66528927829 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Sep 2023 05:51:40 +0000 Subject: [PATCH] Consider static specially --- .../src/type_check/liveness/trace.rs | 28 +++++++++++++------ .../ui/borrowck/alias-liveness/rtn-static.rs | 17 +++++++++++ .../borrowck/alias-liveness/rtn-static.stderr | 11 ++++++++ 3 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 tests/ui/borrowck/alias-liveness/rtn-static.rs create mode 100644 tests/ui/borrowck/alias-liveness/rtn-static.stderr diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 4a2fd6bb7ea7d..053d35eedda69 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -565,13 +565,21 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { live_at: &'b IntervalSet, } impl<'tcx> MakeAllRegionsLive<'_, '_, 'tcx> { + /// We can prove that an alias is live two ways: + /// 1. All the components are live. + /// 2. There is a known outlives bound or where-clause, and that + /// region is live. + /// We search through the item bounds and where clauses for + /// either `'static` or a unique outlives region, and if one is + /// found, we just need to prove that that region is still live. + /// If one is not found, then we continue to walk through the alias. fn make_alias_live(&mut self, t: Ty<'tcx>) -> ControlFlow { let ty::Alias(_kind, alias_ty) = t.kind() else { - bug!(); + bug!("`make_alias_live` only takes alias types"); }; let tcx = self.typeck.infcx.tcx; let param_env = self.typeck.param_env; - let mut outlives_bounds = tcx + let outlives_bounds: Vec<_> = tcx .item_bounds(alias_ty.def_id) .iter_instantiated(tcx, alias_ty.args) .filter_map(|clause| { @@ -599,12 +607,16 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { t, ) } - })); - if let Some(r) = outlives_bounds.next() - && !r.is_late_bound() - && outlives_bounds.all(|other_r| { - other_r == r - }) + })) + .collect(); + // If we find `'static`, then we know the alias doesn't capture *any* regions. + // Otherwise, all of the outlives regions should be equal -- if they're not, + // we don't really know how to proceed, so we continue recursing through the + // alias. + if outlives_bounds.contains(&tcx.lifetimes.re_static) { + ControlFlow::Continue(()) + } else if let Some(r) = outlives_bounds.first() + && outlives_bounds[1..].iter().all(|other_r| other_r == r) { r.visit_with(self) } else { diff --git a/tests/ui/borrowck/alias-liveness/rtn-static.rs b/tests/ui/borrowck/alias-liveness/rtn-static.rs new file mode 100644 index 0000000000000..f0e8f3cd5129f --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/rtn-static.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait, return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait Foo { + fn borrow(&mut self) -> impl Sized + '_; +} + +// Test that the `'_` item bound in `borrow` does not cause us to +// overlook the `'static` RTN bound. +fn test>(mut t: T) { + let x = t.borrow(); + let x = t.borrow(); +} + +fn main() {} diff --git a/tests/ui/borrowck/alias-liveness/rtn-static.stderr b/tests/ui/borrowck/alias-liveness/rtn-static.stderr new file mode 100644 index 0000000000000..ebc95f18e16d7 --- /dev/null +++ b/tests/ui/borrowck/alias-liveness/rtn-static.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/rtn-static.rs:3:49 + | +LL | #![feature(return_position_impl_trait_in_trait, return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted +