about summary refs log tree commit diff
path: root/library/core/src/alloc
AgeCommit message (Collapse)AuthorLines
2025-08-12Address dangling docSacha Ayoun-4/+4
Signed-off-by: Sacha Ayoun <sachaayoun@gmail.com>
2025-07-04clippy fix: indentationMarijn Schouten-2/+2
2025-05-21Add some track_caller info to precondition panicsBen Kimock-0/+1
2025-04-14Fix some grammar errors and hyperlinks in doc for `trait Allocator`Janggun Lee-2/+4
* "while until either" could also be changed to "for a while until either", but I just deleted "while". * fixed sentence with incorrect "at" and "has/have". * linked [*currently allocated*] similar to other methods.
2025-03-26Pass `Alignment` for `RawVecInner::new_in`James Wainwright-0/+8
Encodes the safety constraint that `Unique`'s pointer must be non-zero into the API.
2025-03-06library: Use size_of from the prelude instead of importedThalia Archibald-2/+2
Use `std::mem::{size_of, size_of_val, align_of, align_of_val}` from the prelude instead of importing or qualifying them. These functions were added to all preludes in Rust 1.80.
2025-02-14core: Apply unsafe_op_in_unsafe_fnEric Huss-1/+1
2025-02-07library: doc: core::alloc::Allocator: trivial typo fixAskar Safin-1/+1
2025-01-29Cleanup docs for AllocatorMarijn Schouten-31/+27
2025-01-10Use `NonNull::without_provenance` within the standard librarySamuel Tardieu-2/+1
This API removes the need for several `unsafe` blocks, and leads to clearer code.
2025-01-08update version placeholdersPietro Albini-5/+5
2024-12-25stabilize const_alloc_layoutRalf Jung-10/+5
2024-12-02stabilize const_{size,align}_of_valRalf Jung-1/+1
2024-11-27update cfgsBoxy-5/+4
2024-11-01make const_alloc_layout feature gate only about functions that are already ↵Ralf Jung-6/+5
stable the rest has their constness guarded by their usual feature gate
2024-10-25Auto merge of #131349 - RalfJung:const-stability-checks, r=compiler-errorsbors-3/+1
Const stability checks v2 The const stability system has served us well ever since `const fn` were first stabilized. It's main feature is that it enforces *recursive* validity -- a stable const fn cannot internally make use of unstable const features without an explicit marker in the form of `#[rustc_allow_const_fn_unstable]`. This is done to make sure that we don't accidentally expose unstable const features on stable in a way that would be hard to take back. As part of this, it is enforced that a `#[rustc_const_stable]` can only call `#[rustc_const_stable]` functions. However, some problems have been coming up with increased usage: - It is baffling that we have to mark private or even unstable functions as `#[rustc_const_stable]` when they are used as helpers in regular stable `const fn`, and often people will rather add `#[rustc_allow_const_fn_unstable]` instead which was not our intention. - The system has several gaping holes: a private `const fn` without stability attributes whose inherited stability (walking up parent modules) is `#[stable]` is allowed to call *arbitrary* unstable const operations, but can itself be called from stable `const fn`. Similarly, `#[allow_internal_unstable]` on a macro completely bypasses the recursive nature of the check. Fundamentally, the problem is that we have *three* disjoint categories of functions, and not enough attributes to distinguish them: 1. const-stable functions 2. private/unstable functions that are meant to be callable from const-stable functions 3. functions that can make use of unstable const features Functions in the first two categories cannot use unstable const features and they can only call functions from the first two categories. This PR implements the following system: - `#[rustc_const_stable]` puts functions in the first category. It may only be applied to `#[stable]` functions. - `#[rustc_const_unstable]` by default puts functions in the third category. The new attribute `#[rustc_const_stable_indirect]` can be added to such a function to move it into the second category. - `const fn` without a const stability marker are in the second category if they are still unstable. They automatically inherit the feature gate for regular calls, it can now also be used for const-calls. Also, all the holes mentioned above have been closed. There's still one potential hole that is hard to avoid, which is when MIR building automatically inserts calls to a particular function in stable functions -- which happens in the panic machinery. Those need to be manually marked `#[rustc_const_stable_indirect]` to be sure they follow recursive const stability. But that's a fairly rare and special case so IMO it's fine. The net effect of this is that a `#[unstable]` or unmarked function can be constified simply by marking it as `const fn`, and it will then be const-callable from stable `const fn` and subject to recursive const stability requirements. If it is publicly reachable (which implies it cannot be unmarked), it will be const-unstable under the same feature gate. Only if the function ever becomes `#[stable]` does it need a `#[rustc_const_unstable]` or `#[rustc_const_stable]` marker to decide if this should also imply const-stability. Adding `#[rustc_const_unstable]` is only needed for (a) functions that need to use unstable const lang features (including intrinsics), or (b) `#[stable]` functions that are not yet intended to be const-stable. Adding `#[rustc_const_stable]` is only needed for functions that are actually meant to be directly callable from stable const code. `#[rustc_const_stable_indirect]` is used to mark intrinsics as const-callable and for `#[rustc_const_unstable]` functions that are actually called from other, exposed-on-stable `const fn`. No other attributes are required. Also see the updated dev-guide at https://github.com/rust-lang/rustc-dev-guide/pull/2098. I think in the future we may want to tweak this further, so that in the hopefully common case where a public function's const-stability just exactly mirrors its regular stability, we never have to add any attribute. But right now, once the function is stable this requires `#[rustc_const_stable]`. ### Open question There is one point I could see we might want to do differently, and that is putting `#[rustc_const_unstable]` functions (but not intrinsics) in category 2 by default, and requiring an extra attribute for `#[rustc_const_not_exposed_on_stable]` or so. This would require a bunch of extra annotations, but would have the advantage that turning a `#[rustc_const_unstable]` into `#[rustc_const_stable]` will never change the way the function is const-checked. Currently, we often discover in the const stabilization PR that a function needs some other unstable const things, and then we rush to quickly deal with that. In this alternative universe, we'd work towards getting rid of the `rustc_const_not_exposed_on_stable` before stabilization, and once that is done stabilization becomes a trivial matter. `#[rustc_const_stable_indirect]` would then only be used for intrinsics. I think I like this idea, but might want to do it in a follow-up PR, as it will need a whole bunch of annotations in the standard library. Also, we probably want to convert all const intrinsics to the "new" form (`#[rustc_intrinsic]` instead of an `extern` block) before doing this to avoid having to deal with two different ways of declaring intrinsics. Cc `@rust-lang/wg-const-eval` `@rust-lang/libs-api` Part of https://github.com/rust-lang/rust/issues/129815 (but not finished since this is not yet sufficient to safely let us expose `const fn` from hashbrown) Fixes https://github.com/rust-lang/rust/issues/131073 by making it so that const-stable functions are always stable try-job: test-various
2024-10-25Re-do recursive const stability checksRalf Jung-3/+1
Fundamentally, we have *three* disjoint categories of functions: 1. const-stable functions 2. private/unstable functions that are meant to be callable from const-stable functions 3. functions that can make use of unstable const features This PR implements the following system: - `#[rustc_const_stable]` puts functions in the first category. It may only be applied to `#[stable]` functions. - `#[rustc_const_unstable]` by default puts functions in the third category. The new attribute `#[rustc_const_stable_indirect]` can be added to such a function to move it into the second category. - `const fn` without a const stability marker are in the second category if they are still unstable. They automatically inherit the feature gate for regular calls, it can now also be used for const-calls. Also, several holes in recursive const stability checking are being closed. There's still one potential hole that is hard to avoid, which is when MIR building automatically inserts calls to a particular function in stable functions -- which happens in the panic machinery. Those need to *not* be `rustc_const_unstable` (or manually get a `rustc_const_stable_indirect`) to be sure they follow recursive const stability. But that's a fairly rare and special case so IMO it's fine. The net effect of this is that a `#[unstable]` or unmarked function can be constified simply by marking it as `const fn`, and it will then be const-callable from stable `const fn` and subject to recursive const stability requirements. If it is publicly reachable (which implies it cannot be unmarked), it will be const-unstable under the same feature gate. Only if the function ever becomes `#[stable]` does it need a `#[rustc_const_unstable]` or `#[rustc_const_stable]` marker to decide if this should also imply const-stability. Adding `#[rustc_const_unstable]` is only needed for (a) functions that need to use unstable const lang features (including intrinsics), or (b) `#[stable]` functions that are not yet intended to be const-stable. Adding `#[rustc_const_stable]` is only needed for functions that are actually meant to be directly callable from stable const code. `#[rustc_const_stable_indirect]` is used to mark intrinsics as const-callable and for `#[rustc_const_unstable]` functions that are actually called from other, exposed-on-stable `const fn`. No other attributes are required.
2024-10-25library: consistently use American spelling for 'behavior'Ralf Jung-2/+2
2024-10-10Fixing rustDoc for LayoutError.Johnathan W-1/+2
2024-09-29Rollup merge of #123932 - adamse:global-alloc-safety-preconds-positive, ↵Matthias Krüger-15/+17
r=tgross35 restate GlobalAlloc method safety preconditions in terms of what the caller has to do for greater clarity
2024-09-17Take more advantage of the `isize::MAX` limit in `Layout`Scott McMurray-56/+105
Things like `padding_needed_for` are current implemented being super careful to handle things like `Layout::size` potentially being `usize::MAX`. But now that 95295 has happened, that's no longer a concern. It's possible to add two `Layout::size`s together without risking overflow now. So take advantage of that to remove a bunch of checked math that's not actually needed. For example, the round-up-and-add-next-size in `extend` doesn't need any overflow checks at all, just the final check for compatibility with the alignment. (And while I was doing that I made it all unstably const, because there's nothing in `Layout` that's fundamentally runtime-only.)
2024-09-07restate GlobalAlloc method safety preconditions in terms of what the caller ↵Adam Sandberg Ericsson-15/+17
has to do for greater clarity
2024-08-20Try to golf down the amount of code in LayoutBen Kimock-8/+3
2024-08-19Add a precondition check for Layout::from_size_align_uncheckedBen Kimock-5/+27
2024-07-29Reformat `use` declarations.Nicholas Nethercote-7/+2
The previous commit updated `rustfmt.toml` appropriately. This commit is the outcome of running `x fmt --all` with the new formatting options.
2024-07-26Fix doc nitsJohn Arundel-6/+6
Many tiny changes to stdlib doc comments to make them consistent (for example "Returns foo", rather than "Return foo", per RFC1574), adding missing periods, paragraph breaks, backticks for monospace style, and other minor nits. https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text
2024-07-10size_of_val_raw: for length 0 this is safe to callRalf Jung-0/+2
2024-03-25alloc::Layout: explicitly document size invariant on the type levelRalf Jung-1/+3
2024-03-19SeqCst->Relaxed in doc examples.Mara Bos-6/+3
SeqCst is unnecessary here.
2024-02-21rename ptr::invalid -> ptr::without_provenanceRalf Jung-1/+1
also introduce ptr::dangling matching NonNull::dangling
2024-02-13Add information about allocation lifetime to Allocator::allocateAmanieu d'Antras-0/+4
2024-02-12Clarify the lifetimes of allocations returned by the `Allocator` traitAmanieu d'Antras-2/+4
The previous definition (accidentally) disallowed the implementation of stack-based allocators whose memory would become invalid once the lifetime of the allocator type ended. This also ensures the validity of the following blanket implementation: ```rust impl<A: Allocator> Allocator for &'_ A {} ```
2024-01-13libs: use `assert_unchecked` instead of intrinsicjoboet-1/+1
2023-11-23Indicate that multiplication in Layout::array cannot overflowMark Rousskov-1/+5
This allows LLVM to optimize comparisons to zero before & after the multiplication into one, saving on code size and eliminating an (always true) branch from most Vec allocations.
2023-10-12Update library/core/src/alloc/layout.rsJoshua Liebow-Feeser-1/+1
Co-authored-by: David Tolnay <dtolnay@gmail.com>
2023-09-07Guarantee that Layout::align returns a non-zero power of twoJoshua Liebow-Feeser-0/+2
2023-05-30Rollup merge of #107916 - reez12g:issue-107040, r=AmanieuNilstrieb-2/+3
fix comment on Allocator trait fixes https://github.com/rust-lang/rust/issues/107040
2023-05-30fix comment on Allocator traitreez12g-2/+3
2023-05-27Rollup merge of #108630 - overlookmotel:realloc-docs-fix, r=AmanieuMatthias Krüger-1/+2
Fix docs for `alloc::realloc` Fixes #108546. Corrects the docs for `alloc::realloc` to bring the safety constraints into line with `Layout::from_size_align_unchecked`'s constraints.
2023-04-16core is now compilableDeadbeef-10/+5
2023-04-16rm const traits in libcoreDeadbeef-1/+0
2023-03-26Auto merge of #105096 - LegionMammal978:copied-allocators, r=Amanieubors-3/+3
Clarify that copied allocators must behave the same Currently, the safety documentation for `Allocator` says that a cloned or moved allocator must behave the same as the original. However, it does not specify that a copied allocator must behave the same, and it's possible to construct an allocator that permits being moved or cloned, but sometimes produces a new allocator when copied. <details> <summary>Contrived example which results in a Miri error</summary> ```rust #![feature(allocator_api, once_cell, strict_provenance)] use std::{ alloc::{AllocError, Allocator, Global, Layout}, collections::HashMap, hint, marker::PhantomPinned, num::NonZeroUsize, pin::Pin, ptr::{addr_of, NonNull}, sync::{LazyLock, Mutex}, }; mod source_allocator { use super::*; // `SourceAllocator` has 3 states: // - invalid value: is_cloned == false, source != self.addr() // - source value: is_cloned == false, source == self.addr() // - cloned value: is_cloned == true pub struct SourceAllocator { is_cloned: bool, source: usize, _pin: PhantomPinned, } impl SourceAllocator { // Returns a pinned source value (pointing to itself). pub fn new_source() -> Pin<Box<Self>> { let mut b = Box::new(Self { is_cloned: false, source: 0, _pin: PhantomPinned, }); b.source = b.addr(); Box::into_pin(b) } fn addr(&self) -> usize { addr_of!(*self).addr() } // Invalid values point to source 0. // Source values point to themselves. // Cloned values point to their corresponding source. fn source(&self) -> usize { if self.is_cloned || self.addr() == self.source { self.source } else { 0 } } } // Copying an invalid value produces an invalid value. // Copying a source value produces an invalid value. // Copying a cloned value produces a cloned value with the same source. impl Copy for SourceAllocator {} // Cloning an invalid value produces an invalid value. // Cloning a source value produces a cloned value with that source. // Cloning a cloned value produces a cloned value with the same source. impl Clone for SourceAllocator { fn clone(&self) -> Self { if self.is_cloned || self.addr() != self.source { *self } else { Self { is_cloned: true, source: self.source, _pin: PhantomPinned, } } } } static SOURCE_MAP: LazyLock<Mutex<HashMap<NonZeroUsize, usize>>> = LazyLock::new(Default::default); // SAFETY: Wraps `Global`'s methods with additional tracking. // All invalid values share blocks with each other. // Each source value shares blocks with all cloned values pointing to it. // Cloning an allocator always produces a compatible allocator: // - Cloning an invalid value produces another invalid value. // - Cloning a source value produces a cloned value pointing to it. // - Cloning a cloned value produces another cloned value with the same source. // Moving an allocator always produces a compatible allocator: // - Invalid values remain invalid when moved. // - Source values cannot be moved, since they are always pinned to the heap. // - Cloned values keep the same source when moved. unsafe impl Allocator for SourceAllocator { fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { let mut map = SOURCE_MAP.lock().unwrap(); let block = Global.allocate(layout)?; let block_addr = block.cast::<u8>().addr(); map.insert(block_addr, self.source()); Ok(block) } unsafe fn deallocate(&self, block: NonNull<u8>, layout: Layout) { let mut map = SOURCE_MAP.lock().unwrap(); let block_addr = block.addr(); // SAFETY: `block` came from an allocator that shares blocks with this allocator. if map.remove(&block_addr) != Some(self.source()) { hint::unreachable_unchecked() } Global.deallocate(block, layout) } } } use source_allocator::SourceAllocator; // SAFETY: `alloc1` and `alloc2` must share blocks. unsafe fn test_same(alloc1: &SourceAllocator, alloc2: &SourceAllocator) { let ptr = alloc1.allocate(Layout::new::<i32>()).unwrap(); alloc2.deallocate(ptr.cast(), Layout::new::<i32>()); } fn main() { let orig = &*SourceAllocator::new_source(); let orig_cloned1 = &orig.clone(); let orig_cloned2 = &orig.clone(); let copied = &{ *orig }; let copied_cloned1 = &copied.clone(); let copied_cloned2 = &copied.clone(); unsafe { test_same(orig, orig_cloned1); test_same(orig_cloned1, orig_cloned2); test_same(copied, copied_cloned1); test_same(copied_cloned1, copied_cloned2); test_same(orig, copied); // error } } ``` </details> This could result in issues in the future for algorithms that specialize on `Copy` types. Right now, nothing in the standard library that depends on `Allocator + Clone` is susceptible to this issue, but I still think it would make sense to specify that copying an allocator is always as valid as cloning it.
2023-03-01Fix docs for `alloc::realloc`overlookmotel-1/+2
Fixes #108546
2023-02-09Clarify `new_size` for realloc means bytesJubilee-4/+5
2022-11-30Clarify that copied allocators must behave the sameLegionMammal978-3/+3
2022-11-22Rollup merge of #102207 - CraftSpider:const-layout, r=scottmcmManish Goregaokar-11/+25
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
2022-11-20Use ? instead of matchRune Tynan-4/+2
2022-11-20Update with derive_constRune Tynan-1/+4
2022-11-20constify remaining layout methodsRune Tynan-10/+23
Remove bad impl for Eq Update Cargo.lock and fix last ValidAlign
2022-11-18clarify that realloc refreshes pointer provenance even when the allocation ↵Ralf Jung-7/+11
remains in-place