Skip to content

[-Znext-solver] Outlive clauses in param env are incorrectly skipped in liveness analysis #158461

Description

@adwinwhite

I tried this code:

trait Id {
    type SelfType;
}

impl<T> Id for T {
    type SelfType = T;
}

trait Foo {
    type Assoc<'a>
    where
        Self: 'a;

    fn assoc(&mut self) -> Self::Assoc<'_>;
}

fn overlapping_mut<T>(mut t: T)
where
    T: Foo,
    for<'a> <T::Assoc<'a> as Id>::SelfType: 'static,
{
    let a = t.assoc();
    let b = t.assoc();
}

fn live_past_borrow<T>(mut t: T)
where
    T: Foo,
    for<'a> <T::Assoc<'a> as Id>::SelfType: 'static {
    let x = t.assoc();
    drop(t);
    drop(x);
}

I expected to see this happen: It compiles like with the old solver.

Instead, this happened:

error[E0499]: cannot borrow `t` as mutable more than once at a time
  --> counter_examples/unnormalized-into-outlive.rs:25:13
   |
24 |     let a = t.assoc();
   |             - first mutable borrow occurs here
25 |     let b = t.assoc();
   |             ^ second mutable borrow occurs here
26 | }
   | - first borrow might be used here, when `a` is dropped and runs the destructor for type `<T as Foo>::Assoc<'_>`

error[E0505]: cannot move out of `t` because it is borrowed
  --> counter_examples/unnormalized-into-outlive.rs:33:10
   |
28 | fn live_past_borrow<T>(mut t: T)
   |                        ----- binding `t` declared here
...
32 |     let x = t.assoc();
   |             - borrow of `t` occurs here
33 |     drop(t);
   |          ^ move out of `t` occurs here
34 |     drop(x);
   |          - borrow later used here

error: aborting due to 2 previous errors

Meta

rustc --version --verbose:

rustc 1.98.0-dev (2026--6-26)
binary: rustc
commit-hash: unknown
commit-date: unknown
host: x86_64-unknown-linux-gnu
release: 1.98.0-dev
LLVM version: 22.1.8

Analysis

We try to record free regions from TypeOutlives bounds.
We only care about the region if the outlive ty is equal to current alias ty.
But the outlive ty from param env is unnormalized and fails the equality check.

Related tests

These can be adapted into regression tests for the fix:
tests/ui/borrowck/alias-liveness/gat-static.rs - just use the example code above.
tests/ui/borrowck/alias-liveness/rtn-static.rs - exploiting RTN is harder, if possible. We can only use it in specific positions.

cc @lcnr

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.WG-trait-system-refactorThe Rustc Trait System Refactor Initiative (-Znext-solver)

    Type

    No type

    Projects

    Status
    in progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions