Skip to content

Conversation

@Delta17920
Copy link
Contributor

@Delta17920 Delta17920 commented Dec 9, 2025

This fixes an internal compiler error that occurred when normalizing associated types during closure capture analysis.

The Fix: Modified rustc_middle/src/ty/normalize_erasing_regions.rs to gracefully handle projection normalization failures instead of panicking when analyzing closure captures.

Regression Test: Added tests/ui/associated-types/normalization-ice-issue-149746.rs, a reproduction case involving complex associated type projections (<() as Owner>::Ty) that previously crashed the compiler. Verified it now emits a standard type error (E0277).

Fixes #149746

@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 Dec 9, 2025
@rustbot
Copy link
Collaborator

rustbot commented Dec 9, 2025

r? @fee1-dead

rustbot has assigned @fee1-dead.
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

@rustbot

This comment has been minimized.

@Delta17920
Copy link
Contributor Author

Delta17920 commented Dec 9, 2025

r? compiler

@rustbot
Copy link
Collaborator

rustbot commented Dec 9, 2025

fmease is not on the review rotation at the moment.
They may take a while to respond.

@rustbot rustbot assigned compiler-errors and unassigned fee1-dead and fmease Dec 9, 2025
@rustbot
Copy link
Collaborator

rustbot commented Dec 9, 2025

compiler-errors is not on the review rotation at the moment.
They may take a while to respond.

@rustbot rustbot assigned lcnr and unassigned compiler-errors Dec 9, 2025
@rust-log-analyzer

This comment has been minimized.

let input = self.typing_env.as_query_input(arg);

// 2. Use unwrap_or(arg) to return the original arg if it fails
self.tcx.try_normalize_generic_arg_after_erasing_regions(input).unwrap_or(arg)
Copy link
Contributor

Choose a reason for hiding this comment

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

we're intentionally using a bug! here as we're in normalize_generic_arg_after_erasing_regions.

The issue happens in the caller:

  • we either have to change the caller to use try_normalize... to avoid this ICE if the error is unavoidable
  • or prevent this error entirely by not calling normalize_... for types which aren#t well-formed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the feedback @lcnr ! I have reverted the global change in rustc_middle and moved the fix to compiler/rustc_hir_typeck/src/upvar.rs as requested. specifically, I updated the needs_drop closure within has_significant_drop_outside_of_captures to use try_normalize_erasing_regions; if normalization fails, it now conservatively returns false (assuming no significant drop) instead of panicking.

@rustbot

This comment has been minimized.

@Delta17920
Copy link
Contributor Author

@lcnr anything else that needs to be changed?

@@ -0,0 +1,16 @@
// edition: 2015..2021
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// edition: 2015..2021
//@ edition: 2015..2021

The MCVE I've posted in #149746 (comment) which you're using here as a test, deliberately has an @ there: It's a compiletest directive.

Copy link
Contributor

Choose a reason for hiding this comment

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

this has not been resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@Delta17920 Delta17920 requested review from fmease and lcnr December 11, 2025 00:38
@Delta17920
Copy link
Contributor Author

@lcnr anything else that needs to be changed?

@Delta17920
Copy link
Contributor Author

r? @fmease

@rustbot rustbot assigned fmease and unassigned lcnr Dec 18, 2025
@rustbot
Copy link
Collaborator

rustbot commented Dec 18, 2025

fmease is not on the review rotation at the moment.
They may take a while to respond.

@lcnr
Copy link
Contributor

lcnr commented Dec 18, 2025

I am sorry that I did not quickly re-review this PR. For non-critical work, it is expected that reviewers sometimes take 1-2 weeks.

Pinging people after a few days is fine if the issue is blocking other important work or if it fixes a critical issue. Please be more patient going forward.

r? lcnr

@Delta17920
Copy link
Contributor Author

I am sorry that I did not quickly re-review this PR. For non-critical work, it is expected that reviewers sometimes take 1-2 weeks.

Pinging people after a few days is fine if the issue is blocking other important work or if it fixes a critical issue. Please be more patient going forward.

r? lcnr

sorry sorry, i will take care of this from the next time

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.

There's something a lot bigger here, which is why I didn't take the time to look at this PR until now.

At its core, a lot of code in the compiler assumes that if a type is well-formed, so are its fields. This is simply not true, neither currently nor in general:

This is separate to the issue in this PR, where the struct itself is not well-formed and we don't emit an error for it. These we could handle by changing normalize_erasing_regions to emit a span_delayed_bug, returning an ty::Error instead. Doing that is kind of whatever however if the issue also just exists for otherwise well-formed programs.

Outside of codegen, using normalize_erasing_regions can pretty much always go wrong. Quickly looking through to source, the following additional calls to normalize_erasing_regions may also result in reachable ICE

  • let normalized = tcx.normalize_erasing_regions(typing_env, ty);
    (we recur into struct fields)
  • let metadata = tcx.normalize_erasing_regions(
    (should ICE for reference to alias as struct field)
  • pretty much all (indirect) uses of normalize_erasing_regions in CTFE and MIR opts can result in ICE as long as they happen in generic bodies
  • using normalize_erasing_regions in borrowck for the not explicitly mentioned fields of Foo { ..Default::default() } expressions should ICE
  • using normalize_erasing_regions in resolve_instance_raw ICEs mir opts and CTFE using it

I would kind of like to figure out a more general strategy here instead of fixing these issues as they crop up. Anyways, fine with this PR for now, but want to start a T-types discussion about this and think about a general solution here.

View changes since this review

// If normalization fails, we assume it doesn't have a significant drop (false)
// to avoid crashing, allowing the compiler to emit the underlying type error later.
self.tcx
.try_normalize_erasing_regions(typing_env, ty)
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 instead replace the normalize_erasing_regions call in has_significant_drop with its try_ variant. r=me after.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done! I've moved the fix to has_significant_drop itself, replacing normalize_erasing_regions with try_normalize_erasing_regions and returning false when normalization fails.

@rustbot

This comment has been minimized.

// FIX: Use try_normalize to avoid crashing. If it fails, return false.
tcx.try_normalize_erasing_regions(typing_env, query_ty)
.map(|erased| tcx.has_significant_drop_raw(typing_env.as_query_input(erased)))
.unwrap_or(false)
Copy link
Contributor

Choose a reason for hiding this comment

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

why false? in case the query_ty has infer we're currently conservatively returning true and we should the the same here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, good point! I completely missed that 😭🤦‍♂️we're already returning true conservatively for the has_infer() case. You're right - we should be consistent here. Updated to return true instead to match that behavior.

@rustbot
Copy link
Collaborator

rustbot commented Dec 23, 2025

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.

@lcnr
Copy link
Contributor

lcnr commented Dec 23, 2025

@bors r+ rollup

@bors
Copy link
Collaborator

bors commented Dec 23, 2025

📌 Commit ac448c9 has been approved by lcnr

It is now in the queue for this repository.

@bors bors 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 Dec 23, 2025
bors added a commit that referenced this pull request Dec 24, 2025
Rollup of 6 pull requests

Successful merges:

 - #149800 (Fix ICE in normalization during closure capture analysis (#149746))
 - #150182 (Don't export upstream monomorphizations from compiler-builtins)
 - #150216 (Tidying up tests/ui/issues 15 tests [6/N])
 - #150308 (Update bors configuration)
 - #150314 (rustc-dev-guide subtree update)
 - #150319 (use new term in description of --target)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit f6c6e84 into rust-lang:main Dec 24, 2025
11 checks passed
@rustbot rustbot added this to the 1.94.0 milestone Dec 24, 2025
rust-timer added a commit that referenced this pull request Dec 24, 2025
Rollup merge of #149800 - Delta17920:fix-ice-149746, r=lcnr

Fix ICE in normalization during closure capture analysis (#149746)

This fixes an internal compiler error that occurred when normalizing associated types during closure capture analysis.

The Fix: Modified rustc_middle/src/ty/normalize_erasing_regions.rs to gracefully handle projection normalization failures instead of panicking when analyzing closure captures.

Regression Test: Added tests/ui/associated-types/normalization-ice-issue-149746.rs, a reproduction case involving complex associated type projections (<() as Owner>::Ty<T>) that previously crashed the compiler. Verified it now emits a standard type error (E0277).

Fixes #149746
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Dec 27, 2025
Rollup of 6 pull requests

Successful merges:

 - rust-lang/rust#149800 (Fix ICE in normalization during closure capture analysis (rust-lang/rust#149746))
 - rust-lang/rust#150182 (Don't export upstream monomorphizations from compiler-builtins)
 - rust-lang/rust#150216 (Tidying up tests/ui/issues 15 tests [6/N])
 - rust-lang/rust#150308 (Update bors configuration)
 - rust-lang/rust#150314 (rustc-dev-guide subtree update)
 - rust-lang/rust#150319 (use new term in description of --target)

r? `@ghost`
`@rustbot` modify labels: rollup
github-actions bot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Dec 29, 2025
Rollup of 6 pull requests

Successful merges:

 - rust-lang/rust#149800 (Fix ICE in normalization during closure capture analysis (rust-lang/rust#149746))
 - rust-lang/rust#150182 (Don't export upstream monomorphizations from compiler-builtins)
 - rust-lang/rust#150216 (Tidying up tests/ui/issues 15 tests [6/N])
 - rust-lang/rust#150308 (Update bors configuration)
 - rust-lang/rust#150314 (rustc-dev-guide subtree update)
 - rust-lang/rust#150319 (use new term in description of --target)

r? `@ghost`
`@rustbot` modify labels: rollup
Kobzol pushed a commit to Kobzol/rustc_codegen_cranelift that referenced this pull request Dec 29, 2025
Rollup of 6 pull requests

Successful merges:

 - rust-lang/rust#149800 (Fix ICE in normalization during closure capture analysis (rust-lang/rust#149746))
 - rust-lang/rust#150182 (Don't export upstream monomorphizations from compiler-builtins)
 - rust-lang/rust#150216 (Tidying up tests/ui/issues 15 tests [6/N])
 - rust-lang/rust#150308 (Update bors configuration)
 - rust-lang/rust#150314 (rustc-dev-guide subtree update)
 - rust-lang/rust#150319 (use new term in description of --target)

r? `@ghost`
`@rustbot` modify labels: rollup
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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ICE when lint rust_2021_incompatible_closure_captures encounters type that can't be normalized

8 participants