Skip to content

Conversation

Darksonn
Copy link
Contributor

@Darksonn Darksonn commented Aug 19, 2025

The safety requirements for PinCoerceUnsized are essentially that the type does not have a malicious Deref or DerefMut impl. However, the Pin type is fundamental, so the end-user can provide their own implementation of DerefMut for Pin<&SomeLocalType>, so it's possible for Pin to have a malicious DerefMut impl. This unsoundness is known as #85099.

Unfortunately, this means that the implementation of PinCoerceUnsized for Pin is currently unsound. To fix that, modify the impl so that it becomes impossible for downstream crates to provide their own implementation of DerefMut for Pin by abusing a hidden struct that is not fundamental.

This PR is a breaking change, but it fixes #85099. The PR supersedes #144896.

r? lcnr

@Darksonn Darksonn added T-lang Relevant to the language team A-pin Area: Pin T-types Relevant to the types team, which will review and decide on the PR/issue. labels Aug 19, 2025
@Darksonn Darksonn requested a review from lcnr August 19, 2025 14:53
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 19, 2025
@Darksonn
Copy link
Contributor Author

It doesn't immediately look like error messages have regressed, but the docs have:

image

I'm going to push another commit to improve the docs to this:

image

I think it's reasonable in this case since the impls really are equivalent except for the orphan rules treatment.

@lcnr
Copy link
Contributor

lcnr commented Aug 19, 2025

I want to make sure I properly understand #85099 before merging this. I do think it's a very nice solution and gj for coming up with it!

I personally dislike "lying in the impl", even if it doesn't matter in practice. Gonna throw that question to @rust-lang/libs-api.

Let's crater

@bors try

rust-bors bot added a commit that referenced this pull request Aug 19, 2025
Prevent downstream impl DerefMut for Pin
@rust-bors

This comment has been minimized.

@dtolnay dtolnay added the I-libs-api-nominated Nominated for discussion during a libs-api team meeting. label Aug 19, 2025
@traviscross traviscross added I-lang-nominated Nominated for discussion during a lang team meeting. I-lang-radar Items that are on lang's radar and will need eventual work or consideration. P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang labels Aug 19, 2025
@dtolnay
Copy link
Member

dtolnay commented Aug 19, 2025

We discussed this PR in today's standard library API meeting. Those present were on board with the approach, but it will be important to see a reasonably clean crater result and send PRs for any breakage, because not all downstream impls of DerefMut for Pin are necessarily unsound. The new implementation rules out correct as well as incorrect impls.

Once crater is finished, we would like to do a libs-api FCP to surface this to the rest of the team.

We noticed that the new pin::hidden::PinHelper type is now going to appear in diagnostics such as the pin-unsound-issue-85099-derefmut.stderr in this PR, but hopefully this mostly only happens when someone is doing funny business like writing their own DerefMut impl, and not for more typical use of Pin's methods and impls.

@dtolnay dtolnay removed the I-libs-api-nominated Nominated for discussion during a libs-api team meeting. label Aug 19, 2025
@Darksonn
Copy link
Contributor Author

Ok, let's see what crater says. But I don't think there are any valid use-cases for impl DerefMut for Pin<P> for pointer types that aren't DerefMut.

@rust-bors
Copy link

rust-bors bot commented Aug 19, 2025

☀️ Try build successful (CI)
Build commit: c659ee1 (c659ee110de67e82444e4b6c8407c1a9af9c2cf6, parent: 8c32e313cccf7df531e2d49ffb8227bb92304aee)

@lcnr
Copy link
Contributor

lcnr commented Aug 19, 2025

@craterbot check

@craterbot
Copy link
Collaborator

👌 Experiment pr-145608 created and queued.
🤖 Automatically detected try build c659ee1
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 19, 2025
@Darksonn
Copy link
Contributor Author

Darksonn commented Aug 19, 2025

Updating this with some additional tests for error messages. I'm not worried about PinHelper showing up in pin-unsound-issue-85099-derefmut.stderr, but that it also shows up in tests/ui/deref/pin-impl-deref.stderr is unfortunate.

(See individual commits for how the error messages change.)

@Darksonn
Copy link
Contributor Author

Darksonn commented Aug 19, 2025

A slightly different implementation seems to give somewhat better errors:

Darksonn@5e4d49a

But let's wait for crater before we think about that further.

@Darksonn Darksonn changed the title Prevent downstream impl DerefMut for Pin Prevent downstream impl DerefMut for Pin<LocalType> Aug 19, 2025
@traviscross traviscross added P-lang-drag-2 Lang team prioritization drag level 2.https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang. and removed P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang labels Aug 20, 2025
@craterbot
Copy link
Collaborator

🚧 Experiment pr-145608 is now running

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot
Copy link
Collaborator

🎉 Experiment pr-145608 is completed!
📊 6 regressed and 8 fixed (685389 total)
📰 Open the summary report.

⚠️ If you notice any spurious failure please add them to the denylist!
ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@rustbot
Copy link
Collaborator

rustbot commented Oct 5, 2025

This PR was rebased onto a different master 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.

@Darksonn Darksonn added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 6, 2025
@lcnr
Copy link
Contributor

lcnr commented Oct 7, 2025

@bors r+

@bors
Copy link
Collaborator

bors commented Oct 7, 2025

📌 Commit 76dcb39 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 Oct 7, 2025
Zalathar added a commit to Zalathar/rust that referenced this pull request Oct 7, 2025
Prevent downstream `impl DerefMut for Pin<LocalType>`

The safety requirements for [`PinCoerceUnsized`](https://doc.rust-lang.org/stable/std/pin/trait.PinCoerceUnsized.html) are essentially that the type does not have a malicious `Deref` or `DerefMut` impl. However, the `Pin` type is fundamental, so the end-user can provide their own implementation of `DerefMut` for `Pin<&SomeLocalType>`, so it's possible for `Pin` to have a malicious `DerefMut` impl. This unsoundness is known as rust-lang#85099.

Unfortunately, this means that the implementation of `PinCoerceUnsized` for `Pin` is currently unsound. To fix that, modify the impl so that it becomes impossible for downstream crates to provide their own implementation of `DerefMut` for `Pin` by abusing a hidden struct that is not fundamental.

This PR is a breaking change, but it fixes rust-lang#85099. The PR supersedes rust-lang#144896.

r? lcnr
bors added a commit that referenced this pull request Oct 7, 2025
Rollup of 7 pull requests

Successful merges:

 - #143900 ([rustdoc] Correctly handle `should_panic` doctest attribute and fix `--no-run` test flag on the 2024 edition)
 - #145608 (Prevent downstream `impl DerefMut for Pin<LocalType>`)
 - #146865 (kcfi: only reify trait methods when dyn-compatible)
 - #147390 (Use globals instead of metadata for std::autodiff)
 - #147398 (Fix; correct placement of type inference error for method calls)
 - #147431 (compiletest: Read the whole test file before parsing directives)
 - #147433 (Fix doc comment)

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit that referenced this pull request Oct 7, 2025
Prevent downstream `impl DerefMut for Pin<LocalType>`

The safety requirements for [`PinCoerceUnsized`](https://doc.rust-lang.org/stable/std/pin/trait.PinCoerceUnsized.html) are essentially that the type does not have a malicious `Deref` or `DerefMut` impl. However, the `Pin` type is fundamental, so the end-user can provide their own implementation of `DerefMut` for `Pin<&SomeLocalType>`, so it's possible for `Pin` to have a malicious `DerefMut` impl. This unsoundness is known as #85099.

Unfortunately, this means that the implementation of `PinCoerceUnsized` for `Pin` is currently unsound. To fix that, modify the impl so that it becomes impossible for downstream crates to provide their own implementation of `DerefMut` for `Pin` by abusing a hidden struct that is not fundamental.

This PR is a breaking change, but it fixes #85099. The PR supersedes #144896.

r? lcnr
@bors
Copy link
Collaborator

bors commented Oct 7, 2025

⌛ Testing commit 76dcb39 with merge 052a6fe...

Zalathar added a commit to Zalathar/rust that referenced this pull request Oct 7, 2025
Prevent downstream `impl DerefMut for Pin<LocalType>`

The safety requirements for [`PinCoerceUnsized`](https://doc.rust-lang.org/stable/std/pin/trait.PinCoerceUnsized.html) are essentially that the type does not have a malicious `Deref` or `DerefMut` impl. However, the `Pin` type is fundamental, so the end-user can provide their own implementation of `DerefMut` for `Pin<&SomeLocalType>`, so it's possible for `Pin` to have a malicious `DerefMut` impl. This unsoundness is known as rust-lang#85099.

Unfortunately, this means that the implementation of `PinCoerceUnsized` for `Pin` is currently unsound. To fix that, modify the impl so that it becomes impossible for downstream crates to provide their own implementation of `DerefMut` for `Pin` by abusing a hidden struct that is not fundamental.

This PR is a breaking change, but it fixes rust-lang#85099. The PR supersedes rust-lang#144896.

r? lcnr
@Zalathar
Copy link
Contributor

Zalathar commented Oct 7, 2025

Yielding to enclosing rollup.

@bors retry

bors added a commit that referenced this pull request Oct 7, 2025
Rollup of 8 pull requests

Successful merges:

 - #145608 (Prevent downstream `impl DerefMut for Pin<LocalType>`)
 - #146865 (kcfi: only reify trait methods when dyn-compatible)
 - #147205 (Add a new `wasm32-wasip3` target to Rust)
 - #147390 (Use globals instead of metadata for std::autodiff)
 - #147398 (Fix; correct placement of type inference error for method calls)
 - #147422 (collect-license-metadata: Print a diff of the expected output)
 - #147431 (compiletest: Read the whole test file before parsing directives)
 - #147433 (Fix doc comment)

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit that referenced this pull request Oct 7, 2025
Prevent downstream `impl DerefMut for Pin<LocalType>`

The safety requirements for [`PinCoerceUnsized`](https://doc.rust-lang.org/stable/std/pin/trait.PinCoerceUnsized.html) are essentially that the type does not have a malicious `Deref` or `DerefMut` impl. However, the `Pin` type is fundamental, so the end-user can provide their own implementation of `DerefMut` for `Pin<&SomeLocalType>`, so it's possible for `Pin` to have a malicious `DerefMut` impl. This unsoundness is known as #85099.

Unfortunately, this means that the implementation of `PinCoerceUnsized` for `Pin` is currently unsound. To fix that, modify the impl so that it becomes impossible for downstream crates to provide their own implementation of `DerefMut` for `Pin` by abusing a hidden struct that is not fundamental.

This PR is a breaking change, but it fixes #85099. The PR supersedes #144896.

r? lcnr
@bors
Copy link
Collaborator

bors commented Oct 7, 2025

⌛ Testing commit 76dcb39 with merge dfeac91...

@fmease
Copy link
Member

fmease commented Oct 7, 2025

Yielding to overarching rollup @bors retry

bors added a commit that referenced this pull request Oct 7, 2025
Rollup of 8 pull requests

Successful merges:

 - #145608 (Prevent downstream `impl DerefMut for Pin<LocalType>`)
 - #146865 (kcfi: only reify trait methods when dyn-compatible)
 - #147205 (Add a new `wasm32-wasip3` target to Rust)
 - #147390 (Use globals instead of metadata for std::autodiff)
 - #147398 (Fix; correct placement of type inference error for method calls)
 - #147422 (collect-license-metadata: Print a diff of the expected output)
 - #147431 (compiletest: Read the whole test file before parsing directives)
 - #147433 (Fix doc comment)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors
Copy link
Collaborator

bors commented Oct 7, 2025

⌛ Testing commit 76dcb39 with merge fed46ff...

@bors
Copy link
Collaborator

bors commented Oct 7, 2025

☀️ Test successful - checks-actions
Approved by: lcnr
Pushing fed46ff to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Oct 7, 2025
@bors bors merged commit fed46ff into rust-lang:master Oct 7, 2025
11 checks passed
@rustbot rustbot added this to the 1.92.0 milestone Oct 7, 2025
Copy link
Contributor

github-actions bot commented Oct 7, 2025

What is this? This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.

Comparing 4a54b26 (parent) -> fed46ff (this PR)

Test differences

Show 20 test diffs

20 doctest diffs were found. These are ignored, as they are noisy.

Test dashboard

Run

cargo run --manifest-path src/ci/citool/Cargo.toml -- \
    test-dashboard fed46ffd5059e11669df1bd9406b02914c3fb73f --output-dir test-dashboard

And then open test-dashboard/index.html in your browser to see an overview of all executed tests.

Job duration changes

  1. dist-aarch64-linux: 8607.1s -> 6204.2s (-27.9%)
  2. x86_64-gnu-llvm-20-1: 3216.0s -> 3666.2s (14.0%)
  3. pr-check-1: 1598.6s -> 1375.2s (-14.0%)
  4. x86_64-gnu-llvm-20: 2752.6s -> 2466.6s (-10.4%)
  5. dist-x86_64-apple: 7843.4s -> 7078.3s (-9.8%)
  6. x86_64-mingw-2: 7563.8s -> 8203.4s (8.5%)
  7. test-various: 4460.8s -> 4822.2s (8.1%)
  8. dist-x86_64-musl: 8524.6s -> 7836.7s (-8.1%)
  9. i686-msvc-2: 7783.4s -> 8387.2s (7.8%)
  10. i686-gnu-1: 7945.8s -> 7333.4s (-7.7%)
How to interpret the job duration changes?

Job durations can vary a lot, based on the actual runner instance
that executed the job, system noise, invalidated caches, etc. The table above is provided
mostly for t-infra members, for simpler debugging of potential CI slow-downs.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (fed46ff): comparison URL.

Overall result: ❌✅ regressions and improvements - please read the text below

Our benchmarks found a performance regression caused by this PR.
This might be an actual regression, but it can also be just noise.

Next Steps:

  • If the regression was expected or you think it can be justified,
    please write a comment with sufficient written justification, and add
    @rustbot label: +perf-regression-triaged to it, to mark the regression as triaged.
  • If you think that you know of a way to resolve the regression, try to create
    a new PR with a fix for the regression.
  • If you do not understand the regression or you think that it is just noise,
    you can ask the @rust-lang/wg-compiler-performance working group for help (members of this group
    were already notified of this PR).

@rustbot label: +perf-regression
cc @rust-lang/wg-compiler-performance

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
0.3% [0.3%, 0.3%] 2
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.0% [-0.0%, -0.0%] 1
All ❌✅ (primary) 0.3% [0.3%, 0.3%] 2

Max RSS (memory usage)

Results (primary 1.8%, secondary 1.6%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
1.8% [1.8%, 1.8%] 1
Regressions ❌
(secondary)
3.6% [2.1%, 5.1%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.2% [-2.2%, -2.2%] 1
All ❌✅ (primary) 1.8% [1.8%, 1.8%] 1

Cycles

This benchmark run did not return any relevant results for this metric.

Binary size

Results (primary 0.1%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
0.1% [0.0%, 0.4%] 5
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.1% [0.0%, 0.4%] 5

Bootstrap: 473.216s -> 474.165s (0.20%)
Artifact size: 388.39 MiB -> 388.38 MiB (-0.00%)

@rustbot rustbot added the perf-regression Performance regression. label Oct 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-pin Area: Pin disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. I-lang-radar Items that are on lang's radar and will need eventual work or consideration. merged-by-bors This PR was explicitly merged by bors. perf-regression Performance regression. relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-lang Relevant to the language team T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. to-announce Announce this issue on triage meeting
Projects
None yet
Development

Successfully merging this pull request may close these issues.

A Pin unsoundness involving an impl DerefMut for Pin<&dyn LocalTrait>