Skip to content

traits: Allow escaping self types in ExistentialTraitRef::with_self_ty#157280

Open
Dnreikronos wants to merge 3 commits into
rust-lang:mainfrom
Dnreikronos:existential_trait_ref_escaping_bound_vars_assert
Open

traits: Allow escaping self types in ExistentialTraitRef::with_self_ty#157280
Dnreikronos wants to merge 3 commits into
rust-lang:mainfrom
Dnreikronos:existential_trait_ref_escaping_bound_vars_assert

Conversation

@Dnreikronos

@Dnreikronos Dnreikronos commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #157122

WF-checking recurses through higher-ranked binders without instantiating them, so a dyn Trait nested inside a for<'a> binder reaches the ty::Dynamic arm of WfPredicates::visit_ty while still carrying escaping bound vars. Building the principal trait ref there via ExistentialTraitRef::with_self_ty hands that escaping self type to a debug_assert!(!self_ty.has_escaping_bound_vars()), which ICEs once the assertion is enabled. The assert was accidentally disabled in 2018 refactor #53816, and the // FIXME(#157122) left in its place asks whether to remove it or fix the fallout.

An escaping bound var is expected for trait objects, and we already catch trait refs with escaping bound vars at the places that actually use them — so creating one here is fine. Rather than work around the assert in WF, this removes the assert and its stale FIXME from with_self_ty.

Two regression tests pin the behavior:

  • wf-dyn-in-hrtb-bound-issue-157122.rs reproduces the original ICE (dyn nested in an HRTB bound).
  • wf-dyn-in-hrtb-bound-const-mismatch.rs checks that the ConstArgHasType obligation this arm reads off still fires, so an ill-typed const argument on such a dyn keeps erroring instead of compiling clean.

@rustbot

rustbot commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

changes to the core type system

cc @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. labels Jun 2, 2026
@rustbot

rustbot commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

r? @mejrs

rustbot has assigned @mejrs.
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 73 candidates
  • Random selection from 17 candidates

WF-checking walks through higher-ranked binders without instantiating
them, so a `dyn Trait` nested inside a `for<'a>` bound reaches the
`ty::Dynamic` arm of `WfPredicates::visit_ty` while still carrying
escaping bound vars. Feeding that type into
`ExistentialTraitRef::with_self_ty` violated its no-escaping-self
precondition and tripped the assertion that guards it.

The trait ref built there is only used to read off `ConstArgHasType`
clauses, which constrain the trait's own const arguments and never
mention the `Self` type. Substitute a fresh placeholder self type when
the real one escapes: the assertion holds and the const-argument check
is still performed. Re-enable the `with_self_ty` debug assertion now
that its precondition is upheld.
One test covers the original ICE (a `dyn Trait` nested in a `for<'a>`
bound, distilled from itertools). The other locks in that a const
argument on such a nested `dyn` is still type-checked, so the
placeholder-self-type fix cannot silently regress into dropping the
`ConstArgHasType` check.
@Dnreikronos Dnreikronos force-pushed the existential_trait_ref_escaping_bound_vars_assert branch from 87f6783 to 0676d4a Compare June 2, 2026 02:49
@rustbot

rustbot commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

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.

@mejrs

mejrs commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

I'm not confident reviewing this.

r? @fmease perhaps?

@rustbot rustbot assigned fmease and unassigned mejrs Jun 2, 2026
@Dnreikronos

Copy link
Copy Markdown
Contributor Author

I'm not confident reviewing this.

r? @fmease perhaps?

Hi, @mejrs!
I'm not 100% confident that this implementation that I did it's the best approach as possible to solve the problem. So I'm totally open/available to discuss about it

@mejrs

mejrs commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Oh it's not about what and how you implemented this, I'm very unfamiliar with this part of the compiler so I'm ill-suited to review PRs touching it.

@oli-obk oli-obk added T-types Relevant to the types team, which will review and decide on the PR/issue. and removed T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 2, 2026
Comment thread compiler/rustc_type_ir/src/predicate.rs Outdated

@lcnr lcnr left a comment

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.

sorry for the late review, RustWeek was a thing

View changes since this review

WF-checking can reach ExistentialTraitRef::with_self_ty with a dyn
principal that still carries escaping bound vars, e.g. a dyn nested in
a for<'a> bound, which tripped the debug assertion forbidding escaping
self types and ICEd when compiling itertools.

Building such a trait ref is fine: escaping bound vars are caught where
it is actually used. Remove the assertion rather than working around it,
which lets the WF visitor pass the type through unchanged and drops the
placeholder-self-type detour.
@rust-log-analyzer

This comment was marked as outdated.

@fmease fmease assigned lcnr and unassigned fmease Jun 9, 2026
@lcnr

lcnr commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

@bors delegate+

r=me after updating the PR name

@rust-bors

rust-bors Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

✌️ @Dnreikronos, you can now approve this pull request!

If @lcnr told you to "r=me" after making some further change, then please make that change and post @bors r=lcnr.

View changes since this delegation.

@Dnreikronos Dnreikronos changed the title traits: Use a placeholder self type for escaping dyn principals in WF traits: Allow escaping self types in ExistentialTraitRef::with_self_ty Jun 10, 2026
@Dnreikronos

Dnreikronos commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

just reenamed the PR.
the old name still described the placeholder self type approach we dropped.

@bors r=lcnr

@rust-bors

rust-bors Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 3669c24 has been approved by lcnr

It is now in the queue for this repository.

🌲 The tree is currently closed for pull requests below priority 5. This pull request will be tested once the tree is reopened.

@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 Jun 10, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jun 10, 2026
…escaping_bound_vars_assert, r=lcnr

traits: Allow escaping self types in ExistentialTraitRef::with_self_ty

Fixes rust-lang#157122

WF-checking recurses through higher-ranked binders without instantiating them, so a `dyn Trait` nested inside a `for<'a>` binder reaches the `ty::Dynamic` arm of `WfPredicates::visit_ty` while still carrying escaping bound vars. Building the principal trait ref there via `ExistentialTraitRef::with_self_ty` hands that escaping self type to a `debug_assert!(!self_ty.has_escaping_bound_vars())`, which ICEs once the assertion is enabled. The assert was accidentally disabled in 2018 refactor rust-lang#53816, and the `// FIXME(rust-lang#157122)` left in its place asks whether to remove it or fix the fallout.

An escaping bound var is expected for trait objects, and we already catch trait refs with escaping bound vars at the places that actually use them — so creating one here is fine. Rather than work around the assert in WF, this removes the assert and its stale FIXME from `with_self_ty`.

Two regression tests pin the behavior:
- `wf-dyn-in-hrtb-bound-issue-157122.rs` reproduces the original ICE (`dyn` nested in an HRTB bound).
- `wf-dyn-in-hrtb-bound-const-mismatch.rs` checks that the `ConstArgHasType` obligation this arm reads off still fires, so an ill-typed const argument on such a `dyn` keeps erroring instead of compiling clean.
rust-bors Bot pushed a commit that referenced this pull request Jun 10, 2026
…uwer

Rollup of 14 pull requests

Successful merges:

 - #157280 (traits: Allow escaping self types in ExistentialTraitRef::with_self_ty)
 - #157282 (Fix post-monomorphization error note race in the parallel frontend)
 - #157352 (Make the retained dep graph deterministic under the parallel frontend)
 - #157601 (Emit error for unused target expression in glob and list delegations)
 - #157626 (Autogenerate unstable compiler flag stubs for unstable-book)
 - #157647 (Start using comptime for reflection intrinsics and their wrapper functions)
 - #157013 (Ensure inferred let pattern types are well-formed)
 - #157288 (platform support: add SNaN erratum to MIPS targets)
 - #157355 (Add `or_try_*` variants for `HashMap` and `BTreeMap` Entry APIs)
 - #157577 (Fix parser error recovery treating 'dyn' as a strict keyword in Rust …)
 - #157670 (Rename `errors.rs` file to `diagnostics.rs` (4/N))
 - #157691 (Move symbol hiding code to a new file)
 - #157700 (Rename `errors.rs` file to `diagnostics.rs` (5/N))
 - #157703 (Fix doc link to Instant sub in saturating caveat)

Failed merges:

 - #157699 (Arg splat experiment - hir FnDecl impl)
rust-bors Bot pushed a commit that referenced this pull request Jun 10, 2026
…uwer

Rollup of 14 pull requests

Successful merges:

 - #157280 (traits: Allow escaping self types in ExistentialTraitRef::with_self_ty)
 - #157282 (Fix post-monomorphization error note race in the parallel frontend)
 - #157352 (Make the retained dep graph deterministic under the parallel frontend)
 - #157601 (Emit error for unused target expression in glob and list delegations)
 - #157626 (Autogenerate unstable compiler flag stubs for unstable-book)
 - #157647 (Start using comptime for reflection intrinsics and their wrapper functions)
 - #157013 (Ensure inferred let pattern types are well-formed)
 - #157288 (platform support: add SNaN erratum to MIPS targets)
 - #157355 (Add `or_try_*` variants for `HashMap` and `BTreeMap` Entry APIs)
 - #157577 (Fix parser error recovery treating 'dyn' as a strict keyword in Rust …)
 - #157670 (Rename `errors.rs` file to `diagnostics.rs` (4/N))
 - #157691 (Move symbol hiding code to a new file)
 - #157700 (Rename `errors.rs` file to `diagnostics.rs` (5/N))
 - #157703 (Fix doc link to Instant sub in saturating caveat)

Failed merges:

 - #157699 (Arg splat experiment - hir FnDecl impl)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jun 10, 2026
…escaping_bound_vars_assert, r=lcnr

traits: Allow escaping self types in ExistentialTraitRef::with_self_ty

Fixes rust-lang#157122

WF-checking recurses through higher-ranked binders without instantiating them, so a `dyn Trait` nested inside a `for<'a>` binder reaches the `ty::Dynamic` arm of `WfPredicates::visit_ty` while still carrying escaping bound vars. Building the principal trait ref there via `ExistentialTraitRef::with_self_ty` hands that escaping self type to a `debug_assert!(!self_ty.has_escaping_bound_vars())`, which ICEs once the assertion is enabled. The assert was accidentally disabled in 2018 refactor rust-lang#53816, and the `// FIXME(rust-lang#157122)` left in its place asks whether to remove it or fix the fallout.

An escaping bound var is expected for trait objects, and we already catch trait refs with escaping bound vars at the places that actually use them — so creating one here is fine. Rather than work around the assert in WF, this removes the assert and its stale FIXME from `with_self_ty`.

Two regression tests pin the behavior:
- `wf-dyn-in-hrtb-bound-issue-157122.rs` reproduces the original ICE (`dyn` nested in an HRTB bound).
- `wf-dyn-in-hrtb-bound-const-mismatch.rs` checks that the `ConstArgHasType` obligation this arm reads off still fires, so an ill-typed const argument on such a `dyn` keeps erroring instead of compiling clean.
jhpratt added a commit to jhpratt/rust that referenced this pull request Jun 10, 2026
…escaping_bound_vars_assert, r=lcnr

traits: Allow escaping self types in ExistentialTraitRef::with_self_ty

Fixes rust-lang#157122

WF-checking recurses through higher-ranked binders without instantiating them, so a `dyn Trait` nested inside a `for<'a>` binder reaches the `ty::Dynamic` arm of `WfPredicates::visit_ty` while still carrying escaping bound vars. Building the principal trait ref there via `ExistentialTraitRef::with_self_ty` hands that escaping self type to a `debug_assert!(!self_ty.has_escaping_bound_vars())`, which ICEs once the assertion is enabled. The assert was accidentally disabled in 2018 refactor rust-lang#53816, and the `// FIXME(rust-lang#157122)` left in its place asks whether to remove it or fix the fallout.

An escaping bound var is expected for trait objects, and we already catch trait refs with escaping bound vars at the places that actually use them — so creating one here is fine. Rather than work around the assert in WF, this removes the assert and its stale FIXME from `with_self_ty`.

Two regression tests pin the behavior:
- `wf-dyn-in-hrtb-bound-issue-157122.rs` reproduces the original ICE (`dyn` nested in an HRTB bound).
- `wf-dyn-in-hrtb-bound-const-mismatch.rs` checks that the `ConstArgHasType` obligation this arm reads off still fires, so an ill-typed const argument on such a `dyn` keeps erroring instead of compiling clean.
rust-bors Bot pushed a commit that referenced this pull request Jun 10, 2026
Rollup of 23 pull requests

Successful merges:

 - #157280 (traits: Allow escaping self types in ExistentialTraitRef::with_self_ty)
 - #157282 (Fix post-monomorphization error note race in the parallel frontend)
 - #157352 (Make the retained dep graph deterministic under the parallel frontend)
 - #157601 (Emit error for unused target expression in glob and list delegations)
 - #157611 (Update `browser-ui-test` version to `0.24.0`)
 - #157620 (Add a strategy FnMut to inject behavior into the flush cycle)
 - #157645 (Windows TLS - Only register the `atexit` hook when `cleanup` can be unloaded)
 - #157647 (Start using comptime for reflection intrinsics and their wrapper functions)
 - #157719 (resolve: Partially revert "Remove a special case for dummy imports")
 - #156497 (fix-155516: Don't suggest wrong unwrap expect)
 - #156583 (Support defaults for static EIIs)
 - #157013 (Ensure inferred let pattern types are well-formed)
 - #157230 (borrowck: avoid ICE describing fields on generic params)
 - #157288 (platform support: add SNaN erratum to MIPS targets)
 - #157350 (compiletest: ignore SVG `y` offset in by-lines comparison)
 - #157355 (Add `or_try_*` variants for `HashMap` and `BTreeMap` Entry APIs)
 - #157384 (Add `#[rustc_dump_generics]` attribute)
 - #157577 (Fix parser error recovery treating 'dyn' as a strict keyword in Rust 2015 when used in `dyn + dyn`)
 - #157670 (Rename `errors.rs` file to `diagnostics.rs` (4/N))
 - #157691 (Move symbol hiding code to a new file)
 - #157697 (Add more tests that exercise the well-formedness checking of lazy type aliases)
 - #157700 (Rename `errors.rs` file to `diagnostics.rs` (5/N))
 - #157703 (Fix doc link to Instant sub in saturating caveat)

Failed merges:

 - #157699 (Arg splat experiment - hir FnDecl impl)
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-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.

ExistentialTraitRef::with_self_ty gets called with escaping bound vars since a few months ago

7 participants