Implement va_list and va_arg for s390x FFI
Following the s390x ELF ABI and based on the clang implementation, provide appropriate definitions of va_list in library/core/src/ffi/mod.rs and va_arg handling in compiler/rustc_codegen_llvm/src/va_arg.rs.
Fixes the following test cases on s390x:
src/test/run-make-fulldeps/c-link-to-rust-va-list-fn src/test/ui/abi/variadic-ffi.rs
Fixes https://github.com/rust-lang/rust/issues/84628.
Following the s390x ELF ABI and based on the clang implementation,
provide appropriate definitions of va_list in library/core/src/ffi/mod.rs
and va_arg handling in compiler/rustc_codegen_llvm/src/va_arg.rs.
Fixes the following test cases on s390x:
src/test/run-make-fulldeps/c-link-to-rust-va-list-fn
src/test/ui/abi/variadic-ffi.rs
Fixes https://github.com/rust-lang/rust/issues/84628.
Revert "Replace usage of `ResumeTy` in async lowering with `Context`"
Reverts rust-lang/rust#105250
Fixes: #105501
Following instructions from [forge](https://forge.rust-lang.org/compiler/reviews.html#reverts).
This change introduced a breaking change that is not actionable nor relevant, and is blocking updates to our toolchain. Along with other comments on the CL marking issues that are fixed by reverts, reverting is best until these issues can be resolved
cc. `@Swatinem`
docs: improve pin docs
Override https://github.com/rust-lang/rust/pull/104195 with a full cleanup of the git history, now it should be ready to be merged.
r? ``@eholk``
``@rustbot`` label +A-async-await
Realistic `Path::as_mut_os_str` doctest
With "Implement DerefMut for PathBuf" (#105018) now merged, it's
possible to exercise `Path::as_mut_os_str` (#105002) without going
through `into_boxed_path`.
Use a more efficient `Once` on platforms without threads
The current implementation uses an atomic queue and spins rather than panicking when calling `call_once` recursively. Since concurrency is not supported on platforms like WASM, `Once` can be implemented much more efficiently using just a single non-atomic state variable.
fs: Fix#50619 (again) and add a regression test
Bug #50619 was fixed by adding an end_of_stream flag in #50630.
Unfortunately, that fix only applied to the readdir_r() path. When I
switched Linux to use readdir() in #92778, I inadvertently reintroduced
the bug on that platform. Other platforms that had always used
readdir() were presumably never fixed.
This patch enables end_of_stream for all platforms, and adds a
Linux-specific regression test that should hopefully prevent the bug
from being reintroduced again.
std::fmt: Use args directly in example code
The lint "clippy::uninlined_format_args" recommends inline variables in format strings. Fix two places in the docs that do not do this. I noticed this because I copy/pasted one example in to my project, then noticed this lint error. This fixes:
```
error: variables can be used directly in the `format!` string
--> src/main.rs:30:22
|
30 | let string = format!("{:.*}", decimals, magnitude);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: variables can be used directly in the `format!` string
--> src/main.rs:39:2
|
39 | write!(&mut io::stdout(), "{}", args).unwrap();
```
Support call and drop terminators in custom mir
The only caveat with this change is that cleanup blocks are not supported. I would like to add them, but it's not quite clear to me what the best way to do that is, so I'll have to think about it some more.
r? ``@oli-obk``
Allow blocking `Command::output`
### Problem
Currently, `Command::output` is internally implemented using `Command::spawn`. This is problematic because some targets (like UEFI) do not actually support multitasking and thus block while the program is executing. This coupling does not make much sense as `Command::output` is supposed to block until the execution is complete anyway and thus does not need to rely on a non-blocking `Child` or any other intermediate.
### Solution
This PR moves the implementation of `Command::output` to `std::sys`. This means targets can choose to implement only `Command::output` without having to implement `Command::spawn`.
### Additional Information
This was originally conceived when working on https://github.com/rust-lang/rust/pull/100316. Currently, the only target I know about that will benefit from this change is UEFI.
This PR can also be used to implement more efficient `Command::output` since the intermediate `Process` is not actually needed anymore, but that is outside the scope of this PR.
Since this is not a public API change, I'm not sure if an RFC is needed or not.
The lint "clippy::uninlined_format_args" recommends inline
variables in format strings. Fix two places in the docs that do
not do this. I noticed this because I copy/pasted one example in
to my project, then noticed this lint error. This fixes:
error: variables can be used directly in the `format!` string
--> src/main.rs:30:22
|
30 | let string = format!("{:.*}", decimals, magnitude);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: variables can be used directly in the `format!` string
--> src/main.rs:39:2
|
39 | write!(&mut io::stdout(), "{}", args).unwrap();
Previously, the str.lines() docstring stated that lines are split at line
endings, but not whether those were returned or not. This new version of the
docstring states this explicitly, avoiding the need of getting to doctests to
get an answer to this FAQ.
Implement DerefMut for PathBuf
Without this, there's no way to get a `&mut Path` from `PathBuf` without
going through `into_boxed_path`. This is relevant now that #105002 adds
`PathBuf::as_mut_os_string` and `Path::as_mut_os_str`.
This commit
- Renames `Split*::{as_str -> remainder}` as it seems less confusing
- Makes `remainder` return Option<&str> to distinguish between
"iterator is exhausted" and "the tail is empty"
doc: Fix a few small issues
Hey, while reading through the (awesome) stdlib docs, I found a few minor typos.
* A few typos around generic types (`;` vs `,`)
* Use inline code formatting for code fragments
* One instance of wrong wording
Custom MIR: Many more improvements
Commits are each atomic changes, best reviewed one at a time, with the exception that the last commit includes all the documentation.
### First commit
Unsafetyck was not correctly disabled before for `dialect = "built"` custom MIR. This is fixed and a regression test is added.
### Second commit
Implements `Discriminant`, `SetDiscriminant`, and `SwitchInt`.
### Third commit
Implements indexing, field, and variant projections.
### Fourth commit
Documents the previous commits and everything else.
There is some amount of weirdness here due to having to beat Rust syntax into cooperating with MIR concepts, but it hopefully should not be too much. All of it is documented.
r? `@oli-obk`
Use more LFS functions.
On Linux, use mmap64, open64, openat64, and sendfile64 in place of their non-LFS counterparts.
This is relevant to #94173.
With these changes (together with rust-lang/backtrace-rs#501), the simple binaries I produce with rustc seem to have no non-LFS functions, so maybe #94173 is fixed. But I can't be sure if I've missed something and maybe some non-LFS functions could sneak in somehow.
Bug #50619 was fixed by adding an end_of_stream flag in #50630.
Unfortunately, that fix only applied to the readdir_r() path. When I
switched Linux to use readdir() in #92778, I inadvertently reintroduced
the bug on that platform. Other platforms that had always used
readdir() were presumably never fixed.
This patch enables end_of_stream for all platforms, and adds a
Linux-specific regression test that should hopefully prevent the bug
from being reintroduced again.
Better documentation for env::home_dir()'s broken behaviour
This improves the documentation to say *why* it was deprecated. The reason was because it reads `HOME` on Windows which is meaningless there. Note that the PR that deprecated it stated that returning an empty string if `HOME` is set to an empty string was a problem, however I can find no evidence that this is the case. `cd` handles it fine whereas if `HOME` is unset it gives an explicit `HOME not set` error.
* Original deprecation reason: https://internals.rust-lang.org/t/deprecate-or-break-fix-std-env-home-dir/7315
* Original deprecation PR: https://github.com/rust-lang/rust/pull/51656
See #71684
This allows decoupling `Command::spawn` and `Command::output`. This is
useful for targets which do support launching programs in blocking mode
but do not support multitasking (Eg: UEFI).
This was originally conceived when working on https://github.com/rust-lang/rust/pull/100316
Signed-off-by: Ayush Singh <ayushsingh1325@gmail.com>
Avoid heap allocation when truncating thread names
Ensure that heap allocation does not occur in a thread until `std::thread` is ready. This fixes issues with custom allocators that call `std:🧵:current()`, since doing so prematurely initializes `THREAD_INFO` and causes the following `thread_info::set()` to fail.
Remove wrong note for short circuiting operators
They *are* representable by traits, even if the short-circuiting behaviour requires a different approach than the non-short-circuiting operators. For an example proposal, see the postponed [RFC 2722](https://github.com/rust-lang/rfcs/pull/2722). As it is not accurate, remove most of the note.
Reimplement std's thread parker on top of events on SGX
Mutex and Condvar are being replaced by more efficient implementations, which need thread parking themselves (see #93740). Therefore, the generic `Parker` needs to be replaced on all platforms where the new lock implementation will be used.
SGX enclaves have a per-thread event state, which allows waiting for and setting specific bits. This is already used by the current mutex implementation. The thread parker can however be much more efficient, as it only needs to store the `TCS` address of one thread. This address is stored in a state variable, which can also be set to indicate the thread was already notified.
`park_timeout` does not guard against spurious wakeups like the current condition variable does. This is allowed by the API of `Parker`, and I think it is better to let users handle these wakeups themselves as the guarding is quite expensive and might not be necessary.
`@jethrogb` as you wrote the initial SGX support for `std`, I assume you are the target maintainer? Could you help me test this, please? Lacking a x86_64 chip, I can't run SGX.
They *are* representable by traits, even if the short-circuiting
behaviour requires a different approach than the non-short-circuiting
operators. For an example proposal, see the postponed RFC 2722.
As it is not accurate, reword the note.
Make `VecDeque::from_iter` O(1) from `vec(_deque)::IntoIter`
As suggested in https://github.com/rust-lang/rust/pull/105046#issuecomment-1330371695 by
r? ``@the8472``
`Vec` & `VecDeque`'s `IntoIter`s own the allocations, and even if advanced can be turned into `VecDeque`s in O(1).
This is just a specialization, not an API or doc commitment, so I don't think it needs an FCP.
attempt to clarify align_to docs
This is not intended the change the docs at all, but `@workingjubilee` said the current docs are incomprehensible to some people so this is an attempt to fix that. No idea if it helps, so -- feedback welcome.
(Please let's not use this to discuss *changing* the spec. Whoever wants to change the spec should please make a separate PR for that.)
Add `read_to_end` method for `sys::{target}::pipe::AnonPipe`. This allows
having a more optimized version of `read_to_end` for ChildStdout.
Signed-off-by: Ayush Singh <ayushsingh1325@gmail.com>
Fix warning when libcore is compiled with no_fp_fmt_parse
Discovered when trying to compile Rust-for-Linux with Rust 1.66 beta.
It'll be helpful if this is backported to beta (should be trivial enough for backporting), so Rust-for-Linux's rust version bump wouldn't need to do `--cap-lints allow` for libcore.
kmc-solid: `std::sys` code maintenance
Includes a set of changes to fix the [`*-kmc-solid_*`](https://doc.rust-lang.org/nightly/rustc/platform-support/kmc-solid.html) Tier 3 targets and make some other improvements.
- Address `fuzzy_provenance_casts` by using `expose_addr` and `from_exposed_addr` for pointer-integer casts
- Add a stub implementation of `is_terminal` (#98070)
- Address `unused_imports` and `unused_unsafe`
- Stop doing `Box::from_raw(&*(x: Box<T>) as *const T as *mut T)`
Ensure that heap allocation does not occur in a thread until std::thread
is ready. This fixes issues with custom allocators that call
std:🧵:current(), since doing so prematurely initializes
THREAD_INFO and causes the following thread_info::set() to fail.
On Linux, use mmap64, open64, openat64, and sendfile64 in place of their
non-LFS counterparts.
This is relevant to #94173.
With these changes (together with rust-lang/backtrace-rs#501), the
simple binaries I produce with rustc seem to have no non-LFS functions,
so maybe #94173 is fixed. But I can't be sure if I've missed something
and maybe some non-LFS functions could sneak in somehow.
Pass on null handle values to child process
Fixes#101645
In Windows, stdio handles are (semantically speaking) `Option<Handle>` where `Handle` is a non-zero value. When spawning a process with `Stdio::Inherit`, Rust currently turns zero values into `-1` values. This has the unfortunate effect of breaking console subprocesses (which typically need stdio) that are spawned from gui applications (that lack stdio by default) because the console process won't be assigned handles from the newly created console (as they usually would in that situation). Worse, `-1` is actually [a valid handle](https://doc.rust-lang.org/std/os/windows/io/struct.OwnedHandle.html) which means "the current process". So if a console process, for example, waits on stdin and it has a `-1` value then the process will end up waiting on itself.
This PR fixes it by propagating the nulls instead of converting them to `-1`.
While I think the current behaviour is a mistake, changing it (however justified) is an API change so I think this PR should at least have some input from t-libs-api. So choosing at random...
r? `@joshtriplett`
Replace usage of `ResumeTy` in async lowering with `Context`
Replaces using `ResumeTy` / `get_context` in favor of using `&'static mut Context<'_>`.
Usage of the `'static` lifetime here is technically "cheating", and replaces the raw pointer in `ResumeTy` and the `get_context` fn that pulls the correct lifetimes out of thin air.
fixes https://github.com/rust-lang/rust/issues/104828 and https://github.com/rust-lang/rust/pull/104321#issuecomment-1336363077
r? `@oli-obk`
remove no-op 'let _ = '
Also see the discussion at https://github.com/rust-lang/rust/pull/93563#discussion_r1034057555.
I don't know why these `Drop` implementations exist to begin with, given that their body does literally nothing, but did not want to change that. (It might affect dropck.)
Cc `````@ibraheemdev````` `````@Amanieu`````
Commit 77005950f0 implemented masking of
FileType to fix an issue[^1] in the semantic of FileType comparison.
This commit introduces masking to Hash to maintain the invariant that
x == y => hash(x) == hash(y).
[^1]: https://github.com/rust-lang/rust/issues/104900
Replaces using `ResumeTy` / `get_context` in favor of using `&'static mut Context<'_>`.
Usage of the `'static` lifetime here is technically "cheating", and replaces
the raw pointer in `ResumeTy` and the `get_context` fn that pulls the
correct lifetimes out of thin air.
There are OSs that always return the lowest free value.
The algorithm in `lazy_init` always avoids keys with the
sentinel value.
In affected OSs, this means that each call to `lazy_init`
will always request two keys from the OS and returns/frees
the first one (with sentinel value) immediately afterwards.
By making the sentinel value configurable, affected OSs can
use a different value than zero to prevent this performance
issue.
PartialEq: PERs are homogeneous
PartialEq claims that it corresponds to a PER, but that is only a well-defined statement when `Rhs == Self`. There is no standard notion of PER on a relation between two different sets/types. So move this out of the first paragraph and clarify this.
Send `VecDeque::from_iter` via `Vec::from_iter`
Since it's O(1) to convert between them now, might as well reuse the logic.
Mostly for the various specializations it does, but might also save some monomorphization work if, say, people collect slice iterators into both `Vec`s and `VecDeque`s.
Create a hacky fail-fast mode that stops tests at the first failure
This is useful for not having to wait until all 10k+ ui tests have finished running and then having to crawl through hundreds of failure reports.
You now only get the first report when you turn on that env var and no new tests are run at all
This works like a charm, but is obviously welded on very crudely
improve doc of into_boxed_slice and impl From<Vec<T>> for Box<[T]>
Improves description of `into_boxed_slice`, and adds example to `impl From<Vec<T>> for Box<[T]>`.
Fixes#98908
Adjust inlining attributes around panic_immediate_abort
The goal of `panic_immediate_abort` is to permit the panic runtime and formatting code paths to be optimized away. But while poking through some disassembly of a small program compiled with that option, I found that was not the case. Enabling LTO did address that specific issue, but enabling LTO is a steep price to pay for this feature doing its job.
This PR fixes that, by tweaking two things:
* All the slice indexing functions that we `const_eval_select` on get `#[inline]`. `objdump -dC` told me that originally some `_ct` functions could end up in an executable. I won't pretend to understand what's going on there.
* Normalize attributes across all `panic!` wrappers: use `inline(never) + cold` normally, and `inline` when `panic_immediate_abort` is enabled.
But also, with LTO and `panic_immediate_abort` enabled, this patch knocks ~709 kB out of the `.text` segment of `librustc_driver.so`. That is slightly surprising to me, my best theory is that this shifts some inlining earlier in compilation, enabling some subsequent optimizations. The size improvement of `librustc_driver.so` with `panic_immediate_abort` due to this patch is greater with LTO than without LTO, which I suppose backs up this theory.
I do not know how to test this. I would quite like to, because I think what this is solving was an accidental regression. This only works with `-Zbuild-std` which is a cargo flag, and thus can't be used in a rustc codegen test.
r? `@thomcc`
---
I do not seriously think anyone is going to use a compiler built with `panic_immediate_abort`, but I wanted a big complicated Rust program to try this out on, and the compiler is such.
Add `type_ascribe!` macro as placeholder syntax for type ascription
This makes it still possible to test the internal semantics of type ascription even once the `:`-syntax is removed from the parser. The macro now gets used in a bunch of UI tests that test the semantics and not syntax of type ascription.
I might have forgotten a few tests but this should hopefully be most of them. The remaining ones will certainly be found once type ascription is removed from the parser altogether.
Part of #101728
`#![custom_mir]`: Various improvements
This PR makes a bunch of improvements to `#![custom_mir]`. Ideally this would be 4 PRs, one for each commit, but those would take forever to get merged and be a pain to juggle. Should still be reviewed one commit at a time though.
### Commit 1: Support arbitrary `let`
Before this change, all locals used in the body need to be declared at the top of the `mir!` invocation, which is rather annoying. We attempt to change that.
Unfortunately, we still have the requirement that the output of the `mir!` macro must resolve, typecheck, etc. Because of that, we can't just accept this in the THIR -> MIR parser because something like
```rust
{
let x = 0;
Goto(other)
}
other = {
RET = x;
Return()
}
```
will fail to resolve. Instead, the implementation does macro shenanigans to find the let declarations and extract them as part of the `mir!` macro. That *works*, but it is fairly complicated and degrades debuginfo by quite a bit. Specifically, the spans for any statements and declarations that are affected by this are completely wrong. My guess is that this is a net improvement though.
One way to recover some of the debuginfo would be to not support type annotations in the `let` statements, which would allow us to parse like `let $stmt:stmt`. That seems quite surprising though.
### Commit 2: Parse consts
Reuses most of the const parsing from regular Mir building for building custom mir
### Commit 3: Parse statics
Statics are slightly weird because the Mir primitive associated with them is a reference/pointer to them, so this is factored out separately.
### Commit 4: Fix some spans
A bunch of the spans were non-ideal, so we adjust them to be much more helpful.
r? `@oli-obk`
Pointer-integer casts are required for conversion between `EXINF` (ITRON
task entry point parameter) and `*const ThreadInner`. Addresses the
deny-level lint `fuzzy_provenance_casts`.
Extract WStrUnits to sys_common::wstr
This commit extracts WStrUnits from sys::windows::args to sys_common::wstr. This allows using the same structure for other targets which use wtf8 (example UEFI).
This was originally a part of https://github.com/rust-lang/rust/pull/100316
Signed-off-by: Ayush Singh <ayushsingh1325@gmail.com>
Add slice to the stack allocated string comment
Precise that the "stack allocated string" is not a string but a string slice.
``@rustbot`` label +A-docs
Since it's O(1) to convert between them now, might as well reuse the logic.
Mostly for the various specializations it does, but might also save some monomorphization work if, say, people collect slice iterators into both `Vec`s and `VecDeque`s.
This commit extracts WStrUnits from sys::windows::args to sys_common::wstr. This
allows using the same structure for other targets which use wtf8 (example UEFI).
This was originally a part of https://github.com/rust-lang/rust/pull/100316
Signed-off-by: Ayush Singh <ayushsingh1325@gmail.com>
Update VecDeque implementation to use head+len instead of head+tail
(See #99805)
This changes `alloc::collections::VecDeque`'s internal representation from using head and tail indices to using a head index and a length field. It has a few advantages over the current design:
* It allows the buffer to be of length 0, which means the `VecDeque::new` new longer has to allocate and could be changed to a `const fn`
* It allows the `VecDeque` to fill the buffer completely, unlike the old implementation, which always had to leave a free space
* It removes the restriction for the size to be a power of two, allowing it to properly `shrink_to_fit`, unlike the old `VecDeque`
* The above points also combine to allow the `Vec<T> -> VecDeque<T>` conversion to be very cheap and guaranteed O(1). I mention this in the `From<Vec<T>>` impl, but it's not a strong guarantee just yet, as that would likely need some form of API change proposal.
All the tests seem to pass for the new `VecDeque`, with some slight adjustments.
r? `@scottmcm`
Remove redundant `all` in cfg
This appears to have been accidentally left in after removing the other branches 45bf1ed1a1
(hat tip to kangalioo for the git archaeology)
Stop peeling the last iteration of the loop in `Vec::resize_with`
`resize_with` uses the `ExtendWith` code that peels the last iteration:
341d8b8a2c/library/alloc/src/vec/mod.rs (L2525-L2529)
But that's kinda weird for `ExtendFunc` because it does the same thing on the last iteration anyway:
341d8b8a2c/library/alloc/src/vec/mod.rs (L2494-L2502)
So this just has it use the normal `extend`-from-`TrustedLen` code instead.
r? `@ghost`
Manually implement PartialEq for Option<T> and specialize non-nullable types
This PR manually implements `PartialEq` and `StructuralPartialEq` for `Option`, which seems to produce slightly better codegen than the automatically derived implementation.
It also allows specializing on the `core::num::NonZero*` and `core::ptr::NonNull` types, taking advantage of the niche optimization by transmuting the `Option<T>` to `T` to be compared directly, which can be done in just two instructions.
A comparison of the original, new and specialized code generation is available [here](https://godbolt.org/z/dE4jxdYsa).
Revert "Forbid inlining `thread_local!`'s `__getit` function on Windows"
Revert of #101368, fixes#104852.
I'd rather not do this since that's a soundness fix and this is hitting some compiler bug, but I don't really know an alternative.
r? `@ChrisDenton`
Previously, async constructs would be lowered to "normal" generators,
with an additional `from_generator` / `GenFuture` shim in between to
convert from `Generator` to `Future`.
The compiler will now special-case these generators internally so that
async constructs will *directly* implement `Future` without the need
to go through the `from_generator` / `GenFuture` shim.
The primary motivation for this change was hiding this implementation
detail in stack traces and debuginfo, but it can in theory also help
the optimizer as there is less abstractions to see through.
Forbid inlining `thread_local!`'s `__getit` function on Windows
Sadly, this will make things slower to avoid UB in an edge case, but it seems hard to avoid... and really whenever I look at this code I can't help but think we're asking for trouble.
It's pretty dodgy for us to leave this as a normal function rather than `#[inline(never)]`, given that if it *does* get inlined into a dynamically linked component, it's extremely unsafe (you get some other thread local, or if you're lucky, crash). Given that it's pretty rare for people to use dylibs on Windows, the fact that we haven't gotten bug reports about it isn't really that convincing. Ideally we'd come up with some kind of compiler solution (that avoids paying for this cost when static linking, or *at least* for use within the same crate...), but it's not clear what that looks like.
Oh, and because all this is only needed when we're implementing `thread_local!` with `#[thread_local]`, this patch adjusts the `cfg_attr` to be `all(windows, target_thread_local)` as well.
r? ``@ChrisDenton``
See also #84933, which is about improving the situation.
disable strict-provenance-violating doctests in Miri
Most of these are on deprecated unstable functions anyway. This lets us run the remaining doctests with `-Zmiri-strict-provenance`, which I think is a win.
r? `@thomcc`
Constify remaining `Layout` methods
Makes the methods on `Layout` that aren't yet unstably const, under the same feature and issue, #67521. Most of them required no changes, only non-trivial change is probably constifying `ValidAlignment` which may affect #102072
Deprecate the unstable `ptr_to_from_bits` feature
I propose that we deprecate the (unstable!) `to_bits` and `from_bits` methods on raw pointers. (With the intent to ~~remove them once `addr` has been around long enough to make the transition easy on people -- maybe another 6 weeks~~ remove them fairly soon after, as the strict and expose versions have been around for a while already.)
The APIs that came from the strict provenance explorations (#95228) are a more holistic version of these, and things like `.expose_addr()` work for the "that cast looks sketchy" case even if the full strict provenance stuff never happens. (As a bonus, `addr` is even shorter than `to_bits`, though it is only applicable if people can use full strict provenance! `addr` is *not* a direct replacement for `to_bits`.) So I think it's fine to move away from the `{to|from}_bits` methods, and encourage the others instead.
That also resolves the worry that was brought up (I forget where) that `q.to_bits()` and `(*q).to_bits()` both work if `q` is a pointer-to-floating-point, as they also have a `to_bits` method.
Tracking issue #91126
Code search: https://github.com/search?l=Rust&p=1&q=ptr_to_from_bits&type=Code
For potential pushback, some users in case they want to chime in
- `@RSSchermer` 365bb68541/arwa/src/html/custom_element.rs (L105)
- `@strax` 99616d1dbf/openexr/src/core/alloc.rs (L36)
- `@MiSawa` 577c622358/crates/kernel/src/timer.rs (L50)
Add slice methods for indexing via an array of indices.
Disclaimer: It's been a while since I contributed to the main Rust repo, apologies in advance if this is large enough already that it should've been an RFC.
---
# Update:
- Based on feedback, removed the `&[T]` variant of this API, and removed the requirements for the indices to be sorted.
# Description
This adds the following slice methods to `core`:
```rust
impl<T> [T] {
pub unsafe fn get_many_unchecked_mut<const N: usize>(&mut self, indices: [usize; N]) -> [&mut T; N];
pub fn get_many_mut<const N: usize>(&mut self, indices: [usize; N]) -> Option<[&mut T; N]>;
}
```
This allows creating multiple mutable references to disjunct positions in a slice, which previously required writing some awkward code with `split_at_mut()` or `iter_mut()`. For the bound-checked variant, the indices are checked against each other and against the bounds of the slice, which requires `N * (N + 1) / 2` comparison operations.
This has a proof-of-concept standalone implementation here: https://crates.io/crates/index_many
Care has been taken that the implementation passes miri borrow checks, and generates straight-forward assembly (though this was only checked on x86_64).
# Example
```rust
let v = &mut [1, 2, 3, 4];
let [a, b] = v.get_many_mut([0, 2]).unwrap();
std::mem::swap(a, b);
*v += 100;
assert_eq!(v, &[3, 2, 101, 4]);
```
# Codegen Examples
<details>
<summary>Click to expand!</summary>
Disclaimer: Taken from local tests with the standalone implementation.
## Unchecked Indexing:
```rust
pub unsafe fn example_unchecked(slice: &mut [usize], indices: [usize; 3]) -> [&mut usize; 3] {
slice.get_many_unchecked_mut(indices)
}
```
```nasm
example_unchecked:
mov rcx, qword, ptr, [r9]
mov r8, qword, ptr, [r9, +, 8]
mov r9, qword, ptr, [r9, +, 16]
lea rcx, [rdx, +, 8*rcx]
lea r8, [rdx, +, 8*r8]
lea rdx, [rdx, +, 8*r9]
mov qword, ptr, [rax], rcx
mov qword, ptr, [rax, +, 8], r8
mov qword, ptr, [rax, +, 16], rdx
ret
```
## Checked Indexing (Option):
```rust
pub unsafe fn example_option(slice: &mut [usize], indices: [usize; 3]) -> Option<[&mut usize; 3]> {
slice.get_many_mut(indices)
}
```
```nasm
mov r10, qword, ptr, [r9, +, 8]
mov rcx, qword, ptr, [r9, +, 16]
cmp rcx, r10
je .LBB0_7
mov r9, qword, ptr, [r9]
cmp rcx, r9
je .LBB0_7
cmp rcx, r8
jae .LBB0_7
cmp r10, r9
je .LBB0_7
cmp r9, r8
jae .LBB0_7
cmp r10, r8
jae .LBB0_7
lea r8, [rdx, +, 8*r9]
lea r9, [rdx, +, 8*r10]
lea rcx, [rdx, +, 8*rcx]
mov qword, ptr, [rax], r8
mov qword, ptr, [rax, +, 8], r9
mov qword, ptr, [rax, +, 16], rcx
ret
.LBB0_7:
mov qword, ptr, [rax], 0
ret
```
## Checked Indexing (Panic):
```rust
pub fn example_panic(slice: &mut [usize], indices: [usize; 3]) -> [&mut usize; 3] {
let len = slice.len();
match slice.get_many_mut(indices) {
Some(s) => s,
None => {
let tmp = indices;
index_many::sorted_bound_check_failed(&tmp, len)
}
}
}
```
```nasm
example_panic:
sub rsp, 56
mov rax, qword, ptr, [r9]
mov r10, qword, ptr, [r9, +, 8]
mov r9, qword, ptr, [r9, +, 16]
cmp r9, r10
je .LBB0_6
cmp r9, rax
je .LBB0_6
cmp r9, r8
jae .LBB0_6
cmp r10, rax
je .LBB0_6
cmp rax, r8
jae .LBB0_6
cmp r10, r8
jae .LBB0_6
lea rax, [rdx, +, 8*rax]
lea r8, [rdx, +, 8*r10]
lea rdx, [rdx, +, 8*r9]
mov qword, ptr, [rcx], rax
mov qword, ptr, [rcx, +, 8], r8
mov qword, ptr, [rcx, +, 16], rdx
mov rax, rcx
add rsp, 56
ret
.LBB0_6:
mov qword, ptr, [rsp, +, 32], rax
mov qword, ptr, [rsp, +, 40], r10
mov qword, ptr, [rsp, +, 48], r9
lea rcx, [rsp, +, 32]
mov edx, 3
call index_many::bound_check_failed
ud2
```
</details>
# Extensions
There are multiple optional extensions to this.
## Indexing With Ranges
This could easily be expanded to allow indexing with `[I; N]` where `I: SliceIndex<Self>`. I wanted to keep the initial implementation simple, so I didn't include it yet.
## Panicking Variant
We could also add this method:
```rust
impl<T> [T] {
fn index_many_mut<const N: usize>(&mut self, indices: [usize; N]) -> [&mut T; N];
}
```
This would work similar to the regular index operator and panic with out-of-bound indices. The advantage would be that we could more easily ensure good codegen with a useful panic message, which is non-trivial with the `Option` variant.
This is implemented in the standalone implementation, and used as basis for the codegen examples here and there.
Pin::new_unchecked: discuss pinning closure captures
Regardless of how the discussion in https://github.com/rust-lang/rust/pull/102737 turns out, pinning closure captures is super subtle business and probably worth discussing separately.
Fix doc example for `wrapping_abs`
The `max` variable is unused. This change introduces the `min_plus` variable, to make the example similar to the one from `saturating_abs`. An alternative would be to remove the unused variable.
add examples to chunks remainder methods.
add examples to chunks remainder methods.
my motivation for adding the examples was to make it very clear that the state of the iterator (in terms of where its cursor lies) has no effect on what remainder returns.
Also fixed some links to rchunk remainder methods.
Clarify and restrict when `{Arc,Rc}::get_unchecked_mut` is allowed.
(Tracking issue for `{Arc,Rc}::get_unchecked_mut`: #63292)
(I'm using `Rc` in this comment, but it applies for `Arc` all the same).
As currently documented, `Rc::get_unchecked_mut` can lead to unsoundness when multiple `Rc`/`Weak` pointers to the same allocation exist. The current documentation only requires that other `Rc`/`Weak` pointers to the same allocation "must not be dereferenced for the duration of the returned borrow". This can lead to unsoundness in (at least) two ways: variance, and `Rc<str>`/`Rc<[u8]>` aliasing. ([playground link](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=d7e2d091c389f463d121630ab0a37320)).
This PR changes the documentation of `Rc::get_unchecked_mut` to restrict usage to when all `Rc<T>`/`Weak<T>` have the exact same `T` (including lifetimes). I believe this is sufficient to prevent unsoundness, while still allowing `get_unchecked_mut` to be called on an aliased `Rc` as long as the safety contract is upheld by the caller.
## Alternatives
* A less strict, but still sound alternative would be to say that the caller must only write values which are valid for all aliased `Rc`/`Weak` inner types. (This was [mentioned](https://github.com/rust-lang/rust/issues/63292#issuecomment-568284090) in the tracking issue). This may be too complicated to clearly express in the documentation.
* A more strict alternative would be to say that there must not be any aliased `Rc`/`Weak` pointers, i.e. it is required that get_mut would return `Some(_)`. (This was also mentioned in the tracking issue). There is at least one codebase that this would cause to become unsound ([here](be5a164d77/src/memtable.rs (L166)), where additional locking is used to ensure unique access to an aliased `Rc<T>`; I saw this because it was linked on the tracking issue).
clarify that realloc refreshes pointer provenance even when the allocation remains in-place
This [matches what C does](https://en.cppreference.com/w/c/memory/realloc):
> The original pointer ptr is invalidated and any access to it is undefined behavior (even if reallocation was in-place).
Cc `@rust-lang/wg-allocators`
`VecDeque::resize` should re-use the buffer in the passed-in element
Today it always copies it for *every* appended element, but one of those clones is avoidable.
This adds `iter::repeat_n` (https://github.com/rust-lang/rust/issues/104434) as the primitive needed to do this. If this PR is acceptable, I'll also use this in `Vec` rather than its custom `ExtendElement` type & infrastructure that is harder to share between multiple different containers:
101e1822c3/library/alloc/src/vec/mod.rs (L2479-L2492)
* Fix doc examples for Platforms with underaligned integer primitives.
* Mutable pointer doc examples use mutable pointers.
* Fill out tracking issue.
* Minor formatting changes.