# "The optimizer may further assume that allocation is infallible"

**URL:** <https://internals.rust-lang.org/t/the-optimizer-may-further-assume-that-allocation-is-infallible/19780>\
**Category:** language design\
**Created:** [October 29, 2023, 11:20pm UTC](https://internals.rust-lang.org/t/the-optimizer-may-further-assume-that-allocation-is-infallible/19780 "2023-10-29T23:20:56Z")\
**Posts on this page:** 1\
**Showing post:** 5

<div class="post-metadata">

**Author:** ![farnz](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/farnz/32/6587_2.png) [@farnz](https://internals.rust-lang.org/u/farnz)\
**Post date:** [October 31, 2023, 9:00pm UTC](https://internals.rust-lang.org/t/the-optimizer-may-further-assume-that-allocation-is-infallible/19780/5 "2023-10-31T21:00:10Z")

</div>

> [@Jules-Bertholet](#):
>
> Second, the docs as written seem to imply that the optimizer can insert new allocations, or make them larger, which would be incorrect (I think?)

Can the optimizer replace an allocation with a realloc? Or otherwise reduce the size of memory being allocated

Dumb example to show what I mean:

```rust
pub fn dumb<T: Copy>(s1: Vec<T>, s2: &[T]) -> Option<Vec<T>> {
    assert!(s1.len() == 128);
    assert!(s2.len() == 128);
    
    let mut v = Vec::new();
    v.try_reserve(256).ok()?;
    
    v.extend(s1);
    v.extend(s2);
    
    Some(v)
}

```

It's clear that the programmer's intent is that there is a single allocation for `v`, of 256 items in size. But it wouldn't be unreasonable for the optimizer to exploit the fact that we own `s1` and it's going to be deallocated at the end of this function to convert the allocation of 256 items into reallocating `s1` from 128 to 256 items in size, potentially reducing the memory demand.

This also (if allowed) leads to a possible case where the optimizer might make an allocation larger, via merging of allocations:

```rust
pub fn calls_dumb<T: Copy>(s2: &[T]) -> Option<Vec<T>> {
    assert!(s2.len() == 128);
    
    let mut v = Vec::new();
    v.try_reserve(128).ok()?;
    
    v.resize(128, s2[0]);

    dumb(v, s2)
}

```

Here, `calls_dumb` allocates 128 items worth of space, and then fills them in; it then calls `dumb`, which allocates 256 items worth of space. The optimizer could, in theory, inline `dumb` into `calls_dumb`, then note that the following code has exactly the same observable behaviour and optimize `calls_dumb` into `optimized`:

```rust
pub fn optimized<T: Copy>(s2: &[T]) -> Option<Vec<T>> {
    assert!(s2.len() == 128);
    
    let mut v = Vec::new();
    v.try_reserve(256).ok()?;
    
    v.resize(128, s2[0]);

    v.extend(s2);

    Some(v)
}

```

I could well be missing something, mind, but I would have thought that this is legitimate behaviour for the optimizer, even though the allocator can no longer observe my allocation for 128 items.

---

_[View the full topic](https://internals.rust-lang.org/t/the-optimizer-may-further-assume-that-allocation-is-infallible/19780)._
