about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-09-21 05:51:40 +0000
committerMichael Goulet <michael@errs.io>2023-10-14 15:35:01 +0100
commit371d8a8215597dbdb048552d7bc6962d2a95909b (patch)
tree0920e82bc70849f491a64861ffa1da44661e6713
parente425d85518b4e3c2dc6edfccab638db26380198a (diff)
downloadrust-371d8a8215597dbdb048552d7bc6962d2a95909b.tar.gz
rust-371d8a8215597dbdb048552d7bc6962d2a95909b.zip
Consider static specially
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs28
-rw-r--r--tests/ui/borrowck/alias-liveness/rtn-static.rs17
-rw-r--r--tests/ui/borrowck/alias-liveness/rtn-static.stderr11
3 files changed, 48 insertions, 8 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index d0078f71cd8..e0eed812b6a 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -619,13 +619,21 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
             inflowing_loans: &'b SparseBitMatrix<RegionVid, BorrowIndex>,
         }
         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| {
@@ -653,12 +661,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 00000000000..c850f0122e5
--- /dev/null
+++ b/tests/ui/borrowck/alias-liveness/rtn-static.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+#![feature(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<T: Foo<borrow(): 'static>>(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 00000000000..e9202db2c79
--- /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:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+