From 4d5d763e051fcbaf7b68d2b2c445d1cce21c35b4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 31 Oct 2023 21:43:19 +0000 Subject: [PATCH] Don't check for alias bounds in liveness when aliases have escaping bound vars --- .../src/infer/outlives/for_liveness.rs | 10 ++++++++- .../alias-liveness/escaping-bounds-2.rs | 14 ++++++++++++ .../alias-liveness/escaping-bounds-2.stderr | 19 ++++++++++++++++ .../alias-liveness/escaping-bounds.rs | 22 +++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/ui/borrowck/alias-liveness/escaping-bounds-2.rs create mode 100644 tests/ui/borrowck/alias-liveness/escaping-bounds-2.stderr create mode 100644 tests/ui/borrowck/alias-liveness/escaping-bounds.rs 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() { + let func = get_func::(&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::(&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::(&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 . + +trait Foo { + type Assoc<'a, 'b>: 'static; +} + +struct MentionsLifetimeAndType<'a, T>(&'a (), T); + +fn foo<'a, 'b, T: Foo>(_: ::Assoc<'a, 'b>) {} + +fn test<'b, T: Foo>() { + let y: MentionsLifetimeAndType<'_, for<'a> fn(::Assoc<'a, 'b>)> = + MentionsLifetimeAndType(&(), foo); +} + +fn main() {}