Hi everyone,
The review of SE-0524 " Add withTemporaryAllocation using Output(Raw)Span" begins now and runs through April 14, 2026.
Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the review manager via the forum messaging feature. When contacting the review manager directly, please keep the proposal link at the top of the message.
What goes into a review?
The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:
- What is your evaluation of the proposal?
- Is the problem being addressed significant enough to warrant a change to Swift?
- Does this proposal fit well with the feel and direction of Swift?
- If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
- How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
More information about the Swift evolution process is available at https://github.com/swiftlang/swift-evolution/blob/main/process.md .
Thanks for contributing to Swift!
Doug Gregor
Review Manager
11 Likes
Seems like an obvious thing to add, though I don't know how often it'll actually be useful — most of the time when I need withTemporaryAllocation it's to hand a pointer off to a C API anyway.
Like all these with functions, the function coloring problem hurts; there's no async version of these (though perhaps in this specific case, an async version is harder or undesirable).
Overall strongly in favor of this proposal. There are a number of places that I’d like to adopt this in Foundation and related libraries to eliminate (or narrow) unsafety around temporary allocations. The proposed API aligns with existing and proposed span-based APIs and follows the direction that Swift is heading by allowing developers to eliminate unsafe code.
I agree that there are some future directions (such as async variants) that may also be desirable in this space. But, in my opinion, this is a straightforward addition that would provide immediate benefits and does not preclude us from following those directions in the future, so I don’t think we should block this addition on solving those more general problems.
Thank you for your work on this!
3 Likes
Thanks for the proposal, the benefit is obvious to me. Just one question about its application.
There's this pattern of using withUnsafeTemporaryAllocation directly, the caller asks for a stack-allocated buffer to materialize an object, and it uses move to minimize ARC traffic:
let someObject = withUnsafeTemporaryAllocation(of: MyType.self, capacity: 1) { buffer in
initialize_object(buffer.baseAddress!)
return buffer.baseAddress!.move()
}
Is the proposed withTemporaryAllocation suitable for this situation? If so, can it achieve the same level of efficiency?
You can use the proposed API for that, but if you fundamentally require an UnsafeMutablePointer<MyType> to pass to initialize_object, it won't really be much safer. It would look like this:
let someObject = withTemporaryAllocation(of: MyType.self, capacity: 1) { span in
span.withUnsafeMutableBufferPointer { buffer, initializedCount in
initialize_object(&buffer[0])
initializedCount = 1
}
return span.removeLast()
}
Anyway, it should have the same basic performance. If you find yourself needing that pattern a lot, you should just write it generically:
func valueFromConstructor<R, E>(
construct: (UnsafeMutablePointer<R>) throws(E) -> Void
) throws(E) -> R where E: Error, R: ~Copyable {
return try withTemporaryAllocation(of: R, capacity: 1) { span in
try span.withUnsafeMutableBufferPointer { buffer, initializedCount in
// We unsafely assume 'construct' does not leave an initialized
// value in the buffer if it throws, so we can leave initializedCount
// at 0 on that path.
try construct(&buffer[0])
initializedCount = 1
}
return span.removeLast()
}
}
This would be a reasonable thing to add to the standard library. (And the standard library version could reasonably guarantee to do it in-place.)
2 Likes