Skip to content

borrowck: Restore alias rigidity from HIR typeck - #161926

Merged
rust-bors[bot] merged 3 commits into
rust-lang:mainfrom
Dnreikronos:borrowck/restore_alias_rigidity
Aug 31, 2026
Merged

borrowck: Restore alias rigidity from HIR typeck#161926
rust-bors[bot] merged 3 commits into
rust-lang:mainfrom
Dnreikronos:borrowck/restore_alias_rigidity

Conversation

@Dnreikronos

@Dnreikronos Dnreikronos commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #161012. This came out of the review thread here:
#161012 (comment)

Borrowck was normalizing the closure type again in a fresh inference context. HIR writeback had already done that work. EarlyBinder only marked the aliases as non-rigid again because it has to be conservative. If the second normalization creates region constraints, they disappear with the temporary context.

I first thought normalizing again here was fine. After tracing the type back through writeback, I think it makes more sense to trust the result from HIR typeck. Borrowck now restores the rigid flag, and the IsRigid docs explain that this state can carry into borrowck and when it needs to be reset.

Tested with the coroutine regression and tidy.

cc @adwinwhite @lcnr

HIR writeback already normalizes closure types. Reuse that result instead of normalizing again in a temporary inference context that would drop region constraints.
@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 28, 2026
@rustbot

rustbot commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

r? @folkertdev

rustbot has assigned @folkertdev.
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: borrowck, compiler
  • borrowck, compiler expanded to 75 candidates
  • Random selection from 21 candidates

@folkertdev

Copy link
Copy Markdown
Contributor

r? types

@rustbot rustbot added the T-types Relevant to the types team, which will review and decide on the PR/issue. label Aug 28, 2026
@rustbot rustbot assigned BoxyUwU and unassigned folkertdev Aug 28, 2026
@lcnr

lcnr commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

r? adwinwhite :>

@rustbot rustbot assigned adwinwhite and unassigned BoxyUwU Aug 28, 2026
Comment thread compiler/rustc_type_ir/src/ty_kind.rs Outdated
Comment on lines +115 to +119
/// Rigidness is shared across inference contexts and compiler phases. For example, aliases
/// normalized during HIR typeck can remain rigid when the resulting type is later used by
/// borrowck. They must be made non-rigid again if they enter a typing mode or parameter
/// environment in which further normalization may be possible.
///

@adwinwhite adwinwhite Aug 29, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Rigidness is shared across inference contexts and compiler phases. For example, aliases
/// normalized during HIR typeck can remain rigid when the resulting type is later used by
/// borrowck. They must be made non-rigid again if they enter a typing mode or parameter
/// environment in which further normalization may be possible.
///
/// Rigidness becomes outdated when the surrounding typing mode or param env changes,
/// because further normalization might be possible.
/// We should also note that rigidness can be shared within some typing mode groups
/// if the param env is the same, e.g., `Typeck/PostTypeckUntilBorrowck` and
/// `PostAnalysis/Codegen`.
///

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah, I think I wrote that comment around this PR instead of explaining the actual rule. The flag becomes stale when the typing mode or param env changes and more normalization could become possible. Typeck/PostTypeckUntilBorrowck can still share it when the param env is the same, and the same goes for PostAnalysis/Codegen.

I changed the docs along those lines. I like this wording more because it explains when rigidness stops being valid, instead of making HIR typeck and borrowck sound like a special case.

Comment on lines +141 to +151
let defining_ty =
tcx.type_of(body_def_id).instantiate_identity().skip_normalization();
let defining_ty = if tcx.next_trait_solver_globally() {
// Closure types come from HIR typeck results, where they were already
// normalized during writeback. Wrapping them in an `EarlyBinder`
// conservatively makes aliases non-rigid, so restore their rigidness
// instead of normalizing them again during borrowck.
ty::set_aliases_to_rigid(tcx, defining_ty)
} else {
defining_ty
};

@adwinwhite adwinwhite Aug 29, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should do the same for the mir build one?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah, did that one too.

I initially left MIR build alone because the borrowck case looked like the real problem. That normalization used a fresh inference context, so any region constraints created there were thrown away. MIR build keeps its inference context around for the builder, so it was not quite the same bug.

Still, both places read the same closure type from HIR writeback. EarlyBinder::bind makes its aliases non-rigid because it has to be conservative, but this path stays in the same typing mode group with the same param env. Running the solver again does not buy us anything there.

I replaced the MIR build normalization with set_aliases_to_rigid too and removed the helper that was only there to normalize it. I think this is cleaner. MIR build and borrowck now agree that the HIR typeck result can be reused, and the coroutine regression still passes.

HIR writeback already normalizes closure types. Restore alias rigidity after identity instantiation instead of running the solver again while building MIR.
Document when changes to the typing mode or parameter environment make rigidness stale, and when compatible mode groups may reuse it.
@adwinwhite

Copy link
Copy Markdown
Contributor

Thanks!
@bors r+ rollup

@rust-bors

rust-bors Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

📌 Commit dad53fd has been approved by adwinwhite

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 31, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Aug 31, 2026
…_rigidity, r=adwinwhite

borrowck: Restore alias rigidity from HIR typeck

Follow-up to rust-lang#161012. This came out of the review thread here:
rust-lang#161012 (comment)

Borrowck was normalizing the closure type again in a fresh inference context. HIR writeback had already done that work. EarlyBinder only marked the aliases as non-rigid again because it has to be conservative. If the second normalization creates region constraints, they disappear with the temporary context.

I first thought normalizing again here was fine. After tracing the type back through writeback, I think it makes more sense to trust the result from HIR typeck. Borrowck now restores the rigid flag, and the IsRigid docs explain that this state can carry into borrowck and when it needs to be reset.

Tested with the coroutine regression and tidy.

cc @adwinwhite @lcnr
rust-bors Bot pushed a commit that referenced this pull request Aug 31, 2026
Rollup of 8 pull requests

Successful merges:

 - #161301 (libcore: expose volatile atomic operations)
 - #161379 (Use better generic type parameter names for `Extend` and `FromIterator`)
 - #161926 (borrowck: Restore alias rigidity from HIR typeck)
 - #161956 (Remove unused `perform_locally_with_next_solver`)
 - #162026 (Emit delayed bug instead of ICEing when `TypeOutlives` goal fails)
 - #162034 (Make the LLVM version mismatch ICE a fatal error)
 - #162037 (LLVM wrapper cleanups)
 - #162043 (_ an unused parameter)
@rust-bors
rust-bors Bot merged commit 141d9b7 into rust-lang:main Aug 31, 2026
13 checks passed
@rustbot rustbot added this to the 1.100.0 milestone Aug 31, 2026
rust-bors Bot pushed a commit that referenced this pull request Aug 31, 2026
Rollup merge of #161926 - Dnreikronos:borrowck/restore_alias_rigidity, r=adwinwhite

borrowck: Restore alias rigidity from HIR typeck

Follow-up to #161012. This came out of the review thread here:
#161012 (comment)

Borrowck was normalizing the closure type again in a fresh inference context. HIR writeback had already done that work. EarlyBinder only marked the aliases as non-rigid again because it has to be conservative. If the second normalization creates region constraints, they disappear with the temporary context.

I first thought normalizing again here was fine. After tracing the type back through writeback, I think it makes more sense to trust the result from HIR typeck. Borrowck now restores the rigid flag, and the IsRigid docs explain that this state can carry into borrowck and when it needs to be reset.

Tested with the coroutine regression and tidy.

cc @adwinwhite @lcnr
@rust-timer

Copy link
Copy Markdown
Collaborator

Note

This PR was benchmarked as part of triage of its containing rollup: triage URL.

Finished benchmarking commit (85335e5): 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 -0.7%, secondary -0.9%)

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)
-0.7% [-0.7%, -0.7%] 1
Improvements ✅
(secondary)
-0.9% [-1.1%, -0.8%] 2
All ❌✅ (primary) -0.7% [-0.7%, -0.7%] 1

Cycles

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

Binary size

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

Bootstrap: missing data
Artifact size: 307.41 MiB -> 400.54 MiB (30.30%)

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

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants