Commit graph

125 commits

Author SHA1 Message Date
Ralf Jung
c9e77e8776 make const_alloc_layout feature gate only about functions that are already stable
the rest has their constness guarded by their usual feature gate
2024-11-01 14:32:59 +01:00
bors
54761cb3e8 Auto merge of #131349 - RalfJung:const-stability-checks, r=compiler-errors
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-25 23:29:40 +00:00
Ralf Jung
a0215d8e46 Re-do recursive const stability checks
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-25 20:31:40 +02:00
Ralf Jung
854e3c43e0 library: consistently use American spelling for 'behavior' 2024-10-25 12:02:47 +02:00
Johnathan W
8b754fbb4f Fixing rustDoc for LayoutError. 2024-10-10 16:18:56 -04:00
Matthias Krüger
1d45203779
Rollup merge of #123932 - adamse:global-alloc-safety-preconds-positive, r=tgross35
restate GlobalAlloc method safety preconditions in terms of what the caller has to do for greater clarity
2024-09-29 20:17:35 +02:00
Scott McMurray
18ca8bf8ee Take more advantage of the isize::MAX limit in Layout
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-17 20:05:57 -07:00
Adam Sandberg Ericsson
896ccaa8ac restate GlobalAlloc method safety preconditions in terms of what the caller has to do for greater clarity 2024-09-07 15:21:52 +01:00
Ben Kimock
e6b0f27e00 Try to golf down the amount of code in Layout 2024-08-20 18:41:07 -04:00
Ben Kimock
7f5d282185 Add a precondition check for Layout::from_size_align_unchecked 2024-08-19 17:18:17 -04:00
Nicholas Nethercote
84ac80f192 Reformat use declarations.
The previous commit updated `rustfmt.toml` appropriately. This commit is
the outcome of running `x fmt --all` with the new formatting options.
2024-07-29 08:26:52 +10:00
John Arundel
a19472a93e Fix doc nits
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-26 13:26:33 +01:00
Ralf Jung
287b66b0b5 size_of_val_raw: for length 0 this is safe to call 2024-07-10 18:01:06 +02:00
Ralf Jung
7731135af2 alloc::Layout: explicitly document size invariant on the type level 2024-03-25 20:18:46 +01:00
Mara Bos
a2c74b8445 SeqCst->Relaxed in doc examples.
SeqCst is unnecessary here.
2024-03-19 15:27:11 +01:00
Ralf Jung
b58f647d54 rename ptr::invalid -> ptr::without_provenance
also introduce ptr::dangling matching NonNull::dangling
2024-02-21 20:15:52 +01:00
Amanieu d'Antras
8e9c8dd10a Add information about allocation lifetime to Allocator::allocate 2024-02-13 14:12:51 +00:00
Amanieu d'Antras
fb5ed2986e Clarify the lifetimes of allocations returned by the Allocator trait
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-02-12 14:02:30 +00:00
joboet
fa9a911a57
libs: use assert_unchecked instead of intrinsic 2024-01-13 20:10:00 +01:00
Mark Rousskov
b81e788d16 Indicate that multiplication in Layout::array cannot overflow
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-11-23 22:05:45 -05:00
Joshua Liebow-Feeser
a9b0966aa5
Update library/core/src/alloc/layout.rs
Co-authored-by: David Tolnay <dtolnay@gmail.com>
2023-10-12 16:03:45 -07:00
Joshua Liebow-Feeser
25b81024a5
Guarantee that Layout::align returns a non-zero power of two 2023-09-07 12:54:34 -07:00
Nilstrieb
18c9baf4fe
Rollup merge of #107916 - reez12g:issue-107040, r=Amanieu
fix comment on Allocator trait

fixes https://github.com/rust-lang/rust/issues/107040
2023-05-30 12:57:38 +02:00
reez12g
000cd9b5fb fix comment on Allocator trait 2023-05-30 13:56:57 +09:00
Matthias Krüger
1d06bb9612
Rollup merge of #108630 - overlookmotel:realloc-docs-fix, r=Amanieu
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-05-27 20:40:27 +02:00
Deadbeef
63e0ddbf1d core is now compilable 2023-04-16 07:20:26 +00:00
Deadbeef
76dbe29104 rm const traits in libcore 2023-04-16 06:49:27 +00:00
bors
48ae1b335f Auto merge of #105096 - LegionMammal978:copied-allocators, r=Amanieu
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:🆕:<i32>()).unwrap();
    alloc2.deallocate(ptr.cast(), Layout:🆕:<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-26 01:21:12 +00:00
overlookmotel
48e812687e Fix docs for alloc::realloc
Fixes #108546
2023-03-01 23:36:41 +00:00
Jubilee
1af9b4f347
Clarify new_size for realloc means bytes 2023-02-09 23:56:20 -08:00
LegionMammal978
57e12f970c Clarify that copied allocators must behave the same 2022-11-30 13:51:31 -05:00
Manish Goregaokar
1625435fa4
Rollup merge of #102207 - CraftSpider:const-layout, r=scottmcm
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-22 01:26:07 -05:00
Rune Tynan
07911879d2 Use ? instead of match 2022-11-20 15:01:22 -05:00
Rune Tynan
6f2dcac78b Update with derive_const 2022-11-20 15:01:21 -05:00
Rune Tynan
9f4b4e46a3 constify remaining layout methods
Remove bad impl for Eq

Update Cargo.lock and fix last ValidAlign
2022-11-20 15:01:21 -05:00
Ralf Jung
d26659d611 clarify that realloc refreshes pointer provenance even when the allocation remains in-place 2022-11-18 10:43:40 +01:00
Scott McMurray
fed105381b Remove the old ValidAlign name
Since it looks like there won't be any reverts needed in `Layout`, finish off this change.
2022-11-11 21:44:27 -08:00
Yuki Okushi
38db483af7
Rollup merge of #102072 - scottmcm:ptr-alignment-type, r=thomcc
Add `ptr::Alignment` type

Essentially no new code here, just exposing the previously-`pub(crate)` `ValidAlign` type under the name from the ACP.

ACP: https://github.com/rust-lang/libs-team/issues/108
Tracking Issue: https://github.com/rust-lang/rust/issues/102070

r? ``@ghost``
2022-10-10 00:09:40 +09:00
Pietro Albini
3975d55d98
remove cfg(bootstrap) 2022-09-26 10:14:45 +02:00
Scott McMurray
e2d7cdcf2b Add rustc_allow_const_fn_unstable annotations to pre-existing Layout methods 2022-09-21 13:43:21 -07:00
Deadbeef
31f259ce5a Add const_trait to Allocator 2022-09-16 12:08:45 +08:00
Jane Losare-Lusby
bf7611d55e Move error trait into core 2022-08-22 13:28:25 -07:00
Dylan DPC
51eed00ca9
Rollup merge of #100030 - WaffleLapkin:nice_pointer_sis, r=scottmcm
cleanup code w/ pointers in std a little

Use pointer methods (`byte_add`, `null_mut`, etc) to make code in std a little nicer.
2022-08-12 20:39:10 +05:30
Maybe Waffle
127b6c4c18 cleanup code w/ pointers in std a little 2022-08-05 16:47:49 +04:00
Scott McMurray
a32305a80f Re-optimize Layout::array
This way it's one check instead of two, so hopefully it'll be better

Nightly:
```
layout_array_i32:
	movq	%rdi, %rax
	movl	$4, %ecx
	mulq	%rcx
	jo	.LBB1_2
	movabsq	$9223372036854775805, %rcx
	cmpq	%rcx, %rax
	jae	.LBB1_2
	movl	$4, %edx
	retq
.LBB1_2:
	…
```

This PR:
```
	movq	%rcx, %rax
	shrq	$61, %rax
	jne	.LBB2_1
	shlq	$2, %rcx
	movl	$4, %edx
	movq	%rcx, %rax
	retq
.LBB2_1:
	…
```
2022-07-13 17:07:41 -07:00
Christopher Durham
11694905b4 Remove duplication of layout size check 2022-07-11 17:58:42 -04:00
Christopher Durham
079d3eb22f Take advantage of known-valid-align in layout.rs 2022-07-10 20:34:39 -04:00
bors
4ec97d991b Auto merge of #95295 - CAD97:layout-isize, r=scottmcm
Enforce that layout size fits in isize in Layout

As it turns out, enforcing this _in APIs that already enforce `usize` overflow_ is fairly trivial. `Layout::from_size_align_unchecked` continues to "allow" sizes which (when rounded up) would overflow `isize`, but these are now declared as library UB for `Layout`, meaning that consumers of `Layout` no longer have to check this before making an allocation.

(Note that this is "immediate library UB;" IOW it is valid for a future release to make this immediate "language UB," and there is an extant patch to do so, to allow Miri to catch this misuse.)

See also #95252, [Zulip discussion](https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Layout.20Isn't.20Enforcing.20The.20isize.3A.3AMAX.20Rule).
Fixes https://github.com/rust-lang/rust/issues/95334

Some relevant quotes:

`@eddyb,` https://github.com/rust-lang/rust/pull/95252#issuecomment-1078513769

> [B]ecause of the non-trivial presence of both of these among code published on e.g. crates.io:
>
>   1. **`Layout` "producers" / `GlobalAlloc` "users"**: smart pointers (including `alloc::rc` copies with small tweaks), collections, etc.
>   2. **`Layout` "consumers" / `GlobalAlloc` "providers"**: perhaps fewer of these, but anything built on top of OS APIs like `mmap` will expose `> isize::MAX` allocations (on 32-bit hosts) if they lack extra checks
>
> IMO the only responsible option is to enforce the `isize::MAX` limit in `Layout`, which:
>
>   * makes `Layout` _sound_ in terms of only ever allowing allocations where `(alloc_base_ptr: *mut u8).offset(size)` is never UB
>   * frees both "producers" and "consumers" of `Layout` from manually reimplementing the checks
>     * manual checks can be risky, e.g. if the final size passed to the allocator isn't the one being checked
>     * this applies retroactively, fixing the overall soundness of existing code with zero transition period or _any_ changes required from users (as long as going through `Layout` is mandatory, making a "choke point")
>
>
> Feel free to quote this comment onto any relevant issue, I might not be able to keep track of developments.

`@Gankra,` https://github.com/rust-lang/rust/pull/95252#issuecomment-1078556371

> As someone who spent way too much time optimizing libcollections checks for this stuff and tried to splatter docs about it everywhere on the belief that it was a reasonable thing for people to manually take care of: I concede the point, it is not reasonable. I am wholy spiritually defeated by the fact that _liballoc_ of all places is getting this stuff wrong. This isn't throwing shade at the folks who implemented these Rc features, but rather a statement of how impractical it is to expect anyone out in the wider ecosystem to enforce them if _some of the most audited rust code in the library that defines the very notion of allocating memory_ can't even reliably do it.
>
> We need the nuclear option of Layout enforcing this rule. Code that breaks this rule is _deeply_ broken and any "regressions" from changing Layout's contract is a _correctness_ fix. Anyone who disagrees and is sufficiently motivated can go around our backs but the standard library should 100% refuse to enable them.

cc also `@RalfJung` `@rust-lang/wg-allocators.` Even though this technically supersedes #95252, those potential failure points should almost certainly still get nicer panics than just "unwrap failed" (which they would get by this PR).

It might additionally be worth recommending to users of the `Layout` API that they should ideally use `.and_then`/`?` to complete the entire layout calculation, and then `panic!` from a single location at the end of `Layout` manipulation, to reduce the overhead of the checks and optimizations preserving the exact location of each `panic` which are conceptually just one failure: allocation too big.

Probably deserves a T-lang and/or T-libs-api FCP (this technically solidifies the [objects must be no larger than `isize::MAX`](https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize) rule further, and the UCG document says this hasn't been RFCd) and a crater run. Ideally, no code exists that will start failing with this addition; if it does, it was _likely_ (but not certainly) causing UB.

Changes the raw_vec allocation path, thus deserves a perf run as well.

I suggest hiding whitespace-only changes in the diff view.
2022-07-10 08:54:32 +00:00
Christopher Durham
344b99bd9f
nit
Co-authored-by: scottmcm <scottmcm@users.noreply.github.com>
2022-06-30 00:17:21 -04:00
Christopher Durham
c4b4c64804 Revert isize::MAX changes to Layout helpers
The isize::MAX is enforced by the constructor; let it handle it.
2022-06-29 23:17:15 -04:00