about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-10-31 21:43:19 +0000
committerMichael Goulet <michael@errs.io>2023-11-02 10:25:57 +0000
commit4d5d763e051fcbaf7b68d2b2c445d1cce21c35b4 (patch)
treed78a6c8bb771c4e7ced8534012af7e0772770b68
parent46455dc65069387f2dc46612f13fd45452ab301a (diff)
downloadrust-4d5d763e051fcbaf7b68d2b2c445d1cce21c35b4.tar.gz
rust-4d5d763e051fcbaf7b68d2b2c445d1cce21c35b4.zip
Don't check for alias bounds in liveness when aliases have escaping bound vars
-rw-r--r--compiler/rustc_infer/src/infer/outlives/for_liveness.rs10
-rw-r--r--tests/ui/borrowck/alias-liveness/escaping-bounds-2.rs14
-rw-r--r--tests/ui/borrowck/alias-liveness/escaping-bounds-2.stderr19
-rw-r--r--tests/ui/borrowck/alias-liveness/escaping-bounds.rs22
4 files changed, 64 insertions, 1 deletions
diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
index ebc51b98be5..398ac94ee36 100644
--- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
+++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
@@ -1,4 +1,6 @@
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use rustc_middle::ty::{
+    self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+};
 
 use std::ops::ControlFlow;
 
@@ -49,6 +51,12 @@ where
             return ControlFlow::Continue(());
         }
 
+        // FIXME: Don't consider alias bounds on types that have escaping bound
+        // vars. See #117455.
+        if ty.has_escaping_bound_vars() {
+            return ty.super_visit_with(self);
+        }
+
         match ty.kind() {
             // We can prove that an alias is live two ways:
             // 1. All the components are live.
diff --git a/tests/ui/borrowck/alias-liveness/escaping-bounds-2.rs b/tests/ui/borrowck/alias-liveness/escaping-bounds-2.rs
new file mode 100644
index 00000000000..05884f6741c
--- /dev/null
+++ b/tests/ui/borrowck/alias-liveness/escaping-bounds-2.rs
@@ -0,0 +1,14 @@
+trait Trait {
+    type Gat<'a: 'b, 'b: 'c, 'c>: 'c;
+}
+
+fn get_func<'a, T: Trait>(_: &'a str) -> fn(T::Gat<'a, '_, 'static>) {
+    loop {}
+}
+
+fn test<T: Trait>() {
+    let func = get_func::<T>(&String::new()); //~ ERROR temporary value dropped
+    drop(func);
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/alias-liveness/escaping-bounds-2.stderr b/tests/ui/borrowck/alias-liveness/escaping-bounds-2.stderr
new file mode 100644
index 00000000000..7fd0cb9bb02
--- /dev/null
+++ b/tests/ui/borrowck/alias-liveness/escaping-bounds-2.stderr
@@ -0,0 +1,19 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/escaping-bounds-2.rs:10:31
+   |
+LL |     let func = get_func::<T>(&String::new());
+   |                               ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
+   |                               |
+   |                               creates a temporary value which is freed while still in use
+LL |     drop(func);
+   |          ---- borrow later used here
+   |
+help: consider using a `let` binding to create a longer lived value
+   |
+LL ~     let binding = String::new();
+LL ~     let func = get_func::<T>(&binding);
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/borrowck/alias-liveness/escaping-bounds.rs b/tests/ui/borrowck/alias-liveness/escaping-bounds.rs
new file mode 100644
index 00000000000..3ccdc78e60a
--- /dev/null
+++ b/tests/ui/borrowck/alias-liveness/escaping-bounds.rs
@@ -0,0 +1,22 @@
+// check-pass
+
+// Ensure that we don't ICE when an alias that has escaping bound vars is
+// required to be live. This is because the code that allows us to deduce an
+// appropriate outlives bound for a given alias type (in this test, a
+// projection) does not handle aliases with escaping bound vars.
+// See <https://github.com/rust-lang/rust/issues/117455>.
+
+trait Foo {
+    type Assoc<'a, 'b>: 'static;
+}
+
+struct MentionsLifetimeAndType<'a, T>(&'a (), T);
+
+fn foo<'a, 'b, T: Foo>(_: <T as Foo>::Assoc<'a, 'b>) {}
+
+fn test<'b, T: Foo>() {
+    let y: MentionsLifetimeAndType<'_, for<'a> fn(<T as Foo>::Assoc<'a, 'b>)> =
+        MentionsLifetimeAndType(&(), foo);
+}
+
+fn main() {}