Skip to content

Require #[pin_v2] for explicit pin-projection patterns#157680

Merged
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
Dnreikronos:pin_ergonomics_explicit_projection_pin_v2_gate
Jun 12, 2026
Merged

Require #[pin_v2] for explicit pin-projection patterns#157680
rust-bors[bot] merged 1 commit into
rust-lang:mainfrom
Dnreikronos:pin_ergonomics_explicit_projection_pin_v2_gate

Conversation

@Dnreikronos

@Dnreikronos Dnreikronos commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Fixes #157634

The #[pin_v2] projection check only ran for the implicit projection (the match-ergonomics one, gated on default_binding_modes). The explicit &pin mut / ref pin patterns went straight through check_pat_ref into the tuple-struct/struct paths with no check at all, so you could pin-project through a type that never opted into structural pinning and pull a Pin<&mut Field> out of it. that breaks the Pin guarantee: the repro in the issue pins a !Unpin field of an Unpin wrapper and then moves it.

there were a few ways to fix this (i laid them out here), but only approach 1, gating the explicit path on #[pin_v2] too, actually closes it since the hole isn't packed-specific. theemathas landed on the same one in #157615, so that's what i went with.

instead of duplicating the check i moved it to the destructuring site (check_pin_projection, called from check_pat_struct and check_pat_tuple_struct), so one check now covers both the implicit and explicit projections. one subtlety that bit me: max_pinnedness is only set for &pin mut, not for the implicit &pin const, so the gate also looks at the pinned binding mode to catch the shared case.

tests cover tuple-struct / struct / enum / shared projections plus the issue's exact repro. there's also a foreign-type one so the error still fires (just without the "type defined here" note + suggestion) when the projected-through type has no local span. the diagnostic already carries those as Option<Span>, same good practice mejrs raised on #157542, so figured it makes sense to lock it in with a test.

lmk if you'd rather keep the check separate per-path instead of centralized.

cc @theemathas @mejrs

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

rustbot commented Jun 9, 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 18 candidates

@rustbot

This comment has been minimized.

@mejrs

mejrs commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

r? compiler

@rustbot rustbot assigned folkertdev and unassigned mejrs Jun 9, 2026
@Dnreikronos Dnreikronos force-pushed the pin_ergonomics_explicit_projection_pin_v2_gate branch from bd378ed to 53dfa1d Compare June 9, 2026 19:12
@rust-log-analyzer

This comment has been minimized.

@Dnreikronos Dnreikronos force-pushed the pin_ergonomics_explicit_projection_pin_v2_gate branch from 53dfa1d to 90e44c7 Compare June 9, 2026 19:22
@rust-log-analyzer

This comment has been minimized.

@folkertdev

Copy link
Copy Markdown
Contributor

@rustbot author

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

rustbot commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Reminder, once the PR becomes ready for a review, use @rustbot ready.

The structural-pinning check only ran for the implicit projection (match
ergonomics, gated on `default_binding_modes`). Explicit `&pin mut` / `ref
pin` patterns went through `check_pat_ref` and the tuple-struct/struct
paths without any check, so they could pin-project through a type that
never opted into structural pinning and hand out a `Pin<&mut Field>` for
it, breaking the `Pin` guarantee.

Move the check to the destructuring site (`check_pin_projection`, called
from `check_pat_struct` and `check_pat_tuple_struct`) so one check covers
both the implicit and explicit projections.
@Dnreikronos Dnreikronos force-pushed the pin_ergonomics_explicit_projection_pin_v2_gate branch from 90e44c7 to 50b0362 Compare June 10, 2026 19:58
@rustbot

rustbot commented Jun 10, 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.

@Dnreikronos

Dnreikronos commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

i rebased onto latest master and force-pushed. the earlier red CI was just a transient crates.io download failure in the tools job, nothing to do with this change. fmt + tidy pass locally.

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jun 10, 2026
@folkertdev

Copy link
Copy Markdown
Contributor

This looks fine, I don't think this has any unwanted consequences. This is not really my area of expertise and I'm not 100% sure it closes all soundness gaps. But, this feature is still unstable, so there is time to figure that out, and this looks like a step in the right direction.

@bors r+

@rust-bors

rust-bors Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 50b0362 has been approved by folkertdev

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 12, 2026
rust-bors Bot pushed a commit that referenced this pull request Jun 12, 2026
…uwer

Rollup of 23 pull requests

Successful merges:

 - #144220 (Add powerpc64-unknown-linux-gnuelfv2 target)
 - #153238 (debuginfo: slices are DW_TAG_array_type's)
 - #157112 (Update aarch64-unknown-freebsd target description)
 - #157322 (test pre-stabilization items on CI)
 - #157348 (Don't track cwd for `-Zremap-cwd-prefix` in incremental compilation)
 - #157490 (Add field-wise CoerceShared reborrow tests)
 - #157655 (Make Share::share final and improve docs)
 - #157672 (Region inference: Simplify initialisation of region values)
 - #157680 (Require `#[pin_v2]` for explicit pin-projection patterns)
 - #157688 (Create experimental test job `aarch64-apple-macos-26` for evaluating `macos-26` runner images)
 - #157796 (rustdoc: Some more lazy formatting)
 - #157818 (miri subtree update)
 - #157069 (Test that you can't implement Unpin for a compiler-generated future using TAIT)
 - #157079 (Don't recover `&raw EXPR` as a missing comma)
 - #157202 (add #[rustc_no_writable] to slice::get_unchecked_mut)
 - #157622 (Disable retagging for variadic arguments in const-eval)
 - #157684 (-Zassumptions-on-binders: insert empty assumptions when entering binders in the solver)
 - #157695 (Extend capabilities of `TypeFoldable_Generic`)
 - #157766 (interpret: avoid computing layout of sized raw pointee)
 - #157785 (fuchsia: Support AddressSanitizer on riscv64gc-unknown-fuchsia)
 - #157795 (revert 157013)
 - #157798 (Prevent approving PRs that wait for Crater or formal decisions)
 - #157803 (Rename `errors.rs` file to `diagnostics.rs` (7/N))

Failed merges:

 - #157752 (Rename `errors.rs` file to `diagnostics.rs` (6/N))
@rust-bors rust-bors Bot merged commit 927b226 into rust-lang:main Jun 12, 2026
12 checks passed
@rustbot rustbot added this to the 1.98.0 milestone Jun 12, 2026
rust-timer added a commit that referenced this pull request Jun 12, 2026
Rollup merge of #157680 - Dnreikronos:pin_ergonomics_explicit_projection_pin_v2_gate, r=folkertdev

Require `#[pin_v2]` for explicit pin-projection patterns

Fixes #157634

The `#[pin_v2]` projection check only ran for the implicit projection (the match-ergonomics one, gated on `default_binding_modes`). The explicit `&pin mut` / `ref pin` patterns went straight through `check_pat_ref` into the tuple-struct/struct paths with no check at all, so you could pin-project through a type that never opted into structural pinning and pull a `Pin<&mut Field>` out of it. that breaks the `Pin` guarantee: the repro in the issue pins a `!Unpin` field of an `Unpin` wrapper and then moves it.

there were a few ways to fix this (i laid them out [here](#157615 (comment))), but only approach 1, gating the explicit path on `#[pin_v2]` too, actually closes it since the hole isn't packed-specific. theemathas landed on the same one in #157615, so that's what i went with.

instead of duplicating the check i moved it to the destructuring site (`check_pin_projection`, called from `check_pat_struct` and `check_pat_tuple_struct`), so one check now covers both the implicit and explicit projections. one subtlety that bit me: `max_pinnedness` is only set for `&pin mut`, not for the implicit `&pin const`, so the gate also looks at the pinned binding mode to catch the shared case.

tests cover tuple-struct / struct / enum / shared projections plus the issue's exact repro. there's also a foreign-type one so the error still fires (just without the "type defined here" note + suggestion) when the projected-through type has no local span. the diagnostic already carries those as `Option<Span>`, same good practice mejrs raised on #157542, so figured it makes sense to lock it in with a test.

lmk if you'd rather keep the check separate per-path instead of centralized.

cc @theemathas @mejrs
pull Bot pushed a commit to xtqqczze/rust-lang-miri that referenced this pull request Jun 13, 2026
…uwer

Rollup of 23 pull requests

Successful merges:

 - rust-lang/rust#144220 (Add powerpc64-unknown-linux-gnuelfv2 target)
 - rust-lang/rust#153238 (debuginfo: slices are DW_TAG_array_type's)
 - rust-lang/rust#157112 (Update aarch64-unknown-freebsd target description)
 - rust-lang/rust#157322 (test pre-stabilization items on CI)
 - rust-lang/rust#157348 (Don't track cwd for `-Zremap-cwd-prefix` in incremental compilation)
 - rust-lang/rust#157490 (Add field-wise CoerceShared reborrow tests)
 - rust-lang/rust#157655 (Make Share::share final and improve docs)
 - rust-lang/rust#157672 (Region inference: Simplify initialisation of region values)
 - rust-lang/rust#157680 (Require `#[pin_v2]` for explicit pin-projection patterns)
 - rust-lang/rust#157688 (Create experimental test job `aarch64-apple-macos-26` for evaluating `macos-26` runner images)
 - rust-lang/rust#157796 (rustdoc: Some more lazy formatting)
 - rust-lang/rust#157818 (miri subtree update)
 - rust-lang/rust#157069 (Test that you can't implement Unpin for a compiler-generated future using TAIT)
 - rust-lang/rust#157079 (Don't recover `&raw EXPR` as a missing comma)
 - rust-lang/rust#157202 (add #[rustc_no_writable] to slice::get_unchecked_mut)
 - rust-lang/rust#157622 (Disable retagging for variadic arguments in const-eval)
 - rust-lang/rust#157684 (-Zassumptions-on-binders: insert empty assumptions when entering binders in the solver)
 - rust-lang/rust#157695 (Extend capabilities of `TypeFoldable_Generic`)
 - rust-lang/rust#157766 (interpret: avoid computing layout of sized raw pointee)
 - rust-lang/rust#157785 (fuchsia: Support AddressSanitizer on riscv64gc-unknown-fuchsia)
 - rust-lang/rust#157795 (revert 157013)
 - rust-lang/rust#157798 (Prevent approving PRs that wait for Crater or formal decisions)
 - rust-lang/rust#157803 (Rename `errors.rs` file to `diagnostics.rs` (7/N))

Failed merges:

 - rust-lang/rust#157752 (Rename `errors.rs` file to `diagnostics.rs` (6/N))
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.

ref pin mut pattern unsoundly allows pin-projecting arbitrary types

5 participants