# \[Pitch\] Temporary uninitialized buffers

**URL:** <https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954>\
**Category:** Pitches\
**Tags:** memory-safety, pointers\
**Created:** [May 26, 2021, 4:59pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954 "2021-05-26T16:59:22Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![ben-cohen](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ben-cohen/32/296_2.png) [@ben-cohen](https://forums.swift.org/u/ben-cohen)\
**Post date:** [May 27, 2021, 7:23pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/21 "2021-05-27T19:23:48Z")

</div>

What's not clear about the difference between them? A buffer is a pointer plus a length, which allows things like collection conformance and assertions in debug when going beyond that length.

I don't see a justification for including the convenience operator. This really isn't something that needs to be convenient.

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [May 27, 2021, 7:31pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/22 "2021-05-27T19:31:51Z")

</div>

Thanks Ben—I'll keep this feedback in mind when writing the formal proposal.

---

<div class="post-metadata">

**Author:** ![gnuoyd](https://avatars.discourse-cdn.com/v4/letter/g/bc8723/32.png) [@gnuoyd](https://forums.swift.org/u/gnuoyd)\
**Post date:** [May 27, 2021, 7:49pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/23 "2021-05-27T19:49:17Z")

</div>

My examples were deliberately constructed so that all of the initial  
Tacos were available from the start, or the initial count of the array  
was 0 and the Tacos were appended. Maybe I have overlooked something,  
but I do not see a need to default-initialize the FixedCapacityArray at  
any index.

Dave

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [May 27, 2021, 8:28pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/24 "2021-05-27T20:28:06Z")

</div>

> [@ben-cohen](#):
>
> What's not clear about the difference between them? A buffer is a pointer plus a length, which allows things like collection conformance and assertions in debug when going beyond that length.

Just on this point: the distinction made in the past is that a buffer owns its storage and a pointer does not, hence "buffer pointer". In the case of this API, the API _does_ own the storage, so "buffer" seems fine, but that's why the type isn't just called "UnsafeBuffer". Whether this distinction pulls its weight is also of course a matter of debate. :-)

---

<div class="post-metadata">

**Author:** ![Fabio\_Kaminski](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/fabio_kaminski/32/10660_2.png) [@Fabio\_Kaminski](https://forums.swift.org/u/Fabio_Kaminski)\
**Post date:** [May 28, 2021, 12:32am UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/25 "2021-05-28T00:32:30Z")

</div>

Would also like to see this happening.  
This would help to interface with C, C++ and Objective-C code a lot.

There's code that needs to deal with array of things, so or i had to use malloc/free, .allocate or allocate a temp array to use its inner buffer to pass things over, when you know its a lifetime within the inner scope, so calling malloc and free for things that could be stack allocated would be a huge win.

If someone also have some vision for passing buffers that is not so painful it would be nice.

If you have to pass more than one buffer of different types you end up cascading like this

```
.withUnsafeSomething { y in 
  .withUnsafeSomething { a in
     .withUnsafeSomething { h in
       .withUnsafeSomething { o in
         .withUnsafeSomething { o in
            doSomethingWith(y!.baseAddress, yCount, a!.baseAddress, aCount, h!.baseAddress, hCount, o!.baseAddress, oCount, o!.baseAddress, oCount)
          } 
       }
     }
  }
}

```

It gives me all these bad flashbacks from the time i used to write things in Clojure.

Edit: I guess a arena allocator where the buffers could get intermixed in the same chunk of memory would be the best fit for this without any help from language constructions.  
The problem is they are kind of painful to implement. Had to do one in C++ for a multi-column representation and its just awful what you have to do.

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [May 28, 2021, 12:31pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/26 "2021-05-28T12:31:28Z")

</div>

Hi Fabio! Thanks for the feedback. Indeed, I think these functions would make interacting with certain styles of C and C++ code much easier. They would also allow us to wrap those functions in Swift interfaces while maintaining the sort of efficiency possible in C.

As for the nested calls, I don't have a good solution for that in this pitch but I agree it's something the language, as a whole, could use better syntax for. You could start your own pitch thread proposing something!

---

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [May 28, 2021, 1:38pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/27 "2021-05-28T13:38:31Z")

</div>

> [@grynspan](#):
>
> We already have such a construct in the language in the form of `Array<T>` and `reserveCapacity()` , which the compiler can optimize into a simple stack allocation in all the scenarios where it would be safe to use the proposed `FixedCapacityArray<T>` type. Any additional compile-time optimizations that could be added for `FixedCapacityArray<T>` could also be added for `Array<T>`

If the compiler can already stack-promote Arrays, what value does this function add?

AFAICT, the value is that it uses a simpler heuristic than the optimiser. In that case, perhaps we should just fix the optimiser to more reliably stack promote, rather than adding things to the standard library to bypass the optimiser's own logic?

> [@grynspan](#):
>
> But that doesn't mean it's the _only_ way and it doesn't mean that the most obvious way is the most optimal way. Sometimes, developers do need to write code with a different balance of safety and performance than the default would allow. This is why symbols like `UnsafePointer` include the word `Unsafe` in their names—it's a reminder to developers that by using them, they are leaving the well-trodden path.

This is MHO, but I think the only justification for using unsafe constructs should be when there is no other way to do what you're doing - e.g. because the standard library doesn't provide a checked primitive for you to compose, or because you need to interoperate with C. It should be heavily discouraged, much more than it currently is (looking at you, `Sequence.withContiguousStorageIfAvailable`, and `String.withUTF8`).

I don't think "I need a temporary buffer" is a good enough justification to jump to unsafe code. It just doesn't pass the smell test to me.

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [May 28, 2021, 4:21pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/28 "2021-05-28T16:21:36Z")

</div>

> [@Karl](#):
>
> If the compiler can already stack-promote Arrays, what value does this function add?

That's a fair question. **⚠ Warning:** Incoming Wall of Text!

### It helps with escape analysis

`Array` can escape its context, which means [escape analysis](https://en.wikipedia.org/wiki/Escape_analysis) must be performed and passed in order for it to be eligible for stack promotion. In the general case, escape analysis is [undecidable](https://en.wikipedia.org/wiki/Pointer_analysis). The compiler must often assume that, even for seemingly simple programs, values will escape their declaring contexts and so cannot be stack-promoted. This means that `Array`, while safe to use, does not always produce optimal codegen. The proposed `FixedCapacityArray` has the same problem: it can escape its calling context, so it must be subjected to escape analysis.

One common case where the compiler must assume an escape is possible is when a value is passed to a non-transparent function or closure: at that point, the compiler must assume that the value will escape. This limitation makes it very hard to use such a value in a complex project without sacrificing the performance benefits of stack promotion. The proposed unsafe function provides the ability to assert that the provided buffer cannot escape without violating the language's constraints (much like how the language trusts developers not to escape the pointer used in `withUnsafeBytes(of:_:)` or to call `UnsafeContinuation.resume(...)` more than once.)

### It helps build safe, performant API

Unsafe primitives are important in a language like Swift because they are ultimately needed in order to build higher-level, safer constructs. For example, there are a number of C APIs (think POSIX) that write to pointers of various types but don't allocate or deallocate them themselves. Currently, there are really only two ways to use such API in Swift:

1. Heap-allocate an `UnsafeMutable[Buffer]Pointer` or compatible type and pass it to the C API, or
2. If only a single value is needed, pass a mutable `Optional` to the API with `&`, which necessitates zero-initialization.

Both come with performance costs that this function is intended to resolve. Ideally, such API would get customized Swift interfaces that hide the need for unsafe pointers. A developer, working on the Swift interfaces for these C APIs, can use the proposed function to produce an optimal Swift interface that is as fast as using the C interface directly.

### It's okay not to use it

This API is not for everyone. Like other APIs containing the word `Unsafe`, it's expected that most engineers will rarely if ever use it. There are some engineers who will use it because it is necessary for them to complete the tasks in front of them. It's okay to be in the former group instead of the latter group.

For what it's worth, someone could conceivably create an "Extra-Safe Swift" that didn't expose any API for any unsafe constructs, and I think that's probably an area worth exploring in general. I'd be happy to add my two cents to a discussion thread about such a project. 🙂

---

<div class="post-metadata">

**Author:** ![benrimmington](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/benrimmington/32/695_2.png) [@benrimmington](https://forums.swift.org/u/benrimmington)\
**Post date:** [May 28, 2021, 4:46pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/29 "2021-05-28T16:46:56Z")

</div>

Instead of adding more top-level functions, you could add a static method to each type:

```swift
extension UnsafeMutableRawBufferPointer {

  public static func withEphemeral<R>(
    byteCount: Int,
    alignment: Int,
    do body: (inout Self) throws -> R
  ) rethrows -> R
}

```

```swift
extension UnsafeMutableBufferPointer {

  public static func withEphemeral<R>(
    capacity: Int,
    do body: (inout Self) throws -> R
  ) rethrows -> R
}

```

This may improve call sites, especially if the caller is using their own type aliases:

```swift
typealias Bytes = UnsafeMutableRawBufferPointer

Bytes.withEphemeral(byteCount: 42, alignment: 1) { bytes in /*...*/ }

```

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [May 28, 2021, 4:50pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/30 "2021-05-28T16:50:32Z")

</div>

> [@benrimmington](#):
>
> Instead of adding more top-level functions, you could add a static method to each type:

I'll raise this question during the formal proposal!

---

<div class="post-metadata">

**Author:** ![fclout](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/fclout/32/36155_2.png) [@fclout](https://forums.swift.org/u/fclout)\
**Post date:** [May 28, 2021, 6:27pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/31 "2021-05-28T18:27:39Z")

</div>

I'm a big fan of not having unsafe APIs if it can be avoided. If Swift had fixed-size arrays with a stack storage guarantee, would we still feel that this unsafe mechanism was useful?

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [May 28, 2021, 6:44pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/32 "2021-05-28T18:44:58Z")

</div>

> [@fclout](#):
>
> If Swift had fixed-size arrays with a stack storage guarantee, would we still feel that this unsafe mechanism was useful?

See my [wall of text](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/28) above. tl;dr it's not possible to implement such a type _and_ make such guarantees _and_ do so safely. ☹

---

<div class="post-metadata">

**Author:** ![fclout](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/fclout/32/36155_2.png) [@fclout](https://forums.swift.org/u/fclout)\
**Post date:** [May 28, 2021, 6:53pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/33 "2021-05-28T18:53:41Z")

</div>

Escape analysis is generally undecidable, but if a fixed-size array is a value type, then the law of exclusivity solves the problem. Very crudely using your original example, I get this:

```swift
func handleTacos<Tacos: Collection>(tacos: inout Tacos) where Tacos.Element == Taco {
	for i in tacos.indices {
		create(taco: &tacos[i])
	}
	eatTooMuch(tacos: &tacos)
	for i in tacos.indices {
		destroy(taco: &tacos[i])
	}
}

if tacoCount < someLimit {
	var stackOfTacos: (Taco * tacoCount)
	handleTacos(&stackOfTacos)
} else {
	var heapOfTacos: [Taco] = ...
	handleTacos(&heapOfTacos)
}

```

Of course, `(Taco * tacoCount)` doesn't exist, but I think that it gives the right idea. (For a truly fixed-size array, you might have to replace `tacoCount` with an integer literal and have a count parameter in `handleTacos`, but neither seem like mortal sins to me.) What part of this is impossible, unsafe, or not guaranteed to use stack memory?

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [May 28, 2021, 7:01pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/34 "2021-05-28T19:01:20Z")

</div>

A fixed-size array type could certainly help with many use cases, but there are still places where I could see an uninitialized buffer being useful:

- If the desired buffer has a dynamic number of elements. In a future where we have type-level integers, you could conceivably instantiate an `(n x ElementType)` type from a local `let` constant `n`, but we're a ways from that.
- If the buffer needs to be gradually or partially initialized, then in performance-sensitive applications, being able to write to memory incrementally may be preferable to having to pre-initialize a complete value of `(n x ElementType)` and then incrementally update it,

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [May 28, 2021, 7:07pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/35 "2021-05-28T19:07:31Z")

</div>

> [@fclout](#):
>
> For a truly fixed-size array, you might have to replace `tacoCount` with an integer literal

I'll note that nothing in this proposal nor the draft implementation assumes that `tacoCount` is a compile-time constant.

> [@fclout](#):
>
> What part of this is impossible, unsafe, or not guaranteed to use stack memory?

Maybe I can demonstrate with some counterexamples? What happens if you say:

```swift
return stackOfTacos
// escape prevents stack promotion

```

Or:

```swift
struct X {
  var tacos: (Taco * tacoCount)
  // membership prevents stack promotion
}

```

Or:

```swift
let ptr = UnsafeMutablePointer<(Taco * tacoCount)>.allocate(capacity: 100)
// would we even allow this??

```

Or:

```swift
var stackOfTacos: (Taco * tacoCount)
print(stackOfTacos[1])
// assume tacoCount > 2

```

The last sample in particular should be a compile-time error because we are using the value before initializing it—if it is _not_ an error, then this type is unsafe. One of the use cases for the proposed function is to _avoid_ unnecessary premature ~~allocation~~ initialization.

The language already has an affordance for a fixed-size sequence of same-typed values whose count is known at compile-time: tuples. I'm sure you've seen a fixed-size C array imported as a tuple. That affordance is lacking in a lot of ways that have been noted previously, but it exists.

If we were to add fixed-size arrays to the language (and I do want to do that independently of this pitch) then it might make sense to implement them as syntactic sugar over a same-typed tuple. For example, `(Taco * 2)` might simply resolve to `(Taco, Taco)`. I think we'd also want additional members (like a subscript) added to such tuples to make it work well, though.

---

<div class="post-metadata">

**Author:** ![fclout](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/fclout/32/36155_2.png) [@fclout](https://forums.swift.org/u/fclout)\
**Post date:** [May 28, 2021, 7:32pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/36 "2021-05-28T19:32:38Z")

</div>

Of course `tacoCount` is not a constant, but `SOME_LIMIT` in your original example hopefully is, given that variable-length arrays in C are problematic. You can have `handleTacos` take a count in addition to the collection to be modified. That's a small price to pay for safety, IMO.

I feel like these new examples don't go to the point of `withUnsafeUninitializedMutableBufferPointer`:

- You cannot return the result of `withUnsafeUninitializedMutableBufferPointer`, so I think that the concern of returning `stackOfTacos` is moot (aside from many other problematic aspects; if you need to return your array, then a stack-allocated array was probably not the right choice in the first place!).
- `withUnsafeUninitializedBufferPointer` is inherently not using a struct member, so I don't know why the ability to use fixed-size arrays as struct members would invalidate this construct.

Both of these seem to point towards fixed-size arrays being able to do more things, which is a good thing!

Towards the last point: I'm asking because I am deeply skeptical that the cost of zeroing stack memory is unbearable in high-performance applications.

There's been multiple real-world experiments all over the place out here that show that zero-init has a cost that falls within statistical noise. As a Security Guy™, and having some amount of experience adopting security features in large code bases, when people tell you: "we need to be able to opt out of these security features for performance reasons", they aren't telling you that there's a performance problem. They're telling you that they don't know if there is a performance problem.

Android has been shipping a whole userland with stack zero-init and Windows has it in the kernel. At this point, I feel that we're very close to showing that there isn't a performance problem, or that it's not big enough that there should be a standard library function to help you opt out of safety if there's a safe way to do the same thing. Significant effort is put towards closing this very issue in C code bases; I think that there should be careful consideration before it's reopened in Swift.

I agree that fixed-size arrays look like tuples, which is why I used a tuple-like syntax for them. However, last time this was brought up (several years ago), Joe mentioned that it would be problematic to have fixed-size arrays be _too much_ like tuples because anonymous types can't have protocol conformances.

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [May 28, 2021, 7:45pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/37 "2021-05-28T19:45:53Z")

</div>

> [@fclout](#):
>
> Of course `tacoCount` is not a constant, but `SOME_LIMIT` in your original example hopefully is, given that variable-length arrays in C are problematic.

Either constant or known to the stdlib in some way—I have not attempted to define the heuristic here but in my POC branch it's a hard-coded 1KB.

> [@fclout](#):
>
> - You cannot return the result of `withUnsafeUninitializedMutableBufferPointer` , so I think that the concern of returning `stackOfTacos` is moot (aside from many other problematic aspects; if you need to return your array, then a stack-allocated array was probably not the right choice in the first place!).
> - `withUnsafeUninitializedBufferPointer` is inherently not using a struct member, so I don't know why the ability to use fixed-size arrays as struct members would invalidate this construct.

That's my point: by adding a fixed-size array, you make these things possible, which forces the compiler to perform escape analysis, which is undecidable. The proposed function is, like all unsafe affordances in Swift, a way around that which is necessary in certain contexts (which have already been enumerated in this pitch thread.)

> [@fclout](#):
>
> Towards the last point: I'm asking because I am deeply skeptical that the cost of zeroing stack memory is unbearable in high-performance applications.

So, we're using initialization here to mean two things:

1. Zero-initialization, i.e. ensuring the raw bytes under the sequence are filled with zeroes (or `0xDEADBEEF` or whatever), and
2. Swift value initialization, i.e. calling `init(...)` on every element in the sequence.

I think we're conflating these two definitions. I know I have done so previously in this thread, which is entirely my fault and I should know better. My bad!

Zero-initialization is likely cheap in many many cases and has benefits and I'm not questioning that. Swift value initialization, when it's solely for the purpose of satisfying the compiler's requirement that all values be initialized, is a performance cost with measurable impact on real-world codebases. It's also one you can avoid today by using `UnsafeMutableBufferPointer.allocate(capacity:)`, but _that_ comes with the cost of heap allocation unless you're lucky and the optimizer decides to stack promote (hint: it usually won't.)

> [@fclout](#):
>
> I agree that fixed-size arrays look like tuples, which is why I used a tuple-like syntax for them. However, last time this was brought up (several years ago), Joe mentioned that it would be problematic to have fixed-size arrays be _too much_ like tuples because anonymous types can't have protocol conformances.

I think that's worth revisiting in a separate discussion, especially in light of a recent-ish [pitch](https://forums.swift.org/t/tuples-conform-to-equatable-comparable-and-hashable/34156). It might be as "simple" as a new member function on tuples with same-typed values:

```swift
func withSequenceSemantics<R, S: Sequence>(_ body: (S) throws -> R) rethrows -> R where S.Element == Self.TypeOfAllValues

```

The syntax for that is all wrong but I'm sure you get the idea. In any case, I'd be happy to chat with both you and Joe about it in more detail.

---

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [May 28, 2021, 8:46pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/38 "2021-05-28T20:46:59Z")

</div>

> [@grynspan](#):
>
> `Array` can escape its context, which means [escape analysis](https://en.wikipedia.org/wiki/Escape_analysis) must be performed and passed in order for it to be eligible for stack promotion. In the general case, escape analysis is [undecidable](https://en.wikipedia.org/wiki/Pointer_analysis). The compiler must often assume that, even for seemingly simple programs, values will escape their declaring contexts and so cannot be stack-promoted. This means that `Array` , while safe to use, does not always produce optimal codegen. The proposed `FixedCapacityArray` has the same problem: it can escape its calling context, so it must be subjected to escape analysis.

I don't think this is a deal-maker or -breaker: for one thing, we do have non-escaping types in Swift (closures), and I'd love to see that generalised in some way. Another option would be if we had a `withTemporaryArray` function which checked that the buffer didn't actually escape; again, the precedent would be closures, which have the `withoutActuallyEscaping` function.

> [@grynspan](#):
>
> This API is not for everyone. Like other APIs containing the word `Unsafe` , it's expected that most engineers will rarely if ever use it. There are some engineers who will use it because it is necessary for them to complete the tasks in front of them. It's okay to be in the former group instead of the latter group.

I don't know if this is directed at me specifically, but let me assure you that I use unsafe APIs rather frequently. I'm very much in the latter group. The thing is that I've become increasingly sceptical about how acceptable it is to use unsafe APIs at all.

The thing about memory safety is that it needs to be guaranteed _even in the face of bugs_. I've been thinking about that more and more - nobody writes bugs on purpose; they happen because some set of circumstances which you didn't think were possible turned out to, in fact, be possible (possibly due to changes elsewhere in the project, after you wrote the original code, so there's a temporal aspect, too). As an example, I've recently been trying to guard some code against malicious protocol conformances (e.g. a Collection which has a different number of elements every time you iterate it), because even in that extreme case, it's not acceptable to violate safety. Writing code which is resilient even to bugs is just super-difficult to do.

If you could completely trust engineers to get that right 100% of the time, there would never be any memory safety bugs (or bugs at all, for that matter). But the fact of the matter is that even the most knowledgable, most experienced engineers can't guarantee memory safety all of the time - if they could, we wouldn't be seeing this new generation of languages pitching safety as their top concern.

Just to make it clear - I'm not entirely opposed to this; I can even think of places in my projects where I'd like to use it, or have used similar constructs. But I'd really appreciate if we could thoroughly examine safe alternatives _first_. It's important.

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [May 28, 2021, 9:25pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/39 "2021-05-28T21:25:15Z")

</div>

> [@Karl](#):
>
> I don't think this is a deal-maker or -breaker: for one thing, we do have non-escaping types in Swift (closures)

This is tangential, but… [there are deeper evils](https://developer.apple.com/documentation/swift/2827967-withoutactuallyescaping)… 🙃

> [@Karl](#):
>
> The thing about memory safety is that it needs to be guaranteed _even in the face of bugs_ .

All code is a layer cake of terribleness, and the top layer (which should be the most safe) is built upon lower layers of lesser safety. `Foundation.Data` ultimately calls `malloc()` and `free()` in order to manage its storage. When you pass an object to some generic function, it is boxed in an "existential container" which, for values more than 3 words long, also involves heap allocation and deallocation. When you throw an `Error`, it's allocated, caught, handled, and deallocated—again, possibly involving the heap depending on the size of the thrown error value.

For every layer you descend, you sacrifice a little safety, until you get down to a layer where there isn't really any memory safety at all. The proposed function (or, yes, some alternative) is a necessary part of one of these lower layers that is needed in order to build that safe topmost layer in an optimal way.

And that's really the point: we want Swift to be safe! But to make it safe at a high level, we need some unsafety underneath to support it all. The proposed function allows library developers to build higher-level APIs that are safe _and_ performant instead of exposing C APIs or similar that carry with them all of C's _laissez-faire_ memory management cruft.

> [@Karl](#):
>
> Just to make it clear - I'm not entirely opposed to this; I can even think of places in my projects where I'd like to use it, or have used similar constructs. But I'd really appreciate if we could thoroughly examine safe alternatives _first_ . It's important.

I agree that it's important to examine alternatives, and I appreciate your interest in this pitch! I do hope my replies don't come off as dismissive, because that's not my intent.

---

<div class="post-metadata">

**Author:** ![fclout](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/fclout/32/36155_2.png) [@fclout](https://forums.swift.org/u/fclout)\
**Post date:** [May 28, 2021, 9:39pm UTC](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954/40 "2021-05-28T21:39:53Z")

</div>

I've spoken out of band with @grynspan and I feel that my opinion has been heard, but for the benefit of public discussion, here are my rough takeaways:

- Same as @Karl, I'm very very skeptical of unsafe APIs. I don't think that any of the currently permitted unsafe operations should be a bar for new ones; we shouldn't add unsafe operations on the basis that other, unrelated operations are unsafer
- I don't believe that the escape problem applies to the narrow case of value types as local variables. There is never an escape problem for value types. Sometimes you might have a copy problem even when using `inout` instead, but I think that none of the reasons that could cause a copy apply to this case (someone from the Core Team confirm that you basically never need to copy a value type passed as an inout parameter if it has automatic storage?)
  - my favourite outcome is still a translation of the C snippet from above using fixed-size arrays with automatic storage (which don't exist currently), because it does the same thing except it's safe; but it's contingent on the compiler having some strong guarantee that it wouldn't need a copy

- I don't fundamentally disagree with any of the benefits that have been brought up, but once there is a `withUnsafeUninitializedMutableBufferPointer` in the standard library, there are no take-backsies, so it would be disappointing if we ended up with two things that do the same thing except that one is unsafe but sounds faster (when it probably is at best negligibly better)
- I don't really like the positioning of this unsafe function: I think that it looks just usable enough that a bunch of people might use it without actually needing it. Something less usable and more obviously dangerous, like `withUnsafeLocalStorage` giving you an `UnsafeMutableRawBufferPointer` that always came from `alloca`, would make more sense as a "building block" to me, and it's easier to label with red crosses and skulls to tell people to stay away from it. You can then use that in code bases where it's this important to get stack-allocated buffers
  - I don't know how you would define a generic heuristic to figure out what's the maximum amount of space you can use anyway. There isn't any great (or even just good) context-free answer.

- if Swift does moves in this direction, I think that at least storage needs to be zeroed unless the compiler can prove that the zeroing is pointless, and there need to be `chkstk` calls sprinkled over this

[Previous page](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954.md?page=1)

[Next page](https://forums.swift.org/t/pitch-temporary-uninitialized-buffers/48954.md?page=3)
