Skip to content

fix: fix the capture behavior of if let in closures#154210

Open
Embers-of-the-Fire wants to merge 6 commits into
rust-lang:mainfrom
Embers-of-the-Fire:feat/if-let-no-full-capture
Open

fix: fix the capture behavior of if let in closures#154210
Embers-of-the-Fire wants to merge 6 commits into
rust-lang:mainfrom
Embers-of-the-Fire:feat/if-let-no-full-capture

Conversation

@Embers-of-the-Fire
Copy link
Copy Markdown
Contributor

@Embers-of-the-Fire Embers-of-the-Fire commented Mar 22, 2026

View all comments

Closes #153982.
TL;DR This patch adds the missing capture behavior change for if let statements introduced in RFC 2229.

This patch converts

self.walk_local(init, pat, None, || self.borrow_expr(init, BorrowKind::Immutable))?;

into

self.walk_local(init, pat, None, || Ok(()))?;

so that if let now behaves like let.

@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 Mar 22, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 22, 2026

r? @mati865

rustbot has assigned @mati865.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 69 candidates
  • Random selection from 13 candidates

@meithecatte
Copy link
Copy Markdown
Contributor

Could you add a test case that's a bit more like #153982, so that there's also a field that doesn't get captured in the first place?

@Kivooeo
Copy link
Copy Markdown
Member

Kivooeo commented Mar 22, 2026

cc @Nadrieril

@theemathas theemathas added T-lang Relevant to the language team needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. needs-crater This change needs a crater run to check for possible breakage in the ecosystem. labels Mar 22, 2026
Copy link
Copy Markdown
Contributor

@meithecatte meithecatte left a comment

Choose a reason for hiding this comment

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

So, this is technically a breaking change, much like #138961, right? It'd be nice to have a proof-of-concept test on which the borrow checker will start erroring, at which point we'd probably wanna do a crater run...

View changes since this review

Comment thread compiler/rustc_hir_typeck/src/expr_use_visitor.rs Outdated
@Kivooeo
Copy link
Copy Markdown
Member

Kivooeo commented Mar 22, 2026

@bors try

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Mar 22, 2026
…e, r=<try>

fix: fix the capture behavior of `if let` in closures
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Mar 22, 2026

☀️ Try build successful (CI)
Build commit: dec9417 (dec9417b8611e34e787a3e4c37686b5131f9e5c5, parent: 562dee4820c458d823175268e41601d4c060588a)

@Kivooeo
Copy link
Copy Markdown
Member

Kivooeo commented Mar 22, 2026

I'm wondering which mode we should run crater in. Would cargo check be sufficient, or should we use build or build and test instead?

@Embers-of-the-Fire
Copy link
Copy Markdown
Contributor Author

Would cargo check be sufficient

AFAIK check should be sufficient since this patch modifies something rather high in the compiler, and in theory, strong dependencies on the size of closures shouldn't be very common. The most likely result is that we may break the unit tests for some of the lower level libraries, but it’s unlikely that this will affect functionality.

@meithecatte
Copy link
Copy Markdown
Contributor

Since this PR changes the drop order in some cases, it is technically conceivable that some code would have an observable change in behavior after this PR gets merged. It is also technically possible that a crate's test suite would notice this. I would however be extremely surprised if someone has written such code and made a test suite good enough to be able to detect this – previous experience with crater runs for similar adjustments confirms this.

If it was my call to make, I'd run a check run and assume that in the exceedingly unlikely case where someone does depend on this, it'll get caught by the full crater run for the beta.

But my call to make it is not.

@theemathas
Copy link
Copy Markdown
Contributor

It can technically change run time behavior by changing drop order. I think that's kind of unlikely to be relied on though.

@Kivooeo
Copy link
Copy Markdown
Member

Kivooeo commented Mar 22, 2026

Based on the discussion above, I'm going with just check.

@craterbot run mode=check-only

@craterbot
Copy link
Copy Markdown
Collaborator

👌 Experiment pr-154210 created and queued.
🤖 Automatically detected try build dec9417
⚠️ Try build based on commit 66777ad, but latest commit is 4d78fd1. 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. labels Mar 22, 2026
@jieyouxu
Copy link
Copy Markdown
Member

jieyouxu commented Mar 23, 2026

It can technically change run time behavior by changing drop order. I think that's kind of unlikely to be relied on though.

If this can change runtime behavior (ergo, a stable breaking change), then IMO this definitely justifies a full build-and-test not just check-only. I imagine lang would likewise want as much of the full picture as possible on ecosystem impact when making the accept/reject call.

@Nadrieril
Copy link
Copy Markdown
Member

@craterbot cancel

@craterbot
Copy link
Copy Markdown
Collaborator

🗑️ Experiment pr-154210 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 Mar 24, 2026
@Nadrieril
Copy link
Copy Markdown
Member

@craterbot run mode=build-and-test

@craterbot
Copy link
Copy Markdown
Collaborator

👌 Experiment pr-154210 created and queued.
🤖 Automatically detected try build dec9417
⚠️ Try build based on commit 66777ad, but latest commit is 4d78fd1. 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 removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 24, 2026
@traviscross traviscross removed I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang labels May 6, 2026
@rust-rfcbot rust-rfcbot added final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. and removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. labels May 6, 2026
@rust-rfcbot
Copy link
Copy Markdown
Collaborator

🔔 This is now entering its final comment period, as per the review above. 🔔

@RalfJung
Copy link
Copy Markdown
Member

RalfJung commented May 6, 2026

cc @rust-lang/opsem

This is more a question of how the generated MIR for these patterns looks like, which we're not the experts on... @Nadrieril are there tests we should have to ensure all the intended UB is captured by the generated MIR?

@Nadrieril
Copy link
Copy Markdown
Member

@Nadrieril are there tests we should have to ensure all the intended UB is captured by the generated MIR?

I'm not sure I follow, do you mean Miri tests?

@RalfJung
Copy link
Copy Markdown
Member

RalfJung commented May 7, 2026

Yes.

@Nadrieril
Copy link
Copy Markdown
Member

match and if let will have the same capture behavior after this, so you could duplicate any test with a match inside a closure and turn it into an if let (and/or vice-versa), but if you trust that the capturing and lowering is indeed the same now then you don't have to do anything.

@RalfJung
Copy link
Copy Markdown
Member

RalfJung commented May 7, 2026

Apparently the lowering was not the same before this PR so it may be worth having some sort of smoke test here?

Is there some test where Miri's verdict (UB vs non-UB) changes with this PR due to the changed capture behavior?

@rust-rfcbot rust-rfcbot added finished-final-comment-period The final comment period is finished for this PR / Issue. to-announce Announce this issue on triage meeting and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels May 16, 2026
@rust-rfcbot
Copy link
Copy Markdown
Collaborator

The final comment period, with a disposition to merge, as per the review above, is now complete.

As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

@Embers-of-the-Fire
Copy link
Copy Markdown
Contributor Author

Is there some test where Miri's verdict (UB vs non-UB) changes with this PR due to the changed capture behavior?

In #138961 there's some miri tests added, should I add some miri tests like that?

@traviscross traviscross added waived-reference-pr This language change does not need a Reference PR. relnotes Marks issues that should be documented in the release notes of the next release. labels May 20, 2026
@RalfJung
Copy link
Copy Markdown
Member

Yeah something like that -- especially if one of them changes behavior with this PR.

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 21, 2026

The Miri subtree was changed

cc @rust-lang/miri

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

Signed-off-by: Embers-of-the-Fire <stellarishs@163.com>
Add focused Miri coverage for the if-let closure capture change, demonstrating UB at closure construction when partial pattern capture reborrows dangling references.

Assisted-by: OpenAI:gpt-5.5
Signed-off-by: Embers-of-the-Fire <stellarishs@163.com>
@Embers-of-the-Fire Embers-of-the-Fire force-pushed the feat/if-let-no-full-capture branch from 4da8000 to 12dd438 Compare May 21, 2026 09:43
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 21, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. I-lang-radar Items that are on lang's radar and will need eventual work or consideration. needs-crater This change needs a crater run to check for possible breakage in the ecosystem. needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. relnotes Marks issues that should be documented in the release notes of the next release. 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. T-lang Relevant to the language team to-announce Announce this issue on triage meeting waived-reference-pr This language change does not need a Reference PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

let and if let have different closure capture behaviors