about summary refs log tree commit diff
path: root/library/alloc/src
AgeCommit message (Collapse)AuthorLines
2024-10-12Stabilize `const_option`Trevor Gross-1/+0
This makes the following API stable in const contexts: impl<T> Option<T> { pub const fn as_mut(&mut self) -> Option<&mut T>; pub const fn expect(self, msg: &str) -> T; pub const fn unwrap(self) -> T; pub const unsafe fn unwrap_unchecked(self) -> T; pub const fn take(&mut self) -> Option<T>; pub const fn replace(&mut self, value: T) -> Option<T>; } impl<T> Option<&T> { pub const fn copied(self) -> Option<T> where T: Copy; } impl<T> Option<&mut T> { pub const fn copied(self) -> Option<T> where T: Copy; } impl<T, E> Option<Result<T, E>> { pub const fn transpose(self) -> Result<Option<T>, E> } impl<T> Option<Option<T>> { pub const fn flatten(self) -> Option<T>; } The following functions make use of the unstable `const_precise_live_drops` feature: - `expect` - `unwrap` - `unwrap_unchecked` - `transpose` - `flatten` Fixes: <https://github.com/rust-lang/rust/issues/67441>
2024-10-12Rollup merge of #131617 - RalfJung:const_cow_is_borrowed, r=tgross35Matthias Krüger-3/+0
remove const_cow_is_borrowed feature gate The two functions guarded by this are still unstable, and there's no reason to require a separate feature gate for their const-ness -- we can just have `cow_is_borrowed` cover both kinds of stability. Cc #65143
2024-10-12remove const_cow_is_borrowed feature gateRalf Jung-3/+0
2024-10-12library: Stabilize `const_ptr_write`Jubilee Young-1/+0
Const-stabilizes: - `write` - `write_bytes` - `write_unaligned` In the following paths: - `core::ptr` - `core::ptr::NonNull` - pointer `<*mut T>` Const-stabilizes the internal `core::intrinsics`: - `write_bytes` - `write_via_move`
2024-10-11Rollup merge of #131065 - Voultapher:port-sort-test-suite, r=thomccTrevor Gross-383/+10
Port sort-research-rs test suite to Rust stdlib tests This PR is a followup to https://github.com/rust-lang/rust/pull/124032. It replaces the tests that test the various sort functions in the standard library with a test-suite developed as part of https://github.com/Voultapher/sort-research-rs. The current tests suffer a couple of problems: - They don't cover important real world patterns that the implementations take advantage of and execute special code for. - The input lengths tested miss out on code paths. For example, important safety property tests never reach the quicksort part of the implementation. - The miri side is often limited to `len <= 20` which means it very thoroughly tests the insertion sort, which accounts for 19 out of 1.5k LoC. - They are split into to core and alloc, causing code duplication and uneven coverage. - ~~The randomness is tied to a caller location, wasting the space exploration capabilities of randomized testing.~~ The randomness is not repeatable, as it relies on `std::hash::RandomState::new().build_hasher()`. Most of these issues existed before https://github.com/rust-lang/rust/pull/124032, but they are intensified by it. One thing that is new and requires additional testing, is that the new sort implementations specialize based on type properties. For example `Freeze` and non `Freeze` execute different code paths. Effectively there are three dimensions that matter: - Input type - Input length - Input pattern The ported test-suite tests various properties along all three dimensions, greatly improving test coverage. It side-steps the miri issue by preferring sampled approaches. For example the test that checks if after a panic the set of elements is still the original one, doesn't do so for every single possible panic opportunity but rather it picks one at random, and performs this test across a range of input length, which varies the panic point across them. This allows regular execution to easily test inputs of length 10k, and miri execution up to 100 which covers significantly more code. The randomness used is tied to a fixed - but random per process execution - seed. This allows for fully repeatable tests and fuzzer like exploration across multiple runs. Structure wise, the tests are previously found in the core integration tests for `sort_unstable` and alloc unit tests for `sort`. The new test-suite was developed to be a purely black-box approach, which makes integration testing the better place, because it can't accidentally rely on internal access. Because unwinding support is required the tests can't be in core, even if the implementation is, so they are now part of the alloc integration tests. Are there architectures that can only build and test core and not alloc? If so, do such platforms require sort testing? For what it's worth the current implementation state passes miri `--target mips64-unknown-linux-gnuabi64` which is big endian. The test-suite also contains tests for properties that were and are given by the current and previous implementations, and likely relied upon by users but weren't tested. For example `self_cmp` tests that the two parameters `a` and `b` passed into the comparison function are never references to the same object, which if the user is sorting for example a `&mut [Mutex<i32>]` could lead to a deadlock. Instead of using the hashed caller location as rand seed, it uses seconds since unix epoch / 10, which given timestamps in the CI should be reasonably easy to reproduce, but also allows fuzzer like space exploration. --- Test run-time changes: Setup: ``` Linux 6.10 rustc 1.83.0-nightly (f79a912d9 2024-09-18) AMD Ryzen 9 5900X 12-Core Processor (Zen 3 micro-architecture) CPU boost enabled. ``` master: e9df22f Before core integration tests: ``` $ LD_LIBRARY_PATH=build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/ hyperfine build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/coretests-219cbd0308a49e2f Time (mean ± σ): 869.6 ms ± 21.1 ms [User: 1327.6 ms, System: 95.1 ms] Range (min … max): 845.4 ms … 917.0 ms 10 runs # MIRIFLAGS="-Zmiri-disable-isolation" to get real time $ MIRIFLAGS="-Zmiri-disable-isolation" ./x.py miri library/core finished in 738.44s ``` After core integration tests: ``` $ LD_LIBRARY_PATH=build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/ hyperfine build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/coretests-219cbd0308a49e2f Time (mean ± σ): 865.1 ms ± 14.7 ms [User: 1283.5 ms, System: 88.4 ms] Range (min … max): 836.2 ms … 885.7 ms 10 runs $ MIRIFLAGS="-Zmiri-disable-isolation" ./x.py miri library/core finished in 752.35s ``` Before alloc unit tests: ``` LD_LIBRARY_PATH=build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/ hyperfine build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/alloc-19c15e6e8565aa54 Time (mean ± σ): 295.0 ms ± 9.9 ms [User: 719.6 ms, System: 35.3 ms] Range (min … max): 284.9 ms … 319.3 ms 10 runs $ MIRIFLAGS="-Zmiri-disable-isolation" ./x.py miri library/alloc finished in 322.75s ``` After alloc unit tests: ``` LD_LIBRARY_PATH=build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/ hyperfine build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/alloc-19c15e6e8565aa54 Time (mean ± σ): 97.4 ms ± 4.1 ms [User: 297.7 ms, System: 28.6 ms] Range (min … max): 92.3 ms … 109.2 ms 27 runs $ MIRIFLAGS="-Zmiri-disable-isolation" ./x.py miri library/alloc finished in 309.18s ``` Before alloc integration tests: ``` $ LD_LIBRARY_PATH=build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/ hyperfine build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/alloctests-439e7300c61a8046 Time (mean ± σ): 103.2 ms ± 1.7 ms [User: 135.7 ms, System: 39.4 ms] Range (min … max): 99.7 ms … 107.3 ms 28 runs $ MIRIFLAGS="-Zmiri-disable-isolation" ./x.py miri library/alloc finished in 231.35s ``` After alloc integration tests: ``` $ LD_LIBRARY_PATH=build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/ hyperfine build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/alloctests-439e7300c61a8046 Time (mean ± σ): 379.8 ms ± 4.7 ms [User: 4620.5 ms, System: 1157.2 ms] Range (min … max): 373.6 ms … 386.9 ms 10 runs $ MIRIFLAGS="-Zmiri-disable-isolation" ./x.py miri library/alloc finished in 449.24s ``` In my opinion the results don't change iterative library development or CI execution in meaningful ways. For example currently the library doc-tests take ~66s and incremental compilation takes 10+ seconds. However I only have limited knowledge of the various local development workflows that exist, and might be missing one that is significantly impacted by this change.
2024-10-11rename RcBox in other places tooJonathan Dönszelmann-4/+4
2024-10-11rename RcBox to RcInner for consistencyJonathan Dönszelmann-67/+71
2024-10-10allocate before calling T::default in <Arc<T>>::default()Joshua Wong-1/+8
Same rationale as in the previous commit.
2024-10-10allocate before calling T::default in <Box<T>>::default()Joshua Wong-1/+1
The `Box<T: Default>` impl currently calls `T::default()` before allocating the `Box`. Most `Default` impls are trivial, which should in theory allow LLVM to construct `T: Default` directly in the `Box` allocation when calling `<Box<T>>::default()`. However, the allocation may fail, which necessitates calling `T's` destructor if it has one. If the destructor is non-trivial, then LLVM has a hard time proving that it's sound to elide, which makes it construct `T` on the stack first, and then copy it into the allocation. Create an uninit `Box` first, and then write `T::default` into it, so that LLVM now only needs to prove that the `T::default` can't panic, which should be trivial for most `Default` impls.
2024-10-07Rollup merge of #128399 - mammothbane:master, r=Amanieu,tgross35Stuart Cook-30/+76
liballoc: introduce String, Vec const-slicing This change `const`-qualifies many methods on `Vec` and `String`, notably `as_slice`, `as_str`, `len`. These changes are made behind the unstable feature flag `const_vec_string_slice`. ## Motivation This is to support simultaneous variance over ownership and constness. I have an enum type that may contain either `String` or `&str`, and I want to produce a `&str` from it in a possibly-`const` context. ```rust enum StrOrString<'s> { Str(&'s str), String(String), } impl<'s> StrOrString<'s> { const fn as_str(&self) -> &str { match self { // In a const-context, I really only expect to see this variant, but I can't switch the implementation // in some mode like #[cfg(const)] -- there has to be a single body Self::Str(s) => s, // so this is a problem, since it's not `const` Self::String(s) => s.as_str(), } } } ``` Currently `String` and `Vec` don't support this, but can without functional changes. Similar logic applies for `len`, `capacity`, `is_empty`. ## Changes The essential thing enabling this change is that `Unique::as_ptr` is `const`. This lets us convert `RawVec::ptr` -> `Vec::as_ptr` -> `Vec::as_slice` -> `String::as_str`. I had to move the `Deref` implementations into `as_{str,slice}` because `Deref` isn't `#[const_trait]`, but I would expect this change to be invisible up to inlining. I moved the `DerefMut` implementations as well for uniformity.
2024-10-06liballoc: introduce String, Vec const-slicingNathan Perry-30/+76
This change `const`-qualifies many methods on Vec and String, notably `as_slice`, `as_str`, `len`. These changes are made behind the unstable feature flag `const_vec_string_slice` with the following tracking issue: https://github.com/rust-lang/rust/issues/129041
2024-10-03Avoid emptiness check in `PeekMut::pop`EFanZh-1/+4
2024-10-01Implemented FromStr for CString and TryFrom<CString> for StringYoh Deadfall-1/+25
2024-09-30Rollup merge of #130914 - compiler-errors:insignificant-dtor, r=AmanieuTrevor Gross-0/+3
Mark some more types as having insignificant dtor These were caught by https://github.com/rust-lang/rust/pull/129864#issuecomment-2376658407, which is implementing a lint for some changes in drop order for temporaries in tail expressions. Specifically, the destructors of `CString` and the bitpacked repr for `std::io::Error` are insignificant insofar as they don't have side-effects on things like locking or synchronization; they just free memory. See some discussion on #89144 for what makes a drop impl "significant"
2024-09-30Port sort-research-rs test suite Rust stdlib testsLukas Bergdoll-383/+10
This commit is a followup to https://github.com/rust-lang/rust/pull/124032. It replaces the tests that test the various sort functions in the standard library with a test-suite developed as part of https://github.com/Voultapher/sort-research-rs. The current tests suffer a couple of problems: - They don't cover important real world patterns that the implementations take advantage of and execute special code for. - The input lengths tested miss out on code paths. For example, important safety property tests never reach the quicksort part of the implementation. - The miri side is often limited to `len <= 20` which means it very thoroughly tests the insertion sort, which accounts for 19 out of 1.5k LoC. - They are split into to core and alloc, causing code duplication and uneven coverage. - The randomness is not repeatable, as it relies on `std::hash::RandomState::new().build_hasher()`. Most of these issues existed before https://github.com/rust-lang/rust/pull/124032, but they are intensified by it. One thing that is new and requires additional testing, is that the new sort implementations specialize based on type properties. For example `Freeze` and non `Freeze` execute different code paths. Effectively there are three dimensions that matter: - Input type - Input length - Input pattern The ported test-suite tests various properties along all three dimensions, greatly improving test coverage. It side-steps the miri issue by preferring sampled approaches. For example the test that checks if after a panic the set of elements is still the original one, doesn't do so for every single possible panic opportunity but rather it picks one at random, and performs this test across a range of input length, which varies the panic point across them. This allows regular execution to easily test inputs of length 10k, and miri execution up to 100 which covers significantly more code. The randomness used is tied to a fixed - but random per process execution - seed. This allows for fully repeatable tests and fuzzer like exploration across multiple runs. Structure wise, the tests are previously found in the core integration tests for `sort_unstable` and alloc unit tests for `sort`. The new test-suite was developed to be a purely black-box approach, which makes integration testing the better place, because it can't accidentally rely on internal access. Because unwinding support is required the tests can't be in core, even if the implementation is, so they are now part of the alloc integration tests. Are there architectures that can only build and test core and not alloc? If so, do such platforms require sort testing? For what it's worth the current implementation state passes miri `--target mips64-unknown-linux-gnuabi64` which is big endian. The test-suite also contains tests for properties that were and are given by the current and previous implementations, and likely relied upon by users but weren't tested. For example `self_cmp` tests that the two parameters `a` and `b` passed into the comparison function are never references to the same object, which if the user is sorting for example a `&mut [Mutex<i32>]` could lead to a deadlock. Instead of using the hashed caller location as rand seed, it uses seconds since unix epoch / 10, which given timestamps in the CI should be reasonably easy to reproduce, but also allows fuzzer like space exploration.
2024-09-29Rollup merge of #130416 - BatmanAoD:130122-sort-by-docs, r=Mark-SimulacrumGuillaume Gomez-20/+47
resolve #130122: reword 'sort-by' edge-conditions documentation See #130122 for rationale & preliminary discussion.
2024-09-28Auto merge of #123778 - jhorstmann:optimize-upper-lower-auto-vectorization, ↵bors-52/+77
r=the8472 Improve autovectorization of to_lowercase / to_uppercase functions Refactor the code in the `convert_while_ascii` helper function to make it more suitable for auto-vectorization and also process the full ascii prefix of the string. The generic case conversion logic will only be invoked starting from the first non-ascii character. The runtime on a microbenchmark with a small ascii-only input decreases from ~55ns to ~18ns per iteration. The new implementation also reduces the amount of unsafe code and encapsulates all unsafe inside the helper function. Fixes #123712
2024-09-27Mark some more smart pointers as insignificantMichael Goulet-0/+2
2024-09-27Mark some more types as having insignificant dtorMichael Goulet-0/+1
2024-09-25Use `&raw` in the standard libraryJosh Stone-39/+35
Since the stabilization in #127679 has reached stage0, 1.82-beta, we can start using `&raw` freely, and even the soft-deprecated `ptr::addr_of!` and `ptr::addr_of_mut!` can stop allowing the unstable feature. I intentionally did not change any documentation or tests, but the rest of those macro uses are all now using `&raw const` or `&raw mut` in the standard library.
2024-09-23Add fast path for ascii to ascii in str::replaceLaiho-2/+30
2024-09-23Improve autovectorization of to_lowercase / to_uppercase functionsJörn Horstmann-52/+77
Refactor the code in the `convert_while_ascii` helper function to make it more suitable for auto-vectorization and also process the full ascii prefix of the string. The generic case conversion logic will only be invoked starting from the first non-ascii character. The runtime on microbenchmarks with ascii-only inputs improves between 1.5x for short and 4x for long inputs on x86_64 and aarch64. The new implementation also encapsulates all unsafe inside the `convert_while_ascii` function. Fixes #123712
2024-09-23Rollup merge of #129550 - kornelski:boxasstr, r=joshtriplett,dtolnayMatthias Krüger-0/+5
Add str.as_str() for easy Deref to string slices Working with `Box<str>` is cumbersome, because in places like `iter.filter()` it can end up being `&Box<str>` or even `&&Box<str>`, and such type doesn't always get auto-dereferenced as expected. Dereferencing such box to `&str` requires ugly syntax like `&**boxed_str` or `&***boxed_str`, with the exact amount of `*`s. `Box<str>` is [not easily comparable with other string types](https://github.com/rust-lang/rust/pull/129852) via `PartialEq`. `Box<str>` won't work for lookups in types like `HashSet<String>`, because `Borrow<String>` won't take types like `&Box<str>`. OTOH `set.contains(s.as_str())` works nicely regardless of levels of indirection. `String` has a simple solution for this: the `as_str()` method, and `Box<str>` should too.
2024-09-22Reformat using the new identifier sorting from rustfmtMichael Goulet-74/+68
2024-09-22reword edge-conditions documentation on all slice 'sort' functions; resolves ↵Kyle J Strand-20/+47
#130122
2024-09-21Rollup merge of #130408 - okaneco:into_lossy_refactor, r=NoratriebMichael Goulet-1/+25
Avoid re-validating UTF-8 in `FromUtf8Error::into_utf8_lossy` Part of the unstable feature `string_from_utf8_lossy_owned` - #129436 Refactor `FromUtf8Error::into_utf8_lossy` to copy valid UTF-8 bytes into the buffer, avoiding double validation of bytes. Add tests that mirror the `String::from_utf8_lossy` tests.
2024-09-20Avoid re-validating UTF-8 in `FromUtf8Error::into_utf8_lossy`okaneco-1/+25
Refactor `into_utf8_lossy` to copy valid UTF-8 bytes into the buffer, avoiding double validation of bytes. Add tests that mirror the `String::from_utf8_lossy` tests
2024-09-20Auto merge of #130631 - GuillaumeGomez:rollup-jpgy1iv, r=GuillaumeGomezbors-2/+69
Rollup of 7 pull requests Successful merges: - #128209 (Remove macOS 10.10 dynamic linker bug workaround) - #130526 (Begin experimental support for pin reborrowing) - #130611 (Address diagnostics regression for `const_char_encode_utf8`.) - #130614 (Add arm64e-apple-tvos target) - #130617 (bail if there are too many non-region infer vars in the query response) - #130619 (Fix scraped examples height) - #130624 (Add `Vec::as_non_null`) r? `@ghost` `@rustbot` modify labels: rollup
2024-09-20Auto merge of #124895 - obeis:static-mut-hidden-ref, r=compiler-errorsbors-0/+6
Disallow hidden references to mutable static Closes #123060 Tracking: - https://github.com/rust-lang/rust/issues/123758
2024-09-20Add `Vec::as_non_null`Tim (Theemathas) Chirananthavat-2/+69
2024-09-20Add `#[track_caller]` to allocating methods of `Vec` & `VecDeque`Pavel Grigorenko-0/+105
2024-09-19Rollup merge of #130553 - GnomedDev:remove-clippy-paths, r=compiler-errorsMatthias Krüger-0/+17
[Clippy] Get rid of most `std` `match_def_path` usage, swap to diagnostic items. Part of https://github.com/rust-lang/rust-clippy/issues/5393. This was going to remove all `std` paths, but `SeekFrom` has issues being cleanly replaced with a diagnostic item as the paths are for variants, which currently cannot be diagnostic items. This also, as a last step, categories the paths to help with future path removals.
2024-09-19Add str.as_str() for easy dereferencing of Box<str>Kornel-0/+5
2024-09-19[Clippy] Swap `unnecessary_owned_empty_strings` to use diagnostic item ↵GnomedDev-0/+1
instead of path
2024-09-19[Clippy] Swap `unnecessary_to_owned` to use diagnostic item instead of pathGnomedDev-0/+1
2024-09-19[Clippy] Swap `manual_while_let_some` to use diagnostic items instead of pathsGnomedDev-0/+2
2024-09-19[Clippy] Swap `repeat_vec_with_capacity` to use diagnostic item instead of pathGnomedDev-0/+1
2024-09-19[Clippy] Swap `VecArgs::hir` to use diagnostic items instead of pathsGnomedDev-0/+3
2024-09-19[Clippy] Swap `single_char_add_str`/`format_push_string` to use diagnostic ↵GnomedDev-0/+2
items instead of paths
2024-09-19[Clippy] Swap `option_as_ref_deref` to use diagnostic items instead of pathsGnomedDev-0/+5
2024-09-19[Clippy] Swap `map_entry` to use diagnostic items instead of pathsGnomedDev-0/+2
2024-09-18remove feature attributes as const_maybe_uninit_as_mut_ptr is stabilizedultrabear-1/+0
2024-09-18Rollup merge of #130522 - GnomedDev:clippy-manual-retain-paths, ↵Jubilee-0/+3
r=compiler-errors [Clippy] Swap `manual_retain` to use diagnostic items instead of paths Part of https://github.com/rust-lang/rust-clippy/issues/5393, just a chore.
2024-09-18[Clippy] Swap `manual_retain` to use diagnostic items instead of pathsGnomedDev-0/+3
2024-09-17read_volatile __rust_no_alloc_shim_is_unstable in alloc_zeroedBen Kimock-1/+7
2024-09-17Rollup merge of #129674 - matthewpipie:rc-arc-new-cyclic-in, r=dtolnayMatthias Krüger-84/+172
Add new_cyclic_in for Rc and Arc Currently, new_cyclic_in does not exist for Rc and Arc. This is an oversight according to https://github.com/rust-lang/wg-allocators/issues/132. This PR adds new_cyclic_in for Rc and Arc. The implementation is almost the exact same as new_cyclic with some small differences to make it allocator-specific. new_cyclic's implementation has been replaced with a call to `new_cyclic_in(data_fn, Global)`. Remaining questions: * ~~Is requiring Allocator to be Clone OK? According to https://github.com/rust-lang/wg-allocators/issues/88, Allocators should be cheap to clone. I'm just hesitant to add unnecessary constraints, though I don't see an obvious workaround for this function since many called functions in new_cyclic_in expect an owned Allocator. I see Allocator.by_ref() as an option, but that doesn't work on when creating Weak { ptr: init_ptr, alloc: alloc.clone() }, because the type of Weak then becomes Weak<T, &A> which is incompatible.~~ Fixed, thank you `@zakarumych!` This PR no longer requires the allocator to be Clone. * Currently, new_cyclic_in's documentation is almost entirely copy-pasted from new_cyclic, with minor tweaks to make it more accurate (e.g. Rc<T> -> Rc<T, A>). The example section is removed to mitigate redundancy and instead redirects to cyclic_in. Is this appropriate? * ~~The comments in new_cyclic_in (and much of the implementation) are also copy-pasted from new_cyclic. Would it be better to make a helper method new_cyclic_in_internal that both functions call, with either Global or the custom allocator? I'm not sure if that's even possible, since the internal method would have to return Arc<T, Global> and I don't know if it's possible to "downcast" that to an Arc<T>. Maybe transmute would work here?~~ Done, thanks `@zakarumych` * Arc::new_cyclic is #[inline], but Rc::new_cyclic is not. Which is preferred? * nit: does it matter where in the impl block new_cyclic_in is defined?
2024-09-16Update library/alloc/src/sync.rsmatthewpipie-1/+1
Co-authored-by: David Tolnay <dtolnay@gmail.com>
2024-09-15Rollup merge of #129439 - okaneco:vec_string_lossy, r=NoratriebMatthias Krüger-0/+74
Implement feature `string_from_utf8_lossy_owned` for lossy conversion from `Vec<u8>` to `String` methods Accepted ACP: https://github.com/rust-lang/libs-team/issues/116 Tracking issue: #129436 Implement feature for lossily converting from `Vec<u8>` to `String` - Add `String::from_utf8_lossy_owned` - Add `FromUtf8Error::into_utf8_lossy` --- Related to #64727, but unsure whether to mark it "fixed" by this PR. That issue partly asks for in-place replacement of the original allocation. We fulfill the other half of that request with these functions. closes #64727
2024-09-15Rollup merge of #129195 - RalfJung:const-mut-refs, r=fee1-deadMatthias Krüger-2/+2
Stabilize `&mut` (and `*mut`) as well as `&Cell` (and `*const Cell`) in const This stabilizes `const_mut_refs` and `const_refs_to_cell`. That allows a bunch of new things in const contexts: - Mentioning `&mut` types - Creating `&mut` and `*mut` values - Creating `&T` and `*const T` values where `T` contains interior mutability - Dereferencing `&mut` and `*mut` values (both for reads and writes) The same rules as at runtime apply: mutating immutable data is UB. This includes mutation through pointers derived from shared references; the following is diagnosed with a hard error: ```rust #[allow(invalid_reference_casting)] const _: () = { let mut val = 15; let ptr = &val as *const i32 as *mut i32; unsafe { *ptr = 16; } }; ``` The main limitation that is enforced is that the final value of a const (or non-`mut` static) may not contain `&mut` values nor interior mutable `&` values. This is necessary because the memory those references point to becomes *read-only* when the constant is done computing, so (interior) mutable references to such memory would be pretty dangerous. We take a multi-layered approach here to ensuring no mutable references escape the initializer expression: - A static analysis rejects (interior) mutable references when the referee looks like it may outlive the current MIR body. - To be extra sure, this static check is complemented by a "safety net" of dynamic checks. ("Dynamic" in the sense of "running during/after const-evaluation, e.g. at runtime of this code" -- in contrast to "static" which works entirely by looking at the MIR without evaluating it.) - After the final value is computed, we do a type-driven traversal of the entire value, and if we find any `&mut` or interior-mutable `&` we error out. - However, the type-driven traversal cannot traverse `union` or raw pointers, so there is a second dynamic check where if the final value of the const contains any pointer that was not derived from a shared reference, we complain. This is currently a future-compat lint, but will become an ICE in #128543. On the off-chance that it's actually possible to trigger this lint on stable, I'd prefer if we could make it an ICE before stabilizing const_mut_refs, but it's not a hard blocker. This part of the "safety net" is only active for mutable references since with shared references, it has false positives. Altogether this should prevent people from leaking (interior) mutable references out of the const initializer. While updating the tests I learned that surprisingly, this code gets rejected: ```rust const _: Vec<i32> = { let mut x = Vec::<i32>::new(); //~ ERROR destructor of `Vec<i32>` cannot be evaluated at compile-time let r = &mut x; let y = x; y }; ``` The analysis that rejects destructors in `const` is very conservative when it sees an `&mut` being created to `x`, and then considers `x` to be always live. See [here](https://github.com/rust-lang/rust/issues/65394#issuecomment-541499219) for a longer explanation. `const_precise_live_drops` will solve this, so I consider this problem to be tracked by https://github.com/rust-lang/rust/issues/73255. Cc `@rust-lang/wg-const-eval` `@rust-lang/lang` Cc https://github.com/rust-lang/rust/issues/57349 Cc https://github.com/rust-lang/rust/issues/80384
2024-09-15also stabilize const_refs_to_cellRalf Jung-1/+1