Skip to content

Treat vars created for opaque subtyping as live everywhere - #161151

Merged
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
jackh726:issue-160669-subtyping-live
Aug 18, 2026
Merged

Treat vars created for opaque subtyping as live everywhere#161151
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
jackh726:issue-160669-subtyping-live

Conversation

@jackh726

@jackh726 jackh726 commented Aug 15, 2026

Copy link
Copy Markdown
Member

Fixes #160669

r? lqd

Let's look at a minimal variant of #160669

fn minimal(short: (), out: &'static ()) -> impl Sized {
    if true {
        return &short; //~ ERROR `short` does not live long enough
    }
    out
}

That has the following (simplified) MIR:

fn foo(_1: (), _2: &'?4 ()) -> Opaque(DefId(foo::{opaque#0}), []) {
    bb0: { switchInt(move _4) -> [0: bb2, otherwise: bb1]; }

    bb1: {
        _0 = &'?2 _1; // bb1[0]
        goto -> bb3;
    }

    bb2: {
        _0 = &'?3 (*_2); // bb2[3]
        goto -> bb3;
    }

    bb3: {
        return;
    }
}

And the following region constraints:

image

Note '?5 and '?6: these don't show up in the MIR graph because they arise from the enable_subtyping closure in relate_opaques. Importantly (today), these regions are related to each other (and to other regions in hidden types) at a single point, but are not live at any point.

For NLL this is not a problem (since liveness does not matter for outlives constraint propagation. For Polonius, this is an issue.

The fix here is fairly simple: consider these lifetimes live at all points. This may be an overestimate of liveness, but this is all code that doesn't get called with the next solver.

This is also the same reason that this is not an issue with the next solver. Opaque types are normalized in HIR typeck, so these hacky regions are never created.

There are a couple alternative fixes that I think are ultimately not as good:

  1. Equate the previous hidden type with the new hidden type using Locations::All - when registering the goals from equating these two, force Locations::All instead of Locations::Single.
  2. Equate all uses, not just the final defining use, in borrowck - this has us store any duplicates in insert_hidden_type, which then get equated with the "expected" hidden type in apply_definition_site_hidden_types with Locations::All. I think this is fine, but a lot less "local" logic.

I'll note that for the next solver, we equate the hidden types with the return type in the signature withLocations::Single:

image

(note, this MIR is slightly different: '5 is short's lifetime; '6 is the lifetime from the normalized opaque (&'?6 ()); '4 is the renumbered lifetime for the MIR body)

Given that, perhaps (1) is the most faithful to the spirit of the next solver (that there is one hidden type that things get related to), but this seems like a slightly smaller-in-scope fix.

In any case, I think any solution here is mostly just a waiting game for the next solver.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Aug 15, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-cloud-vms
rust-cloud-vms Bot force-pushed the issue-160669-subtyping-live branch from 104159c to be1ec41 Compare August 15, 2026 22:47
@jackh726

Copy link
Copy Markdown
Member Author

Disclosure: An LLM was used to help diagnose the root cause of the issue

@rust-log-analyzer

This comment has been minimized.

@rust-cloud-vms
rust-cloud-vms Bot force-pushed the issue-160669-subtyping-live branch from be1ec41 to b06c28a Compare August 15, 2026 23:10
Comment thread tests/ui/nll/polonius/opaque-multiple-defining-uses-160669.rs Outdated
Comment thread tests/ui/nll/polonius/opaque-multiple-defining-uses-160669.rs Outdated
Comment thread tests/ui/nll/polonius/opaque-multiple-defining-uses-160669.rs

@lqd lqd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, I don't believe people will encounter this in practice, especially as this code will be unused in the next couple days when we enable the new solver on nightly, but it's fine to land it.

r=me with slight more focus on the regression test being old solver only, so we don't have to think much about what to do with it when we stabilize the new solver.

View changes since this review

@rust-cloud-vms
rust-cloud-vms Bot force-pushed the issue-160669-subtyping-live branch from b06c28a to 16ae7a4 Compare August 18, 2026 01:15
@jackh726

Copy link
Copy Markdown
Member Author

@bors r=lqd

@rust-bors

rust-bors Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 16ae7a4 has been approved by lqd

It is now in the queue for this repository.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 18, 2026
@rust-bors

This comment has been minimized.

@rust-bors rust-bors Bot added merged-by-bors This PR was explicitly merged by bors. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Aug 18, 2026
@rust-bors

rust-bors Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

☀️ Test successful - CI
Approved by: lqd
Duration: 3h 13m 28s
Pushing cda599c to main...

@rust-bors
rust-bors Bot merged commit cda599c into rust-lang:main Aug 18, 2026
14 checks passed
@rustbot rustbot added this to the 1.100.0 milestone Aug 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor
What is this? This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.

Comparing 8fa1c96 (parent) -> cda599c (this PR)

Test differences

Show 11 test diffs

Stage 1

  • [ui] tests/ui/nll/polonius/opaque-multiple-defining-uses-160669.rs#next: [missing] -> pass (J1)
  • [ui] tests/ui/nll/polonius/opaque-multiple-defining-uses-160669.rs#nll: [missing] -> pass (J1)
  • [ui] tests/ui/nll/polonius/opaque-multiple-defining-uses-160669.rs#polonius: [missing] -> pass (J1)
  • [ui (polonius)] tests/ui/nll/polonius/opaque-multiple-defining-uses-160669.rs#next: [missing] -> ignore (ignored when comparing with compare-mode-polonius ((explicit revisions))) (J2)
  • [ui (polonius)] tests/ui/nll/polonius/opaque-multiple-defining-uses-160669.rs#nll: [missing] -> ignore (ignored when comparing with compare-mode-polonius ((explicit revisions))) (J2)
  • [ui (polonius)] tests/ui/nll/polonius/opaque-multiple-defining-uses-160669.rs#polonius: [missing] -> ignore (ignored when comparing with compare-mode-polonius ((explicit revisions))) (J2)

Stage 2

  • [ui] tests/ui/nll/polonius/opaque-multiple-defining-uses-160669.rs#next: [missing] -> pass (J0)
  • [ui] tests/ui/nll/polonius/opaque-multiple-defining-uses-160669.rs#nll: [missing] -> pass (J0)
  • [ui] tests/ui/nll/polonius/opaque-multiple-defining-uses-160669.rs#polonius: [missing] -> pass (J0)

Additionally, 2 doctest diffs were found. These are ignored, as they are noisy.

Job group index

Test dashboard

Run

cargo run --manifest-path src/ci/citool/Cargo.toml -- \
    test-dashboard cda599c55f56d6cc234352f267102c293e55f3d0 --output-dir test-dashboard

And then open test-dashboard/index.html in your browser to see an overview of all executed tests.

Job duration changes

  1. i686-gnu-nopt-2: 1h 29m -> 2h 17m (+54.0%)
  2. pr-check-1: 29m 38s -> 17m 23s (-41.3%)
  3. x86_64-gnu-stdlib-semver-check: 12m 18s -> 7m 22s (-40.1%)
  4. dist-powerpc64le-linux-gnu: 1h 7m -> 1h 33m (+37.8%)
  5. x86_64-gnu-llvm-21-2: 1h 33m -> 58m 47s (-37.2%)
  6. dist-aarch64-linux: 1h 56m -> 2h 39m (+36.4%)
  7. x86_64-gnu-gcc-core-tests: 14m 49s -> 9m 31s (-35.8%)
  8. dist-x86_64-freebsd: 1h 3m -> 1h 24m (+33.5%)
  9. x86_64-gnu-gcc: 1h 18m -> 54m 14s (-30.5%)
  10. tidy: 2m 18s -> 2m 59s (+29.9%)
How to interpret the job duration changes?

Job durations can vary a lot, based on the actual runner instance
that executed the job, system noise, invalidated caches, etc. The table above is provided
mostly for t-infra members, for simpler debugging of potential CI slow-downs.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (cda599c): comparison URL.

Overall result: ✅ improvements - no action needed

@rustbot label: -perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.3% [-0.3%, -0.3%] 1
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (primary 2.1%, secondary 2.4%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
2.1% [2.1%, 2.1%] 1
Regressions ❌
(secondary)
2.4% [2.4%, 2.4%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 2.1% [2.1%, 2.1%] 1

Cycles

Results (secondary 1.0%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
1.0% [1.0%, 1.0%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Binary size

This perf run didn't have relevant results for this metric.

Bootstrap: 458.344s -> 455.4s (-0.64%)
Artifact size: 398.95 MiB -> 398.90 MiB (-0.01%)

@jackh726
jackh726 deleted the issue-160669-subtyping-live branch August 18, 2026 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merged-by-bors This PR was explicitly merged by bors. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Zpolonius=next soundness bug: defining use of an opaque type discards the first one's region

5 participants