Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

89 lines
2.2 KiB
Rust
Raw Normal View History

alloc_system: don’t assume MIN_ALIGN for small sizes, fix #45955 The GNU C library (glibc) is documented to always allocate with an alignment of at least 8 or 16 bytes, on 32-bit or 64-bit platforms: https://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html This matches our use of `MIN_ALIGN` before this commit. However, even when libc is glibc, the program might be linked with another allocator that redefines the `malloc` symbol and friends. (The `alloc_jemalloc` crate does, in some cases.) So `alloc_system` doesn’t know which allocator it calls, and needs to be conservative in assumptions it makes. The C standard says: https://port70.net/%7Ensz/c/c11/n1570.html#7.22.3 > The pointer returned if the allocation succeeds is suitably aligned > so that it may be assigned to a pointer to any type of object > with a fundamental alignment requirement https://port70.net/~nsz/c/c11/n1570.html#6.2.8p2 > A fundamental alignment is represented by an alignment less than > or equal to the greatest alignment supported by the implementation > in all contexts, which is equal to `_Alignof (max_align_t)`. `_Alignof (max_align_t)` depends on the ABI and doesn’t seem to have a clear definition, but it seems to match our `MIN_ALIGN` in practice. However, the size of objects is rounded up to the next multiple of their alignment (since that size is also the stride used in arrays). Conversely, the alignment of a non-zero-size object is at most its size. So for example it seems ot be legal for `malloc(8)` to return a pointer that’s only 8-bytes-aligned, even if `_Alignof (max_align_t)` is 16.
2017-11-20 15:30:04 +01:00
#![feature(allocator_api)]
2021-12-23 22:03:12 +09:00
#![feature(alloc_layout_extra)]
#![feature(iter_array_chunks)]
#![feature(assert_matches)]
#![feature(btree_extract_if)]
#![feature(cow_is_borrowed)]
2021-12-23 22:03:12 +09:00
#![feature(const_heap)]
#![feature(const_try)]
#![feature(core_intrinsics)]
#![feature(extract_if)]
#![feature(exact_size_is_empty)]
Add regression test for lifetimes in alloc internals autotraits Currently pretty much all of the btree_map and btree_set ones fail, as well as linked_list::DrainFilter. error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:38:5 | 38 | / require_send_sync(async { 39 | | let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>; 40 | | async {}.await; 41 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:56:5 | 56 | / require_send_sync(async { 57 | | let _v = None::< 58 | | alloc::collections::btree_map::DrainFilter< 59 | | '_, ... | 65 | | async {}.await; 66 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:68:5 | 68 | / require_send_sync(async { 69 | | let _v = None::<alloc::collections::btree_map::Entry<'_, &u32, &u32>>; 70 | | async {}.await; 71 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:88:5 | 88 | / require_send_sync(async { 89 | | let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>; 90 | | async {}.await; 91 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:93:5 | 93 | / require_send_sync(async { 94 | | let _v = None::<alloc::collections::btree_map::IterMut<'_, &u32, &u32>>; 95 | | async {}.await; 96 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:98:5 | 98 | / require_send_sync(async { 99 | | let _v = None::<alloc::collections::btree_map::Keys<'_, &u32, &u32>>; 100 | | async {}.await; 101 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:103:5 | 103 | / require_send_sync(async { 104 | | let _v = None::<alloc::collections::btree_map::OccupiedEntry<'_, &u32, &u32>>; 105 | | async {}.await; 106 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:108:5 | 108 | / require_send_sync(async { 109 | | let _v = None::<alloc::collections::btree_map::OccupiedError<'_, &u32, &u32>>; 110 | | async {}.await; 111 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:113:5 | 113 | / require_send_sync(async { 114 | | let _v = None::<alloc::collections::btree_map::Range<'_, &u32, &u32>>; 115 | | async {}.await; 116 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:118:5 | 118 | / require_send_sync(async { 119 | | let _v = None::<alloc::collections::btree_map::RangeMut<'_, &u32, &u32>>; 120 | | async {}.await; 121 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:123:5 | 123 | / require_send_sync(async { 124 | | let _v = None::<alloc::collections::btree_map::VacantEntry<'_, &u32, &u32>>; 125 | | async {}.await; 126 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:128:5 | 128 | / require_send_sync(async { 129 | | let _v = None::<alloc::collections::btree_map::Values<'_, &u32, &u32>>; 130 | | async {}.await; 131 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:133:5 | 133 | / require_send_sync(async { 134 | | let _v = None::<alloc::collections::btree_map::ValuesMut<'_, &u32, &u32>>; 135 | | async {}.await; 136 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:146:5 | 146 | / require_send_sync(async { 147 | | let _v = None::<alloc::collections::btree_set::Difference<'_, &u32>>; 148 | | async {}.await; 149 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:151:5 | 151 | / require_send_sync(async { 152 | | let _v = None::<alloc::collections::btree_set::DrainFilter<'_, &u32, fn(&&u32) -> bool>>; 153 | | async {}.await; 154 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:156:5 | 156 | / require_send_sync(async { 157 | | let _v = None::<alloc::collections::btree_set::Intersection<'_, &u32>>; 158 | | async {}.await; 159 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:166:5 | 166 | / require_send_sync(async { 167 | | let _v = None::<alloc::collections::btree_set::Iter<'_, &u32>>; 168 | | async {}.await; 169 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:171:5 | 171 | / require_send_sync(async { 172 | | let _v = None::<alloc::collections::btree_set::Range<'_, &u32>>; 173 | | async {}.await; 174 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:176:5 | 176 | / require_send_sync(async { 177 | | let _v = None::<alloc::collections::btree_set::SymmetricDifference<'_, &u32>>; 178 | | async {}.await; 179 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:181:5 | 181 | / require_send_sync(async { 182 | | let _v = None::<alloc::collections::btree_set::Union<'_, &u32>>; 183 | | async {}.await; 184 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: future cannot be sent between threads safely --> library/alloc/tests/autotraits.rs:243:23 | 243 | require_send_sync(async { | _______________________^ 244 | | let _v = 245 | | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>; 246 | | async {}.await; 247 | | }); | |_____^ future created by async block is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NonNull<std::collections::linked_list::Node<&u32>>` note: future is not `Send` as this value is used across an await --> library/alloc/tests/autotraits.rs:246:17 | 244 | let _v = | -- has type `Option<std::collections::linked_list::DrainFilter<'_, &u32, for<'a, 'b> fn(&'a mut &'b u32) -> bool>>` which is not `Send` 245 | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>; 246 | async {}.await; | ^^^^^^ await occurs here, with `_v` maybe used later 247 | }); | - `_v` is later dropped here note: required by a bound in `require_send_sync` --> library/alloc/tests/autotraits.rs:3:25 | 3 | fn require_send_sync<T: Send + Sync>(_: T) {} | ^^^^ required by this bound in `require_send_sync` error: future cannot be shared between threads safely --> library/alloc/tests/autotraits.rs:243:23 | 243 | require_send_sync(async { | _______________________^ 244 | | let _v = 245 | | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>; 246 | | async {}.await; 247 | | }); | |_____^ future created by async block is not `Sync` | = help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `NonNull<std::collections::linked_list::Node<&u32>>` note: future is not `Sync` as this value is used across an await --> library/alloc/tests/autotraits.rs:246:17 | 244 | let _v = | -- has type `Option<std::collections::linked_list::DrainFilter<'_, &u32, for<'a, 'b> fn(&'a mut &'b u32) -> bool>>` which is not `Sync` 245 | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>; 246 | async {}.await; | ^^^^^^ await occurs here, with `_v` maybe used later 247 | }); | - `_v` is later dropped here note: required by a bound in `require_send_sync` --> library/alloc/tests/autotraits.rs:3:32 | 3 | fn require_send_sync<T: Send + Sync>(_: T) {} | ^^^^ required by this bound in `require_send_sync`
2022-10-05 11:23:14 -07:00
#![feature(linked_list_cursors)]
#![feature(map_try_insert)]
#![feature(pattern)]
2019-06-21 03:52:38 +02:00
#![feature(trusted_len)]
#![feature(try_reserve_kind)]
#![feature(try_with_capacity)]
#![feature(unboxed_closures)]
#![feature(binary_heap_into_iter_sorted)]
#![feature(binary_heap_drain_sorted)]
#![feature(slice_ptr_get)]
#![feature(inplace_iteration)]
#![feature(iter_advance_by)]
#![feature(iter_next_chunk)]
#![feature(round_char_boundary)]
2021-03-15 20:24:35 +01:00
#![feature(slice_partition_dedup)]
#![feature(string_from_utf8_lossy_owned)]
2021-03-05 11:27:58 -05:00
#![feature(string_remove_matches)]
#![feature(const_btree_len)]
2021-07-26 14:04:55 +08:00
#![feature(const_trait_impl)]
#![feature(const_str_from_utf8)]
2022-01-05 22:42:21 +01:00
#![feature(panic_update_hook)]
#![feature(pointer_is_aligned_to)]
2021-10-19 15:23:19 -07:00
#![feature(thin_box)]
#![feature(strict_provenance)]
#![feature(drain_keep_rest)]
#![feature(local_waker)]
2024-03-26 15:54:22 -04:00
#![feature(vec_pop_if)]
2024-05-13 03:16:31 +08:00
#![feature(unique_rc_arc)]
Port sort-research-rs test suite Rust stdlib tests 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-30 10:54:23 +02:00
#![feature(macro_metavar_expr_concat)]
2023-11-22 07:30:09 +01:00
#![allow(internal_features)]
#![deny(fuzzy_provenance_casts)]
#![deny(unsafe_op_in_unsafe_fn)]
2015-07-11 14:34:57 +03:00
use std::hash::{DefaultHasher, Hash, Hasher};
mod arc;
Add regression test for lifetimes in alloc internals autotraits Currently pretty much all of the btree_map and btree_set ones fail, as well as linked_list::DrainFilter. error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:38:5 | 38 | / require_send_sync(async { 39 | | let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>; 40 | | async {}.await; 41 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:56:5 | 56 | / require_send_sync(async { 57 | | let _v = None::< 58 | | alloc::collections::btree_map::DrainFilter< 59 | | '_, ... | 65 | | async {}.await; 66 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:68:5 | 68 | / require_send_sync(async { 69 | | let _v = None::<alloc::collections::btree_map::Entry<'_, &u32, &u32>>; 70 | | async {}.await; 71 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:88:5 | 88 | / require_send_sync(async { 89 | | let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>; 90 | | async {}.await; 91 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:93:5 | 93 | / require_send_sync(async { 94 | | let _v = None::<alloc::collections::btree_map::IterMut<'_, &u32, &u32>>; 95 | | async {}.await; 96 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:98:5 | 98 | / require_send_sync(async { 99 | | let _v = None::<alloc::collections::btree_map::Keys<'_, &u32, &u32>>; 100 | | async {}.await; 101 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:103:5 | 103 | / require_send_sync(async { 104 | | let _v = None::<alloc::collections::btree_map::OccupiedEntry<'_, &u32, &u32>>; 105 | | async {}.await; 106 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:108:5 | 108 | / require_send_sync(async { 109 | | let _v = None::<alloc::collections::btree_map::OccupiedError<'_, &u32, &u32>>; 110 | | async {}.await; 111 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:113:5 | 113 | / require_send_sync(async { 114 | | let _v = None::<alloc::collections::btree_map::Range<'_, &u32, &u32>>; 115 | | async {}.await; 116 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:118:5 | 118 | / require_send_sync(async { 119 | | let _v = None::<alloc::collections::btree_map::RangeMut<'_, &u32, &u32>>; 120 | | async {}.await; 121 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:123:5 | 123 | / require_send_sync(async { 124 | | let _v = None::<alloc::collections::btree_map::VacantEntry<'_, &u32, &u32>>; 125 | | async {}.await; 126 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:128:5 | 128 | / require_send_sync(async { 129 | | let _v = None::<alloc::collections::btree_map::Values<'_, &u32, &u32>>; 130 | | async {}.await; 131 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:133:5 | 133 | / require_send_sync(async { 134 | | let _v = None::<alloc::collections::btree_map::ValuesMut<'_, &u32, &u32>>; 135 | | async {}.await; 136 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:146:5 | 146 | / require_send_sync(async { 147 | | let _v = None::<alloc::collections::btree_set::Difference<'_, &u32>>; 148 | | async {}.await; 149 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: implementation of `Send` is not general enough --> library/alloc/tests/autotraits.rs:151:5 | 151 | / require_send_sync(async { 152 | | let _v = None::<alloc::collections::btree_set::DrainFilter<'_, &u32, fn(&&u32) -> bool>>; 153 | | async {}.await; 154 | | }); | |______^ implementation of `Send` is not general enough | = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:156:5 | 156 | / require_send_sync(async { 157 | | let _v = None::<alloc::collections::btree_set::Intersection<'_, &u32>>; 158 | | async {}.await; 159 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:166:5 | 166 | / require_send_sync(async { 167 | | let _v = None::<alloc::collections::btree_set::Iter<'_, &u32>>; 168 | | async {}.await; 169 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:171:5 | 171 | / require_send_sync(async { 172 | | let _v = None::<alloc::collections::btree_set::Range<'_, &u32>>; 173 | | async {}.await; 174 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:176:5 | 176 | / require_send_sync(async { 177 | | let _v = None::<alloc::collections::btree_set::SymmetricDifference<'_, &u32>>; 178 | | async {}.await; 179 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: higher-ranked lifetime error --> library/alloc/tests/autotraits.rs:181:5 | 181 | / require_send_sync(async { 182 | | let _v = None::<alloc::collections::btree_set::Union<'_, &u32>>; 183 | | async {}.await; 184 | | }); | |______^ | = note: could not prove `impl Future<Output = ()>: Send` error: future cannot be sent between threads safely --> library/alloc/tests/autotraits.rs:243:23 | 243 | require_send_sync(async { | _______________________^ 244 | | let _v = 245 | | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>; 246 | | async {}.await; 247 | | }); | |_____^ future created by async block is not `Send` | = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NonNull<std::collections::linked_list::Node<&u32>>` note: future is not `Send` as this value is used across an await --> library/alloc/tests/autotraits.rs:246:17 | 244 | let _v = | -- has type `Option<std::collections::linked_list::DrainFilter<'_, &u32, for<'a, 'b> fn(&'a mut &'b u32) -> bool>>` which is not `Send` 245 | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>; 246 | async {}.await; | ^^^^^^ await occurs here, with `_v` maybe used later 247 | }); | - `_v` is later dropped here note: required by a bound in `require_send_sync` --> library/alloc/tests/autotraits.rs:3:25 | 3 | fn require_send_sync<T: Send + Sync>(_: T) {} | ^^^^ required by this bound in `require_send_sync` error: future cannot be shared between threads safely --> library/alloc/tests/autotraits.rs:243:23 | 243 | require_send_sync(async { | _______________________^ 244 | | let _v = 245 | | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>; 246 | | async {}.await; 247 | | }); | |_____^ future created by async block is not `Sync` | = help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `NonNull<std::collections::linked_list::Node<&u32>>` note: future is not `Sync` as this value is used across an await --> library/alloc/tests/autotraits.rs:246:17 | 244 | let _v = | -- has type `Option<std::collections::linked_list::DrainFilter<'_, &u32, for<'a, 'b> fn(&'a mut &'b u32) -> bool>>` which is not `Sync` 245 | None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>; 246 | async {}.await; | ^^^^^^ await occurs here, with `_v` maybe used later 247 | }); | - `_v` is later dropped here note: required by a bound in `require_send_sync` --> library/alloc/tests/autotraits.rs:3:32 | 3 | fn require_send_sync<T: Send + Sync>(_: T) {} | ^^^^ required by this bound in `require_send_sync`
2022-10-05 11:23:14 -07:00
mod autotraits;
2020-04-22 14:16:21 -07:00
mod borrow;
mod boxed;
mod btree_set_hash;
mod c_str;
2021-07-26 14:04:55 +08:00
mod const_fns;
mod cow_str;
mod fmt;
alloc_system: don’t assume MIN_ALIGN for small sizes, fix #45955 The GNU C library (glibc) is documented to always allocate with an alignment of at least 8 or 16 bytes, on 32-bit or 64-bit platforms: https://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html This matches our use of `MIN_ALIGN` before this commit. However, even when libc is glibc, the program might be linked with another allocator that redefines the `malloc` symbol and friends. (The `alloc_jemalloc` crate does, in some cases.) So `alloc_system` doesn’t know which allocator it calls, and needs to be conservative in assumptions it makes. The C standard says: https://port70.net/%7Ensz/c/c11/n1570.html#7.22.3 > The pointer returned if the allocation succeeds is suitably aligned > so that it may be assigned to a pointer to any type of object > with a fundamental alignment requirement https://port70.net/~nsz/c/c11/n1570.html#6.2.8p2 > A fundamental alignment is represented by an alignment less than > or equal to the greatest alignment supported by the implementation > in all contexts, which is equal to `_Alignof (max_align_t)`. `_Alignof (max_align_t)` depends on the ABI and doesn’t seem to have a clear definition, but it seems to match our `MIN_ALIGN` in practice. However, the size of objects is rounded up to the next multiple of their alignment (since that size is also the stride used in arrays). Conversely, the alignment of a non-zero-size object is at most its size. So for example it seems ot be legal for `malloc(8)` to return a pointer that’s only 8-bytes-aligned, even if `_Alignof (max_align_t)` is 16.
2017-11-20 15:30:04 +01:00
mod heap;
mod linked_list;
mod rc;
mod slice;
Port sort-research-rs test suite Rust stdlib tests 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-30 10:54:23 +02:00
mod sort;
mod str;
mod string;
mod task;
2021-10-19 15:23:19 -07:00
mod thin_box;
mod vec;
mod vec_deque;
fn hash<T: Hash>(t: &T) -> u64 {
let mut s = DefaultHasher::new();
t.hash(&mut s);
s.finish()
}
// FIXME: Instantiated functions with i128 in the signature is not supported in Emscripten.
// See https://github.com/kripken/emscripten-fastcomp/issues/169
#[cfg(not(target_os = "emscripten"))]
#[test]
fn test_boxed_hasher() {
let ordinary_hash = hash(&5u32);
let mut hasher_1 = Box::new(DefaultHasher::new());
5u32.hash(&mut hasher_1);
assert_eq!(ordinary_hash, hasher_1.finish());
2018-07-13 14:25:22 +09:00
let mut hasher_2 = Box::new(DefaultHasher::new()) as Box<dyn Hasher>;
5u32.hash(&mut hasher_2);
assert_eq!(ordinary_hash, hasher_2.finish());
}