Skip to content

Implement borrowck for &pin mut|const $place#153693

Open
frank-king wants to merge 8 commits intorust-lang:mainfrom
frank-king:feature/pin-borrowck
Open

Implement borrowck for &pin mut|const $place#153693
frank-king wants to merge 8 commits intorust-lang:mainfrom
frank-king:feature/pin-borrowck

Conversation

@frank-king
Copy link
Copy Markdown
Contributor

@frank-king frank-king commented Mar 11, 2026

View all comments

Part of Pin Ergonomics.

This forbids places to be moved or mutably borrowed ever since they are pinned until they are reassigned (even after the pinned borrows themselves expire).

#![feature(pin_ergnonmics)]
#![allow(incomplete_features)]

#[pin_v2]
struct Foo;

fn foo(mut x: Foo) {
    {
        let _x = &pin mut x; // x is pinned
    } // now the pinned reference expires
    let _x = &mut x; //~ ERROR cannot borrow `x` as mutable because it is pinned
    let _x = x; //~ ERROR cannot move out of `x` because it is pinned
    
    x = Foo; // x is reassigned
    let _x = &mut x; // ok because x is reassigned and not pinned yet
}

Tasks:

  • Add Pins dataflow analysis
  • Improve the diagnostics of pinning errors
  • Test pin pattern matching
  • Forbid &pin borrows for ADTs without #[pin_v2] (for soundness concerns)

Unresolved questions

When should #[pin_v2] be checked?

Currently, it is checked at rustc_hir_typck::FnCtxt::check_expr_addr_of, but field projections are not correctly handled.

Should we check this after the expr adjustments are available or even at THIR?

Related discussions:

How to deal with Unpin types?

Should &pin borrowed places of Unpin types be prevented from being moved, or just don't treat Unpin types specially and emit move-after-pin as usual?

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 11, 2026
@rust-log-analyzer

This comment has been minimized.

@frank-king frank-king force-pushed the feature/pin-borrowck branch from f6b714b to 46c66aa Compare April 17, 2026 03:07
@rust-log-analyzer

This comment has been minimized.

@P8L1

This comment has been minimized.

@P8L1

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@P8L1

This comment has been minimized.

@P8L1

This comment was marked as resolved.

@frank-king

This comment was marked as outdated.

@rust-log-analyzer

This comment has been minimized.

@frank-king
Copy link
Copy Markdown
Contributor Author

Let me self-review the whole PR carefully before marking it ready for review.

@rust-log-analyzer

This comment has been minimized.

Comment thread compiler/rustc_middle/src/mir/syntax.rs Outdated
@rust-bors

This comment has been minimized.

@frank-king frank-king force-pushed the feature/pin-borrowck branch from a72c987 to 9fe2f02 Compare May 4, 2026 02:48
@P8L1

This comment has been minimized.

@rust-bors

This comment has been minimized.

@P8L1
Copy link
Copy Markdown
Contributor

P8L1 commented May 8, 2026

@frank-king How is your review going?

}

fn direct_pin_mut_not_unpin() {
let _ = &pin mut NotUnpin { _pin: PhantomPinned };
Copy link
Copy Markdown
Contributor Author

@frank-king frank-king May 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably wrong. Generally, let x = &pin mut y; should be equivalent to let ref mut x = y;. Given that (Playground)

struct NoPinV2 {
    x: i32,
}

struct NoPinV2NoUnpin {
    x: i32,
    __: std::marker::PhantomPinned,
}


struct NoPinV2Generic<T> {
    y: T,
}

struct NoPinV2GenericUnpin<T> {
    y: T,
    __: std::marker::PhantomPinned,
}

impl<T> Unpin for NoPinV2GenericUnpin<T> {}

fn foo<T>(
    mut x: NoPinV2,
    mut y: NoPinV2NoUnpin,
    mut z: NoPinV2Generic<T>,
    mut w: NoPinV2GenericUnpin<T>,
) {
    let ref pin mut x = x; // ok
    let ref pin mut y = y; // ok
    let ref pin mut z = z; // ok
    let ref pin mut w = w; // ok
    // However, only the first is accepted
    let x = &pin mut x; // ok
    let y = &pin mut y; // ERROR
    let z = &pin mut z; // ERROR
    let w = &pin mut w; // ERROR
}

Regarding pin patterns, the #[pin_v2] checks actually happen when field projections take place, rather than when pinned borrows (via the ref pin patterns) do.

I'm afraid that we should check #[pin_v2] at field projections (including nested field projections like &pin mut foo.a[2].0) too. I guess this can be processed when walking at the expr adjuestments (but highly unsure)

View changes since the review

@frank-king frank-king force-pushed the feature/pin-borrowck branch from 1e8d2cd to 5764e08 Compare May 9, 2026 08:03
@frank-king frank-king marked this pull request as ready for review May 9, 2026 08:10
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 9, 2026

Some changes occurred in match lowering

cc @Nadrieril

Some changes occurred to constck

cc @fee1-dead

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

This PR changes MIR

cc @oli-obk, @RalfJung, @JakobDegen, @vakaras

This PR changes rustc_public

cc @oli-obk, @celinval, @ouz-a, @makai410

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 9, 2026
@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label May 9, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 9, 2026

r? @wesleywiser

rustbot has assigned @wesleywiser.
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

@frank-king
Copy link
Copy Markdown
Contributor Author

I'm going to mark this PR ready since there isn't a simple and clear solution to the unresolved questions yet. Help wanted from reviewers.

CC @traviscross @oli-obk

@frank-king frank-king force-pushed the feature/pin-borrowck branch from 5764e08 to 03d1f29 Compare May 9, 2026 08:25
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 9, 2026

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.

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

Labels

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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants