Skip to content

Remove HR subtyping and replace them with coercions - #160461

Draft
spastorino wants to merge 14 commits into
rust-lang:mainfrom
spastorino:hr-subtyping-coercions
Draft

Remove HR subtyping and replace them with coercions#160461
spastorino wants to merge 14 commits into
rust-lang:mainfrom
spastorino:hr-subtyping-coercions

Conversation

@spastorino

@spastorino spastorino commented Aug 3, 2026

Copy link
Copy Markdown
Member

We currently treat, to give an example for<'a> fn(&'a ()) as a subtype of fn(&'static ()) and that relation propagates through type constructors via variance. These are genuinely different types, with different TypeId, trait impls, associated types. Letting subtyping silently interconvert them (e.g. Foo<for<'a> fn(&'a ())> -> Foo<fn(&'static ())> is a long-standing soundness hole (#97156, #134407, #85863, #148821, #25860).

This PR, requires HR binders to relate by equality in the type-relating code, and re adds the legitimate HR -> non-HR conversions as a coercion that only applies at coercion sites (so it can no longer leak through type constructors).

What's in the PR:

  • Binder equality: TypeRelating/SolverRelating/NllTypeRelating::binders now run both directions while keeping ambient variance, using an hr placeholder flag so only the bound variable placeholders are equated and free regions keep their variance.
  • Fn-pointer/item/closure coercion: a new Adjust::Subtype -> ExprKind::Subtype -> CastKind::Subtype lowering, produced by the three coercion.rs entry points and handled in borrowck (which now instantiates the source binder, proves WellFormed, and sub_types). Covers safe -> unsafe and closure cases too.
  • Trait objects: the old-solver (Dynamic, Dynamic) Unsize confirmation now relates principal + projections, fixing dyn for<'a> Trait<'a> -> dyn Trait<'static> at coercion sites.

There's intended breakage (HR conversions through type constructors) is now rejected; direct conversions at coercion sites still compile. Full tests/ui suite green. A wrapped raw-pointer cast (cast_away_higher_ranked_wrap) is left as a FIXME, entangled with #141402.

This is best read commit by commit, after each commit all tests passes, so for instance in one of the first commits, we remove subtyping and tests show what regresses there marking tests as known-bug. In subsequent commits, we see how after each commit tests start to work again.
At the end, over the entire changes, looking at the test changes together is a good idea to see the final state of things.

r? lcnr

cc @rust-lang/types

This is still WIP as:

  • I didn't fill the PR description properly yet
  • It's rebased on an old main branch
  • It probably won't pass tests other than tests/ui
  • It needs to run crater
  • It needs to run perf
  • I need to review all the changes better, in particular in tests again to be 100% sure that the changes are correct.

@rustbot

rustbot commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred in rustc_ty_utils::consts.rs

cc @BoxyUwU

changes to the core type system

cc @lcnr

This PR modifies tests/ui/issues/. If this PR is adding new tests to tests/ui/issues/,
please refrain from doing so, and instead add it to more descriptive subdirectories.

Some changes occurred in match checking

cc @Nadrieril

@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 3, 2026
@rustbot

rustbot commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

⚠️ Warning ⚠️

@spastorino
spastorino marked this pull request as draft August 3, 2026 19:20
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 3, 2026
@spastorino

Copy link
Copy Markdown
Member Author

@bors try @rust-timer queue

@rust-timer

Copy link
Copy Markdown
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rust-bors

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Aug 3, 2026
@spastorino
spastorino force-pushed the hr-subtyping-coercions branch from 0dd23cc to 46133a8 Compare August 3, 2026 23:27
@spastorino

Copy link
Copy Markdown
Member Author

@bors try @rust-timer queue

@rust-timer

Copy link
Copy Markdown
Collaborator

This pull request is already queued and waiting for a try build to finish.

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Aug 3, 2026
Remove HR subtyping and replace them with coercions
@spastorino

Copy link
Copy Markdown
Member Author

@craterbot check

@craterbot

Copy link
Copy Markdown
Collaborator

🚨 Error: missing start toolchain

🆘 If you have any trouble with Crater please ask in t-infra on Zulip
ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@spastorino

Copy link
Copy Markdown
Member Author

🚨 Error: missing start toolchain

Ok, need to wait for the try build to finish.

@rust-log-analyzer

This comment has been minimized.

@rust-bors

rust-bors Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

💔 Test for 2c2a830 failed: CI. Failed job:

@rust-log-analyzer

This comment has been minimized.

@spastorino
spastorino force-pushed the hr-subtyping-coercions branch from 46133a8 to 2895a40 Compare August 4, 2026 00:12
@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job x86_64-gnu-gcc failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
   Compiling litemap v0.8.1
error: `K` does not live long enough
  --> /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/litemap-0.8.1/src/store/slice_impl.rs:61:25
   |
61 |         self.iter().map(map_f)
   |                         ^^^^^

error: `V` does not live long enough
  --> /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/litemap-0.8.1/src/store/slice_impl.rs:61:25
   |
61 |         self.iter().map(map_f)
   |                         ^^^^^

error: `K` does not live long enough
   --> /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/litemap-0.8.1/src/store/vec_impl.rs:269:36
    |
---

error: `K` does not live long enough
   --> /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/litemap-0.8.1/src/store/vec_impl.rs:278:44
    |
278 |         self.as_mut_slice().iter_mut().map(map_f_mut)
    |                                            ^^^^^^^^^

error: `V` does not live long enough
   --> /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/litemap-0.8.1/src/store/vec_impl.rs:278:44
    |
278 |         self.as_mut_slice().iter_mut().map(map_f_mut)
    |                                            ^^^^^^^^^

[RUSTC-TIMING] litemap test:false 0.227
error: could not compile `litemap` (lib) due to 6 previous errors
warning: build failed, waiting for other jobs to finish...

Important

For more information how to resolve CI failures of this job, visit this link.

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

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. S-waiting-on-perf Status: Waiting on a perf run to be completed. 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.

6 participants