Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make &mut !Unpin not dereferenceable, and Box<!Unpin> not noalias #106180

Merged
merged 3 commits into from
Feb 7, 2023

Conversation

RalfJung
Copy link
Member

@RalfJung RalfJung commented Dec 27, 2022

See rust-lang/unsafe-code-guidelines#381 and this LLVM discussion. The exact semantics of how noalias and dereferenceable interact are unclear, and @comex found a case of LLVM actually exploiting that ambiguity for optimizations. I think for now we should treat LLVM dereferenceable as implying a "fake read" to happen immediately at the top of the function (standing in for the spurious reads that LLVM might introduce), and that fake read is subject to all the usual noalias restrictions. This means we cannot put dereferenceable on &mut !Unpin references as those references can alias with other references that are being read and written inside the function (e.g. for self-referential generators), meaning the fake read introduces aliasing conflicts with those other accesses.

For & this is already not a problem due to #98017 which removed the dereferenceable attribute for other reasons.

Regular &mut Unpin references are unaffected, so I hope the impact of this is going to be tiny.

The first commit does some refactoring of the PointerKind enum since I found the old code very confusing each time I had to touch it. It doesn't change behavior.

Fixes rust-lang/miri#2714

EDIT: Turns out our Box<!Unpin> treatment was incorrect, too, so the PR also fixes that now (in codegen and Miri): we do not put noalias on these boxes any more.

@rustbot
Copy link
Collaborator

rustbot commented Dec 27, 2022

r? @jackh726

(rustbot has picked a reviewer for you, use r? to override)

@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 Dec 27, 2022
@rustbot
Copy link
Collaborator

rustbot commented Dec 27, 2022

The Miri subtree was changed

cc @rust-lang/miri

@RalfJung
Copy link
Member Author

Cc @nikic due to LLVM attribute involvement

@RalfJung
Copy link
Member Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Dec 27, 2022
@bors
Copy link
Contributor

bors commented Dec 27, 2022

⌛ Trying commit 3dbce6b7db10c346bec633288dcd314e23b80a41 with merge d0517ed036a21986873e247b24636d0f55aadebb...

@rust-log-analyzer

This comment has been minimized.

@nikic
Copy link
Contributor

nikic commented Dec 27, 2022

No concerns from my side.

@bors
Copy link
Contributor

bors commented Dec 27, 2022

☀️ Try build successful - checks-actions
Build commit: d0517ed036a21986873e247b24636d0f55aadebb (d0517ed036a21986873e247b24636d0f55aadebb)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (d0517ed036a21986873e247b24636d0f55aadebb): comparison URL.

Overall result: no relevant changes - no action needed

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf.

@bors rollup=never
@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

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

Max RSS (memory usage)

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

Cycles

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

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Dec 27, 2022
let raw = x as *mut _;
drop(unsafe { Box::from_raw(raw) });
});
}
Copy link
Member Author

Choose a reason for hiding this comment

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

FWIW we could keep this as UB (by still protecting &mut !Unpin references). But I don't see a good reason for doing that... and it would be asymmetric with &!Freeze references.

@RalfJung
Copy link
Member Author

@rust-lang/lang not sure if this needs a full FCP, but I nominated this anyway to bring it to your attention -- I think putting dereferenceable on references where adding a read would cause aliasing violations in code we consider well-defined is a risk we don't currently want to take. It's not clear how and why such code would not be UB.

Put differently I think everywhere that we emit dereferenceable, we want Miri to do a "fake read" when the function starts to verify that indeed this is dereferenceable -- but for &mut !Unpin references we cannot do that, Miri would report UB on safe code (see rust-lang/unsafe-code-guidelines#381). Therefore we should not put dereferenceable on &mut !Unpin references, which is what this PR implements.

@RalfJung RalfJung added T-lang Relevant to the language team, which will review and decide on the PR/issue. I-lang-nominated Nominated for discussion during a lang team meeting. labels Dec 28, 2022
@RalfJung
Copy link
Member Author

RalfJung commented Jan 2, 2023

I have also added to this PR a commit which fixes a problem pointed out by @Darksonn: we are currently adding noalias to all Boxes, but we can only do that for Box<Unpin>, bot the same reason as with mutable references.

@RalfJung RalfJung changed the title make &mut !Unpin not dereferenceable make &mut !Unpin not dereferenceable, and Box<!Unpin> not noalias Jan 2, 2023
@RalfJung
Copy link
Member Author

RalfJung commented Jan 2, 2023

Cc @rust-lang/wg-mir-opt (AFAIK currently no MIR optimizations do anything aliasing-related but still)

@bors
Copy link
Contributor

bors commented Jan 3, 2023

☔ The latest upstream changes (presumably #106371) made this pull request unmergeable. Please resolve the merge conflicts.

@rustbot rustbot removed the I-lang-nominated Nominated for discussion during a lang team meeting. label Jan 31, 2023
@RalfJung
Copy link
Member Author

RalfJung commented Feb 6, 2023

All right, looks like I now need someone from t-compiler to review. @jackh726 you are currently assigned. Does that work or should I re-assign?

The code that consumes PointerKind (`adjust_for_rust_scalar` in rustc_ty_utils)
ended up using PointerKind variants to talk about Rust reference types (& and
&mut) anyway, making the old code structure quite confusing: one always had to
keep in mind which PointerKind corresponds to which type. So this changes
PointerKind to directly reflect the type.

This does not change behavior.
}
}
};
let pointee_info = match *this.ty.kind() {
Copy link
Member Author

Choose a reason for hiding this comment

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

For some reason rustfmt decided to completely change how this match is formatted. Some recent other PR made the inverse change, and resolving those conflicts was quite painful (git is not great at handling whitespace differences during rebasing). @rust-lang/rustfmt any idea why this back-and-forth is happening? rustfmt seems to sometimes perefer

let var =
    match expr {
        pat => ...
    };

over

let val = match expr {
    pat => ...
};

even though I would think the latter is always preferable?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is where the inverse change recently happened.

@jackh726
Copy link
Member

jackh726 commented Feb 6, 2023

I can review, but I'm not sure if I'm the best person for it (so will need to allocate some time to actually grok what's going on)

frozen: optimize && ty.is_freeze(tcx, cx.param_env()),
},
hir::Mutability::Mut => PointerKind::MutableRef {
unpin: optimize && ty.is_unpin(tcx, cx.param_env()),
Copy link
Contributor

Choose a reason for hiding this comment

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

This changed the behaviour of mutable ref in no-opt builds from SharedMutable to UniqueBorrowedPinned, as opposed to what is claimed in the commit message.

Copy link
Member Author

Choose a reason for hiding this comment

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

That doesn't actually change the emitted flags though, so the commit message is still correct. Or did I miss a case?

Copy link
Contributor

Choose a reason for hiding this comment

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

It changes the emitted flags if you only look at that commit, but of course the latter commits unify the behaviour of these two so the flags ended up being the same. I pointed this out because I'm reviewing per commit.

Copy link
Member Author

Choose a reason for hiding this comment

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

It changes the emitted flags if you only look at that commit,

I don't think it does... in no-opt builds we don't emit any flags either way.

Copy link
Contributor

Choose a reason for hiding this comment

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

If only this commit is applied then we will start emitting dereferenceable for mutable refs? Or am I missing something obvious?

Copy link
Member Author

@RalfJung RalfJung Feb 6, 2023

Choose a reason for hiding this comment

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

When optimizations are disabled, we don't emit any of these attributes, no matter what happens here. That logic is... somewhere, I honestly don't know where exactly.

@RalfJung
Copy link
Member Author

RalfJung commented Feb 6, 2023

I can review, but I'm not sure if I'm the best person for it (so will need to allocate some time to actually grok what's going on)

Happy to assign someone else, if you prefer (and maybe have an idea about who would be a good reviewer).

@RalfJung
Copy link
Member Author

RalfJung commented Feb 6, 2023

r? @nbdd0121
since you seem on it already anyway. Thanks!

@rustbot
Copy link
Collaborator

rustbot commented Feb 6, 2023

Failed to set assignee to nbdd0121: invalid assignee

Note: Only org members, users with write permissions, or people who have commented on the PR may be assigned.

@RalfJung
Copy link
Member Author

RalfJung commented Feb 6, 2023

Oh, lol... bummer.^^

Copy link
Contributor

@nbdd0121 nbdd0121 left a comment

Choose a reason for hiding this comment

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

The compiler change looks correct and consistent with the PR description. I am not familiar enough with MIRI to comment about the MIRI change.

@nbdd0121
Copy link
Contributor

nbdd0121 commented Feb 6, 2023

Failed to set assignee to nbdd0121: invalid assignee

Note: Only org members, users with write permissions, or people who have commented on the PR may be assigned.

Yeah :) sorry. I work on the compiler a lot but isn't in the team.

@jackh726
Copy link
Member

jackh726 commented Feb 6, 2023

@bors delegate=nbdd0121

@bors
Copy link
Contributor

bors commented Feb 6, 2023

✌️ @nbdd0121 can now approve this pull request

@nbdd0121
Copy link
Contributor

nbdd0121 commented Feb 7, 2023

@bors r+

@bors
Copy link
Contributor

bors commented Feb 7, 2023

📌 Commit 1ef1687 has been approved by nbdd0121

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 Feb 7, 2023
@bors
Copy link
Contributor

bors commented Feb 7, 2023

⌛ Testing commit 1ef1687 with merge dffea43...

@bors
Copy link
Contributor

bors commented Feb 7, 2023

☀️ Test successful - checks-actions
Approved by: nbdd0121
Pushing dffea43 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Feb 7, 2023
@bors bors merged commit dffea43 into rust-lang:master Feb 7, 2023
@rustbot rustbot added this to the 1.69.0 milestone Feb 7, 2023
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (dffea43): comparison URL.

Overall result: ✅ improvements - no action needed

@rustbot label: -perf-regression

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.4% [-3.8%, -1.1%] 2
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

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

Cycles

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
1.8% [1.4%, 2.1%] 3
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

@RalfJung RalfJung deleted the dereferenceable-generators branch February 11, 2023 21:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. 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. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Miri does not properly check dereferenceable on &mut !Unpin
10 participants