A possible regression with -Zpolonius=next. Appears to be in how Polonius handles opaque types. These sound like they may be related:
I tried this code:
struct Lifetimed<'a> {
some_tuple: &'a (),
}
static LIFETIMED: Lifetimed<'static> = Lifetimed { some_tuple: &() };
struct ClosureMaker<'a> {
some_string: &'a str,
}
impl<'a> ClosureMaker<'a> {
// Returns an opaque type implementing Fn() -> T where T is &'a Lifetimed<'a>.
// The closure itself is 'static (no captures).
fn make_closure_simple(&self) -> impl Fn() -> &'a Lifetimed<'a> + 'static {
|| {
&LIFETIMED // Coerced from 'static to 'a
}
}
}
fn leak_it<T: 'static>(val: T) -> &'static T {
Box::leak(Box::new(val))
}
fn return_value_with_dangling_lifetime() {
let s = String::from("");
let cm = ClosureMaker { some_string: &s };
let val = cm.make_closure_simple()(); // Type is &'a Lifetimed<'a>
let leaked = leak_it(val); // REQUIRES &'a Lifetimed<'a>: 'static
}
I expected to see this happen: compilation to fail like it does with the old borrow checker:
% rustc -Zpolonius=off --crate-type=rlib lib.rs
error[E0597]: `s` does not live long enough
--> lib.rs:26:42
|
25 | let s = String::from("");
| - binding `s` declared here
26 | let cm = ClosureMaker { some_string: &s };
| ^^ borrowed value does not live long enough
27 | let val = cm.make_closure_simple()(); // Type is &'a Lifetimed<'a>
28 | let leaked = leak_it(val); // REQUIRES &'a Lifetimed<'a>: 'static
| ------------ argument requires that `s` is borrowed for `'static`
29 | }
| - `s` dropped here while still borrowed
|
note: requirement that the value outlives `'static` introduced here
--> lib.rs:20:15
|
20 | fn leak_it<T: 'static>(val: T) -> &'static T {
| ^^^^^^^
Instead, this happened: compilation succeeded with the new borrow checker:
% rustc -Zpolonius=next --crate-type=rlib lib.rs
warning: unused variable: `leaked`
--> lib.rs:28:9
|
28 | let leaked = leak_it(val); // REQUIRES &'a Lifetimed<'a>: 'static
| ^^^^^^ help: if this is intentional, prefix it with an underscore: `_leaked`
|
= note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default
warning: struct `Lifetimed` is never constructed
--> lib.rs:1:8
|
1 | struct Lifetimed<'a> {
| ^^^^^^^^^
|
= note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default
warning: static `LIFETIMED` is never used
--> lib.rs:4:8
|
4 | static LIFETIMED: Lifetimed<'static> = Lifetimed { some_tuple: &() };
| ^^^^^^^^^
warning: struct `ClosureMaker` is never constructed
--> lib.rs:6:8
|
6 | struct ClosureMaker<'a> {
| ^^^^^^^^^^^^
warning: method `make_closure_simple` is never used
--> lib.rs:13:8
|
10 | impl<'a> ClosureMaker<'a> {
| ------------------------- method in this implementation
...
13 | fn make_closure_simple(&self) -> impl Fn() -> &'a Lifetimed<'a> + 'static {
| ^^^^^^^^^^^^^^^^^^^
warning: function `leak_it` is never used
--> lib.rs:20:4
|
20 | fn leak_it<T: 'static>(val: T) -> &'static T {
| ^^^^^^^
warning: function `return_value_with_dangling_lifetime` is never used
--> lib.rs:24:4
|
24 | fn return_value_with_dangling_lifetime() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: 7 warnings emitted
Meta
rustc --version --verbose:
% rustc --version --verbose
rustc 1.99.0-nightly (3d6c19bb9 2026-08-11)
binary: rustc
commit-hash: 3d6c19bb9ab4798ecfb2ee943df01a811720fc27
commit-date: 2026-08-11
host: x86_64-unknown-linux-gnu
release: 1.99.0-nightly
LLVM version: 23.1.0
Backtrace
A possible regression with
-Zpolonius=next. Appears to be in how Polonius handles opaque types. These sound like they may be related:I tried this code:
I expected to see this happen: compilation to fail like it does with the old borrow checker:
Instead, this happened: compilation succeeded with the new borrow checker:
Meta
rustc --version --verbose:Backtrace