Skip to content

Conversation

Amanieu
Copy link
Member

@Amanieu Amanieu commented Apr 17, 2025

This intrinsic doesn't drop the value that is not selected so this is manually done in the public function that wraps the intrinsic.

This intrinsic doesn't drop the value that is not selected so this is
manually done in the public function that wraps the intrinsic.
@rustbot
Copy link
Collaborator

rustbot commented Apr 17, 2025

r? @tgross35

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

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Apr 17, 2025
@rustbot
Copy link
Collaborator

rustbot commented Apr 17, 2025

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

@RalfJung
Copy link
Member

Good catch!
Would it maybe make sense to restrict this function to Copy types?

@Amanieu
Copy link
Member Author

Amanieu commented Apr 17, 2025

I tried that in #139933 but unfortunately that prevents the use of select_unpredictable for &mut T which are not Copy.

@RalfJung
Copy link
Member

Ah, we'd want NoDrop but we don't have that on the trait level... shame.

r=me for the implementation part of this PR once CI is happy. t-libs-api will have to make the final call regarding whether we want to support this function on types with drop glue.

@Amanieu
Copy link
Member Author

Amanieu commented Apr 17, 2025

@bors r=RalfJung

@bors
Copy link
Collaborator

bors commented Apr 17, 2025

📌 Commit e5e5fb9 has been approved by RalfJung

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 Apr 17, 2025
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 17, 2025
…iaskrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang#139351 (Autodiff batching2)
 - rust-lang#139483 (f*::NAN: guarantee that this is a quiet NaN)
 - rust-lang#139498 (Ignore zero-sized types in wasm future-compat warning)
 - rust-lang#139967 (Introduce and use specialized `//@ ignore-auxiliary` for test support files instead of using `//@ ignore-test`)
 - rust-lang#139969 (update libc)
 - rust-lang#139971 (Make C string merging test work on MIPS)
 - rust-lang#139974 (Change `InterpCx::instantiate*` function visibility to pub)
 - rust-lang#139977 (Fix drop handling in `hint::select_unpredictable`)

r? `@ghost`
`@rustbot` modify labels: rollup
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Apr 18, 2025
Rollup merge of rust-lang#139977 - Amanieu:select_unpredictable_drop, r=RalfJung

Fix drop handling in `hint::select_unpredictable`

This intrinsic doesn't drop the value that is not selected so this is manually done in the public function that wraps the intrinsic.
@bors bors merged commit dc2d273 into rust-lang:master Apr 18, 2025
6 checks passed
@rustbot rustbot added this to the 1.88.0 milestone Apr 18, 2025
github-actions bot pushed a commit to model-checking/verify-rust-std that referenced this pull request Apr 19, 2025
… r=RalfJung

Fix drop handling in `hint::select_unpredictable`

This intrinsic doesn't drop the value that is not selected so this is manually done in the public function that wraps the intrinsic.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Aug 31, 2025
…able-drop, r=joboet

Ensure consistent drop for panicking drop in hint::select_unpredictable

There are a few alternatives to the implementation. The principal problem is that the selected value must be owned (in the sense of having a drop flag of sorts) when the unselected value is dropped, such that panic unwind goes through the drop of both. This ownership must then be passed on in return when the drop went smoothly.

The basic way of achieving this is by extracting the selected value first, at the cost of relying on the optimizer a little more for detecting the copy as constructing the return value despite having a place in the body. Unfortunately, that causes LLVM to discard the !unpredictable annotation (for some reason that is beyond my comprehension of LLVM).

<details>
<summary>Extract from the build log showing an unannotated select being used</summary>

```
2025-08-09T16:51:06.8790764Z            39: define noundef i64 `@test_int2(i1` noundef zeroext %p, i64 noundef %a, i64 noundef %b) unnamed_addr #0 personality ptr `@rust_eh_personality` {
2025-08-09T16:51:06.8791368Z check:47'0                                  X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
2025-08-09T16:51:06.8791700Z            40: start:
2025-08-09T16:51:06.8791858Z check:47'0     ~~~~~~~
2025-08-09T16:51:06.8792043Z            41:  %ret.i = select i1 %p, i64 %a, i64 %b
2025-08-09T16:51:06.8792293Z check:47'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2025-08-09T16:51:06.8792686Z check:47'1               ?                             possible intended match
2025-08-09T16:51:06.8792946Z            42:  ret i64 %ret.i
2025-08-09T16:51:06.8793127Z check:47'0     ~~~~~~~~~~~~~~~~
```

</details>

So instead, this PR includes a guard to drop the selected `MaybeUnit<T>` which is active only for the section where the unselected value is dropped. That leaves the code for selecting the result intact leading to the expected ir. That complicates the 'unselection' process a little bit since we require _both_ values as a result of that intrinsic call. Since the arguments alias, this portion as well as the drop guard uses raw pointers.

Closes: rust-lang#145148
Prior: rust-lang#139977
rust-timer added a commit that referenced this pull request Aug 31, 2025
Rollup merge of #145174 - 197g:issue-145148-select-unpredictable-drop, r=joboet

Ensure consistent drop for panicking drop in hint::select_unpredictable

There are a few alternatives to the implementation. The principal problem is that the selected value must be owned (in the sense of having a drop flag of sorts) when the unselected value is dropped, such that panic unwind goes through the drop of both. This ownership must then be passed on in return when the drop went smoothly.

The basic way of achieving this is by extracting the selected value first, at the cost of relying on the optimizer a little more for detecting the copy as constructing the return value despite having a place in the body. Unfortunately, that causes LLVM to discard the !unpredictable annotation (for some reason that is beyond my comprehension of LLVM).

<details>
<summary>Extract from the build log showing an unannotated select being used</summary>

```
2025-08-09T16:51:06.8790764Z            39: define noundef i64 `@test_int2(i1` noundef zeroext %p, i64 noundef %a, i64 noundef %b) unnamed_addr #0 personality ptr `@rust_eh_personality` {
2025-08-09T16:51:06.8791368Z check:47'0                                  X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
2025-08-09T16:51:06.8791700Z            40: start:
2025-08-09T16:51:06.8791858Z check:47'0     ~~~~~~~
2025-08-09T16:51:06.8792043Z            41:  %ret.i = select i1 %p, i64 %a, i64 %b
2025-08-09T16:51:06.8792293Z check:47'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2025-08-09T16:51:06.8792686Z check:47'1               ?                             possible intended match
2025-08-09T16:51:06.8792946Z            42:  ret i64 %ret.i
2025-08-09T16:51:06.8793127Z check:47'0     ~~~~~~~~~~~~~~~~
```

</details>

So instead, this PR includes a guard to drop the selected `MaybeUnit<T>` which is active only for the section where the unselected value is dropped. That leaves the code for selecting the result intact leading to the expected ir. That complicates the 'unselection' process a little bit since we require _both_ values as a result of that intrinsic call. Since the arguments alias, this portion as well as the drop guard uses raw pointers.

Closes: #145148
Prior: #139977
github-actions bot pushed a commit to rust-lang/compiler-builtins that referenced this pull request Sep 1, 2025
…, r=joboet

Ensure consistent drop for panicking drop in hint::select_unpredictable

There are a few alternatives to the implementation. The principal problem is that the selected value must be owned (in the sense of having a drop flag of sorts) when the unselected value is dropped, such that panic unwind goes through the drop of both. This ownership must then be passed on in return when the drop went smoothly.

The basic way of achieving this is by extracting the selected value first, at the cost of relying on the optimizer a little more for detecting the copy as constructing the return value despite having a place in the body. Unfortunately, that causes LLVM to discard the !unpredictable annotation (for some reason that is beyond my comprehension of LLVM).

<details>
<summary>Extract from the build log showing an unannotated select being used</summary>

```
2025-08-09T16:51:06.8790764Z            39: define noundef i64 `@test_int2(i1` noundef zeroext %p, i64 noundef %a, i64 noundef %b) unnamed_addr #0 personality ptr `@rust_eh_personality` {
2025-08-09T16:51:06.8791368Z check:47'0                                  X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
2025-08-09T16:51:06.8791700Z            40: start:
2025-08-09T16:51:06.8791858Z check:47'0     ~~~~~~~
2025-08-09T16:51:06.8792043Z            41:  %ret.i = select i1 %p, i64 %a, i64 %b
2025-08-09T16:51:06.8792293Z check:47'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2025-08-09T16:51:06.8792686Z check:47'1               ?                             possible intended match
2025-08-09T16:51:06.8792946Z            42:  ret i64 %ret.i
2025-08-09T16:51:06.8793127Z check:47'0     ~~~~~~~~~~~~~~~~
```

</details>

So instead, this PR includes a guard to drop the selected `MaybeUnit<T>` which is active only for the section where the unselected value is dropped. That leaves the code for selecting the result intact leading to the expected ir. That complicates the 'unselection' process a little bit since we require _both_ values as a result of that intrinsic call. Since the arguments alias, this portion as well as the drop guard uses raw pointers.

Closes: rust-lang/rust#145148
Prior: rust-lang/rust#139977
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Sep 1, 2025
…, r=joboet

Ensure consistent drop for panicking drop in hint::select_unpredictable

There are a few alternatives to the implementation. The principal problem is that the selected value must be owned (in the sense of having a drop flag of sorts) when the unselected value is dropped, such that panic unwind goes through the drop of both. This ownership must then be passed on in return when the drop went smoothly.

The basic way of achieving this is by extracting the selected value first, at the cost of relying on the optimizer a little more for detecting the copy as constructing the return value despite having a place in the body. Unfortunately, that causes LLVM to discard the !unpredictable annotation (for some reason that is beyond my comprehension of LLVM).

<details>
<summary>Extract from the build log showing an unannotated select being used</summary>

```
2025-08-09T16:51:06.8790764Z            39: define noundef i64 `@test_int2(i1` noundef zeroext %p, i64 noundef %a, i64 noundef %b) unnamed_addr #0 personality ptr `@rust_eh_personality` {
2025-08-09T16:51:06.8791368Z check:47'0                                  X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
2025-08-09T16:51:06.8791700Z            40: start:
2025-08-09T16:51:06.8791858Z check:47'0     ~~~~~~~
2025-08-09T16:51:06.8792043Z            41:  %ret.i = select i1 %p, i64 %a, i64 %b
2025-08-09T16:51:06.8792293Z check:47'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2025-08-09T16:51:06.8792686Z check:47'1               ?                             possible intended match
2025-08-09T16:51:06.8792946Z            42:  ret i64 %ret.i
2025-08-09T16:51:06.8793127Z check:47'0     ~~~~~~~~~~~~~~~~
```

</details>

So instead, this PR includes a guard to drop the selected `MaybeUnit<T>` which is active only for the section where the unselected value is dropped. That leaves the code for selecting the result intact leading to the expected ir. That complicates the 'unselection' process a little bit since we require _both_ values as a result of that intrinsic call. Since the arguments alias, this portion as well as the drop guard uses raw pointers.

Closes: rust-lang/rust#145148
Prior: rust-lang/rust#139977
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-libs Relevant to the library 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