Skip to content

Make pin!() more foolproof.#158061

Merged
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
theemathas:pin-foolproof
Jul 20, 2026
Merged

Make pin!() more foolproof.#158061
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
theemathas:pin-foolproof

Conversation

@theemathas

@theemathas theemathas commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

View all comments

Previously, the soundness argument for the pin!() macro relied on very complicated conditions on what coercions are possible. As a result, it was not obvious whether the macro was sound or not, and the macro was potentially fragile to changes in how coercions work.

Therefore, we change the pin!() macro so that it relies on less subtle properties of coercions. In particular:

  • The soundness argument now only relies on enumerating the possible types that a coercion could produce, as opposed to relying on details about how coercion expectations are propagated.
  • The soundness argument now only requires reasoning about possible coercions between a single pair of types defined in the standard library, as opposed to reasoning about two pairs of types, with some involved types being defined by the user.

Fixes #153438. This PR supersedes the proposed FCP on that issue.

cc @dianne

r? types

@theemathas theemathas added T-libs Relevant to the library team, which will review and decide on the PR/issue. A-pin Area: Pin T-types Relevant to the types team, which will review and decide on the PR/issue. labels Jun 18, 2026
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 18, 2026
Comment thread tests/ui/pin/dont-deref-coerce-pinned-value.stderr

@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.

sgtm

i consider this to properly fix #153438. I don't worry about us adding random coercions inside of user defined types causing problems here, as that should also cause problems for abstractions outside of stdlib

View changes since this review

Comment thread library/core/src/pin.rs Outdated
Comment thread tests/ui/pin/dont-deref-coerce-pinned-value.stderr
Comment thread library/core/src/pin.rs Outdated
Comment thread tests/ui/pin/dont-deref-coerce-pinned-value.stderr
@theemathas theemathas 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 Jul 1, 2026
@theemathas theemathas 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 Jul 1, 2026
@theemathas

Copy link
Copy Markdown
Contributor Author

This should hopefully be ready to merge now. @lcnr

Comment thread compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs Outdated

@mejrs mejrs 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.

I've messed around with this some more and discovered that you can do this (no need for the custom error reporting code)

pub struct PinMacroHelper<T> {
    pub value: T,
}

impl<T> PinMacroHelper<T> {
    pub const unsafe fn pin_new_unchecked<'a>(&'a mut self) -> Pin<&'a mut T> {
        // SAFETY: Ensured by the caller.
        unsafe { Pin::new_unchecked(&mut self.value) }
    }
}

and then you get the error:

error[E0308]: mismatched types
  --> $DIR/dont-deref-coerce-pinned-value.rs:9:14
   |
LL | fn wrong_pin<T>(data: &mut T, callback: impl FnOnce(Pin<&mut T>)) {
   |              - expected this type parameter
LL |     callback(pin!(data));
   |              ^^^^^^^^^^ expected `Pin<&mut T>`, found `Pin<&mut &mut T>`
   |
   = note: expected struct `Pin<&mut _>`
              found struct `Pin<&mut &mut _>`

error: aborting due to 1 previous error

Anyway while I was messing around I noticed that the test passed while the error message changed. Can you add an explicit HELP/NOTE annotation so it doesn't regress?

View changes since this review

@theemathas

Copy link
Copy Markdown
Contributor Author

@mejrs I avoided using the method call syntax because I didn't want to deal with autoref/autoderef. Do you think it's worth slightly complicating the soundness reasoning for the sake of diagnostics?

Comment thread library/core/src/pin.rs
@mejrs

mejrs commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

@mejrs I avoided using the method call syntax because I didn't want to deal with autoref/autoderef. Do you think it's worth slightly complicating the soundness reasoning for the sake of diagnostics?

It would be nice to not have to put these hacks in the error reporting code... 🤔

Previously, the soundness argument for the `pin!()` macro relied on
very complicated conditions on what coercions are possible.
As a result, it was not obvious whether the macro was sound or not,
and the macro was potentially fragile to changes in how coercions work.

Therefore, we change the `pin!()` macro so that it relies on less subtle
properties of coercions. In particular:

* The soundness argument now only relies on enumerating the possible
  types that a coercion could produce, as opposed to relying on details
  about how coercion expectations are propagated.
* The soundness argument now only requires reasoning about possible
  coercions between a single pair of types defined in the
  standard library, as opposed to reasoning about two pairs of types,
  with some involved types being defined by the user.

Fixes <rust-lang#153438>
Comment thread compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs Outdated
@lcnr

lcnr commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Do you think it's worth slightly complicating the soundness reasoning for the sake of diagnostics?

is your concern that resolving method calls might have unintended behavior (e.g. preferring a trait method in scope or sth)

I do prefer not using method call syntax here I think. The diagnostics hack is somewhat ugly, but fine imo

@theemathas theemathas 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 Jul 13, 2026
@theemathas theemathas 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 Jul 13, 2026
@theemathas

This comment was marked as resolved.

@lcnr

lcnr commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

@bors r+ rollup

@rust-bors

rust-bors Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

📌 Commit f0c86f6 has been approved by lcnr

It is now in the queue for this repository.

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

Rollup of 18 pull requests

Successful merges:

 - #159600 (`rust-analyzer` subtree update)
 - #158046 (proc_macro: preserve file module spans for inner attrs)
 - #159000 (Small cleanups to the incr comp session code)
 - #159189 (Account for type alias projections in E0308 "expected/found" shortening logic)
 - #159449 (Enable single Location to issue multiple borrows)
 - #159544 (Suggest valid command-line crate names)
 - #159587 (Improve `AttrItem::span`)
 - #159594 (feat(rustc_hir_typeck): suggest `impl Fn` return for capturing closures)
 - #159597 (std: use `arc4random_buf` from libc)
 - #159599 (Resolver: Record at least 1 ambiguous trait if main decl is not a trait.)
 - #158061 (Make `pin!()` more foolproof.)
 - #159460 (Do not mark unnormalized const aliases as rigid when normalizing param env)
 - #159529 (Add regression test for nested replacement ranges in `collect_tokens`)
 - #159571 (Remove unused bundled library lookup for the local crate)
 - #159585 (Minor `TokenStream` improvements)
 - #159586 (Separate `InterpCx` usage by `ConstAnalysis` phases)
 - #159602 (Remove `ItemLike`)
 - #159603 (Clarify `push_stream`/`push_tree`)

Failed merges:

 - #159590 (Remove some dead code)
@rust-bors
rust-bors Bot merged commit 509ed74 into rust-lang:main Jul 20, 2026
15 of 16 checks passed
rust-timer added a commit that referenced this pull request Jul 20, 2026
Rollup merge of #158061 - theemathas:pin-foolproof, r=lcnr

Make `pin!()` more foolproof.

Previously, the soundness argument for the `pin!()` macro relied on very complicated conditions on what coercions are possible. As a result, it was not obvious whether the macro was sound or not, and the macro was potentially fragile to changes in how coercions work.

Therefore, we change the `pin!()` macro so that it relies on less subtle properties of coercions. In particular:

* The soundness argument now only relies on enumerating the possible types that a coercion could produce, as opposed to relying on details about how coercion expectations are propagated.
* The soundness argument now only requires reasoning about possible coercions between a single pair of types defined in the standard library, as opposed to reasoning about two pairs of types, with some involved types being defined by the user.

Fixes <#153438>. This PR supersedes the proposed FCP on that issue.

cc @dianne

r? types
@theemathas
theemathas deleted the pin-foolproof branch July 20, 2026 23:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-pin Area: Pin S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs Relevant to the library team, which will review and decide on the PR/issue. 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.

pin!() is unsound due to coercions

6 participants