Skip to content

Comments

Normalize capture place tys to prevent ICE#152165

Open
JohnTitor wants to merge 9 commits intorust-lang:mainfrom
JohnTitor:issue-151579
Open

Normalize capture place tys to prevent ICE#152165
JohnTitor wants to merge 9 commits intorust-lang:mainfrom
JohnTitor:issue-151579

Conversation

@JohnTitor
Copy link
Member

@JohnTitor JohnTitor commented Feb 5, 2026

Fixes #151579
Fixes #120811
r? @lcnr

@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. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Feb 5, 2026
@rust-log-analyzer

This comment has been minimized.

@lcnr lcnr closed this Feb 8, 2026
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 8, 2026
@lcnr lcnr reopened this Feb 8, 2026
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 8, 2026
HirPlaceBase::Upvar(upvar_id) => {
ty::TypingEnv::post_analysis(tcx, upvar_id.closure_expr_id)
}
_ => ty::TypingEnv::fully_monomorphized(),
Copy link
Contributor

Choose a reason for hiding this comment

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

This is hacky and subtly wrong in two ways.

  • even if the type is not from an upvar, we still need the right param_env to normalize
  • we use this during MIR build, so it should probably use TypingMode::Borrowck or whatever

see https://rustc-dev-guide.rust-lang.org/typing-parameter-envs.html

Copy link
Member Author

@JohnTitor JohnTitor Feb 11, 2026

Choose a reason for hiding this comment

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

Ah I see, I've switched to use try_structurally_resolve_ty as mentioned in the issue: 176bf7d (this PR)
This way, we can avoid deep normalization here, right?

Copy link
Contributor

@lcnr lcnr left a comment

Choose a reason for hiding this comment

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

ah, I didn't see we always get these types from the typeck_results. We should deeply normalize them in writeback and then assume that they are normalized afterwards

View changes since this review

@rustbot

This comment has been minimized.

@JohnTitor JohnTitor requested a review from lcnr February 11, 2026 11:04
}

fn try_structurally_resolve_place_ty(&self, span: Span, place: &mut Place<'tcx>) {
place.base_ty = self.try_structurally_resolve_type(span, place.base_ty);
Copy link
Contributor

Choose a reason for hiding this comment

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

use deeply_normalize here. We deeply normalize types in the writeback results, so I think we should do the same here

Copy link
Member Author

Choose a reason for hiding this comment

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

Just replacing didn't work so I had to do something like this instead: 750cd53

Is this what you meant for?

Copy link
Contributor

Choose a reason for hiding this comment

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

can you use at.deeply_normalize with both solvers?

Copy link
Member Author

Choose a reason for hiding this comment

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

I've tried but had to construct TraitEngine there which seems an unusual way (I haven't seen such a way in other places).
Instead, I guess using ObligationCtxt might be better here, other places do this way and it shoudl call at.deeply_normalize internally: a7ea420
How about this?

@JohnTitor JohnTitor requested a review from lcnr February 12, 2026 22:32
UpvarMigrationInfo::CapturingPrecise {
source_expr: capture.info.path_expr_id,
var_name: capture.to_string(self.tcx),
var_name: self.place_to_string_for_migration(capture),
Copy link
Contributor

Choose a reason for hiding this comment

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

can we move this normalization even further up so that catpure.place is already deeply normalized and we don't have to do so here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Moved: c22ffdb
I wonder if we should reduce scope by if next_solver as we now normalize stuff more generally, i.e. other than emitting lint rust_2021_incompatible_closure_captures and it would bring unnecessary cost for most cases 🤔

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

}
}

fn try_structurally_resolve_place_ty(&self, span: Span, place: &mut Place<'tcx>) {
Copy link
Contributor

Choose a reason for hiding this comment

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

deeply_normalize should normalize arbitrary TypeFoldable things. Is Place type foldable?

Also, change this function name :>

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, you're right, it's TypeFoldable. Addressed: 7def3bc
And I noticed we have another win, it would fix #120811 (N.B. crashes/120911 is a dup of 120811, so I removed it).

@rustbot

This comment has been minimized.

@lcnr
Copy link
Contributor

lcnr commented Feb 15, 2026

I messed up by reviewing your commit directly yesterday, see c22ffdb#r177216090

@rustbot

This comment has been minimized.

@JohnTitor
Copy link
Member Author

@lcnr Sorry, I missed it 🙏
I think I addressed your comments: ecdea2c
I need to call normalize_capture_place before capture_information.push to prevent ICEs.


assert_eq!(self.tcx.hir_body_owner_def_id(body.id()), closure_def_id);

// Used by `ExprUseVisitor` when collecting closure capture information.
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment feels is odd. It states information which is clearly visible 3 lines down. You could state sth like "We need to create a separate FnCtxt for nested bodies"

Creating FnCtxts for nested bodies is also something we normally do, so I don't know if that is that useful either. I think it's fine to just not have a comment here at all

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, removed in ebefb53.

}
fn normalize_capture_place(&self, span: Span, place: &mut Place<'tcx>) {
*place = self.resolve_vars_if_possible(place.clone());

Copy link
Contributor

Choose a reason for hiding this comment

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

why &mut Place instead of taking by value and returning it again?

Copy link
Member Author

Choose a reason for hiding this comment

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

Fair enough, addressed in dddbf96

restrict_capture_precision(place_with_id.place.clone(), dummy_capture_kind);
let span = self.fcx.tcx.hir_span(diag_expr_id);
let mut place = place_with_id.place.clone();
self.fcx.normalize_capture_place(span, &mut place);
Copy link
Contributor

Choose a reason for hiding this comment

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

could also eagerly normalize closure_fake_reads 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

though, I guess this is fine for now as making sure the ExprUseVisitor always handles things correctly seems like a bigger change

Copy link
Member Author

Choose a reason for hiding this comment

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

Alright, should I add FIXME or something else?

@rustbot

This comment was marked as off-topic.

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-rustc-dev-guide Area: rustc-dev-guide A-rustdoc-json Area: Rustdoc JSON backend T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-clippy Relevant to the Clippy team. T-rust-analyzer Relevant to the rust-analyzer team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output. labels Feb 17, 2026
@rustbot
Copy link
Collaborator

rustbot commented Feb 17, 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.

@JohnTitor
Copy link
Member Author

(rebase mistake, sorry for pinging)

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

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-rustc-dev-guide Area: rustc-dev-guide A-rustdoc-json Area: Rustdoc JSON backend S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rust-analyzer Relevant to the rust-analyzer team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ICE with -Znext-solver when accessing hir place ICE: Broken MIR: NoSolution

4 participants