Skip to content

A possible regression with -Zpolonius=next #160979

Description

@krasimirgg

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

<backtrace>

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-borrow-checkerArea: The borrow checkerA-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.C-bugCategory: This is a bug.NLL-poloniusIssues related for using Polonius in the borrow checkerT-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions