Skip to content

Wf check closure's args while borrow checking its parent#153027

Open
ShoyuVanilla wants to merge 1 commit intorust-lang:mainfrom
ShoyuVanilla:external-implied-bounds
Open

Wf check closure's args while borrow checking its parent#153027
ShoyuVanilla wants to merge 1 commit intorust-lang:mainfrom
ShoyuVanilla:external-implied-bounds

Conversation

@ShoyuVanilla
Copy link
Copy Markdown
Member

@ShoyuVanilla ShoyuVanilla commented Feb 23, 2026

View all comments

Fixes #151637

The actuall cause wasn't that the closure's return type is not being wf checked.
For example, the following code is errored out as intended:

struct Wrap<T: Default>(T);

fn error<T>(x: T) {
    || Wrap(x);
    //~^ ERROR: the trait bound `T: Default` is not satisfied
}

The problem was that we are adding implied bound T: 'static even when borrowck-ing the closures.

struct Wrap<T: 'static>(T);

fn no_error<T>(x: T) {
    || Wrap(x);
}

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 23, 2026
// for it, we might fail with the type test for it, which contains the opaque type
// and therefore `'b` as well. The problem is that if the normalized opaque type doesn't
// mentions `'b`, we have no local free region constrained by it, and end up
// emitting a borrowck error instead of propagating the closure requirements.
Copy link
Copy Markdown
Member Author

@ShoyuVanilla ShoyuVanilla Feb 23, 2026

Choose a reason for hiding this comment

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

Filtering external bounds here regresses this

.map(|&n| Container::new(n, &resolver))

@ShoyuVanilla
Copy link
Copy Markdown
Member Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors bot pushed a commit that referenced this pull request Feb 23, 2026
Do not add outlives implied bounds that contains external regions/params only
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Feb 23, 2026
@ShoyuVanilla ShoyuVanilla changed the title Do not add outlives implied bounds that contains external regions/params only Do not add outlives implied bounds containing external regions/params only Feb 23, 2026
@ShoyuVanilla ShoyuVanilla changed the title Do not add outlives implied bounds containing external regions/params only Do not add implied outlives bounds containing external regions/params only Feb 23, 2026
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors bot commented Feb 23, 2026

☀️ Try build successful (CI)
Build commit: 484ac15 (484ac156cc381bb2cfc74c800423322f261d074d, parent: eeb94be79adc9df7a09ad0b2421f16e60e6d932c)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (484ac15): comparison URL.

Overall result: no relevant changes - no action needed

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

@bors rollup=never
@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

This benchmark run did not return any relevant results for this metric.

Max RSS (memory usage)

This benchmark run did not return any relevant results for this metric.

Cycles

Results (secondary 0.6%)

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)
5.4% [2.9%, 7.9%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-4.3% [-4.5%, -4.1%] 2
All ❌✅ (primary) - - 0

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 481.498s -> 479.757s (-0.36%)
Artifact size: 395.88 MiB -> 397.89 MiB (0.51%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Feb 24, 2026
@ShoyuVanilla
Copy link
Copy Markdown
Member Author

@craterbot check

@craterbot
Copy link
Copy Markdown
Collaborator

👌 Experiment pr-153027 created and queued.
🤖 Automatically detected try build 484ac15
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 24, 2026
@ShoyuVanilla
Copy link
Copy Markdown
Member Author

This doesn't feel correct. I think I should rather add implied bounds as before and directly propagate them again as requirements.
@craterbot cancel

@craterbot
Copy link
Copy Markdown
Collaborator

🗑️ Experiment pr-153027 deleted!

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels Feb 24, 2026
@lcnr
Copy link
Copy Markdown
Contributor

lcnr commented Feb 27, 2026

This doesn't feel correct. I think I should rather add implied bounds as before and directly propagate them again as requirements.
@craterbot cancel

hmm, I do feel like only having implied bounds involving the late-bound things from the closure signature seems correct to me 🤔

@ShoyuVanilla
Copy link
Copy Markdown
Member Author

ShoyuVanilla commented Feb 28, 2026

hmm, I do feel like only having implied bounds involving the late-bound things from the closure signature seems correct to me 🤔

Yeah, only keeping bounds that involve late-bound params feels right to me, too.

But more precisely, I’m currently leaning toward

I'm a bit more inclined to: adding all the implied bounds as before, but gathering the implied bounds don't involve the late bounds and throwing them as propagated closure requirements to the parent body.

I don't have a solid logical basis for this yet 😅, but:

  1. I tried this approach and it avoids the ugly FIXME with the RegionSubAlias bounds I’m not happy with here: Wf check closure's args while borrow checking its parent #153027 (comment)
  2. I'm not even sure such cases actually exist, but I have a vague (and admittedly ungrounded) worry that dropping “legitimate” implied bounds, i.e., ones that can be proven from the parent body and don't mention late-bound params, could cause unexpected borrowck failures.
    Even if those bounds are provable by the parent, removing them outright means the closure gets borrowck-ed without assumptions that the parent could have supplied.
    Conceptually, the mental model I’m gravitating toward is:
    "Closure: Hey, parent, if you want to define me with this signature, these implied bounds are required. I'll borrowck myself assuming they hold, and you're responsible for proving them."

@ShoyuVanilla
Copy link
Copy Markdown
Member Author

ShoyuVanilla commented Feb 28, 2026

Added a bit messy experimental PoC commit: 96312b1 😅

@rust-log-analyzer

This comment has been minimized.

@lcnr
Copy link
Copy Markdown
Contributor

lcnr commented Mar 24, 2026

#153027 (comment) I think this should allow more code as propagating requirements from closures doesn't propagate them perfectly, so having more knowledge about the external regions inside of the closure is useful to make it easier to only propagate the correct things.

Looking at your impl, is there a reason we can't lazily go over the UniversalRegionRelations and propagate all the ones which only mention external regions to the parent at this point?

The actual cause wasn't that the closure's return type is not being wf checked.

Though separately, another fix would be to require the closure signature to be well-formed in the parent, would it? It's fine for the closure to assume that its signature is entirely wf if the parent body just explicitly checks that the signature is wf

@ShoyuVanilla
Copy link
Copy Markdown
Member Author

Looking at your impl, is there a reason we can't lazily go over the UniversalRegionRelations and propagate all the ones which only mention external regions to the parent at this point?

Not really. I was just doing quick PoC with a messy implementation and it ICEd 😅

Though separately, another fix would be to require the closure signature to be well-formed in the parent, would it? It's fine for the closure to assume that its signature is entirely wf if the parent body just explicitly checks that the signature is wf

Yeah, this sounds like a better fix 👍

@ShoyuVanilla ShoyuVanilla force-pushed the external-implied-bounds branch from 96312b1 to c23ddc5 Compare March 26, 2026 18:51
@ShoyuVanilla ShoyuVanilla force-pushed the external-implied-bounds branch from cf603e6 to b909428 Compare April 2, 2026 17:38
@ShoyuVanilla
Copy link
Copy Markdown
Member Author

@bors try @rust-timer queue @craterbot check

@rust-timer
Copy link
Copy Markdown
Collaborator

Error occurred while parsing comment: Invalid command argument @craterbot (there may be no spaces around the = character)

@rust-bors

This comment has been minimized.

rust-bors bot pushed a commit that referenced this pull request Apr 2, 2026
Wf check closure's args while borrow checking its parent
@ShoyuVanilla
Copy link
Copy Markdown
Member Author

@rust-timer queue
@craterbot check

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Apr 2, 2026
@craterbot
Copy link
Copy Markdown
Collaborator

👌 Experiment pr-153027 created and queued.
🤖 Automatically detected try build 7612e2d
⚠️ Try build based on commit c23ddc5, but latest commit is b909428. Did you forget to make a new try build?
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Apr 2, 2026
@ShoyuVanilla
Copy link
Copy Markdown
Member Author

Oh, it tries to use the previous artifact instead of waiting for the current one 😅
@craterbot cancel

@craterbot
Copy link
Copy Markdown
Collaborator

🗑️ Experiment pr-153027 deleted!

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels Apr 2, 2026
@rust-bors rust-bors bot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 2, 2026
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors bot commented Apr 2, 2026

💥 Test timed out after 21600s

@ShoyuVanilla
Copy link
Copy Markdown
Member Author

@bors try

@rust-bors

This comment has been minimized.

rust-bors bot pushed a commit that referenced this pull request Apr 2, 2026
Wf check closure's args while borrow checking its parent
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors bot commented Apr 3, 2026

☀️ Try build successful (CI)
Build commit: c86ec27 (c86ec274072509d26d0ee52682a0c94ed012ed89, parent: 55e86c996809902e8bbad512cfb4d2c18be446d9)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (c86ec27): comparison URL.

Overall result: ❌ regressions - please read the text below

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @rustbot label: +perf-regression-triaged. If not, please fix the regressions and do another perf run. If its results are neutral or positive, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +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.2% [0.2%, 0.2%] 1
Regressions ❌
(secondary)
1.0% [0.2%, 1.4%] 14
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.2% [0.2%, 0.2%] 1

Max RSS (memory usage)

Results (primary -1.0%, secondary -1.6%)

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)
- - 0
Improvements ✅
(primary)
-1.0% [-1.0%, -1.0%] 1
Improvements ✅
(secondary)
-1.6% [-2.0%, -1.1%] 2
All ❌✅ (primary) -1.0% [-1.0%, -1.0%] 1

Cycles

Results (secondary 4.6%)

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)
4.6% [4.6%, 4.6%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 486.952s -> 486.921s (-0.01%)
Artifact size: 395.04 MiB -> 395.12 MiB (0.02%)

@ShoyuVanilla
Copy link
Copy Markdown
Member Author

@craterbot check

@craterbot
Copy link
Copy Markdown
Collaborator

👌 Experiment pr-153027 created and queued.
🤖 Automatically detected try build c86ec27
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

perf-regression Performance regression. S-waiting-on-crater Status: Waiting on a crater run to be completed. 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.

Unsoundness due to closure return value not being checked for WF

6 participants