Skip to content

Commit 9f9565f

Browse files
committed
[stdlib] in-place initializer for InlineArray
1 parent 16afe63 commit 9f9565f

File tree

3 files changed

+117
-3
lines changed

3 files changed

+117
-3
lines changed

stdlib/public/core/InlineArray.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,25 @@ extension InlineArray where Element: ~Copyable {
296296
}
297297
#else
298298
fatalError()
299+
#endif
300+
}
301+
302+
@available(SwiftStdlib 6.2, *)
303+
@_alwaysEmitIntoClient
304+
public init<E: Error>(
305+
initializingWith initializer: (inout OutputSpan<Element>) throws(E) -> Void
306+
) throws(E) {
307+
#if $BuiltinEmplaceTypedThrows
308+
_storage = try Builtin.emplace { (rawPtr) throws(E) -> () in
309+
let buffer = unsafe Self._initializationBuffer(start: rawPtr)
310+
_internalInvariant(Self.count == buffer.count)
311+
var output = unsafe OutputSpan(buffer: buffer, initializedCount: 0)
312+
try initializer(&output)
313+
let initialized = unsafe output.finalize(for: buffer)
314+
_precondition(count == initialized, "InlineArray initialization underflow")
315+
}
316+
#else
317+
fatalError()
299318
#endif
300319
}
301320
}

test/stdlib/InlineArray.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,14 @@ enum InlineArrayTests {
168168
let error = CancellationError()
169169
do {
170170
expectDoesNotThrow {
171-
let a = try InlineArray<0, String> { _ in throw error }
171+
let a = try InlineArray<0, String>({ _ in throw error })
172172
_checkInlineArray(a, oracle: [])
173173
}
174174
_expectThrows {
175-
let _ = try InlineArray<1, String> { _ in throw error }
175+
let _ = try InlineArray<1, String>({ _ in throw error })
176176
}
177177
_expectThrows {
178-
let _ = try InlineArray<1, any P> { _ in throw error }
178+
let _ = try InlineArray<1, any P>({ _ in throw error })
179179
}
180180
_expectThrows {
181181
let _ = try InlineArray<2, String> { index in

test/stdlib/Span/OutputSpanTests.swift

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,3 +325,98 @@ suite.test("mutate with MutableSpan prefix")
325325
expectTrue(b.elementsEqual((0..<10).map({2*(1+$0)})))
326326
b.deinitialize()
327327
}
328+
329+
suite.test("InlineArray initialization")
330+
.require(.stdlib_6_2).code {
331+
guard #available(SwiftStdlib 6.2, *) else { return }
332+
333+
var a: [Int] = []
334+
335+
let i = InlineArray<10, Int> {
336+
(o: inout OutputSpan<Int>) in
337+
for _ in 0..<o.capacity {
338+
let r = Int.random(in: 10...99)
339+
a.append(r)
340+
o.append(r)
341+
}
342+
}
343+
expectEqual(a.count, i.count)
344+
for j in i.indices {
345+
expectEqual(a[j], i[j])
346+
}
347+
}
348+
349+
suite.test("InlineArray initialization underflow")
350+
.skip(.wasiAny(reason: "Trap tests aren't supported on WASI."))
351+
.require(.stdlib_6_2).code {
352+
guard #available(SwiftStdlib 6.2, *) else { return }
353+
354+
expectCrashLater()
355+
_ = InlineArray<4, Int> {
356+
$0.append(1)
357+
}
358+
}
359+
360+
#if false
361+
suite.test("InlineArray initialization throws 0")
362+
.require(.stdlib_6_2).code {
363+
guard #available(SwiftStdlib 6.2, *) else { return }
364+
365+
enum LocalError: Error { case error }
366+
367+
class I {
368+
static public var count = 0
369+
init() { Self.count += 1 }
370+
deinit { Self.count -= 1 }
371+
}
372+
373+
let a: InlineArray<4, I>
374+
do throws(LocalError) {
375+
var c = 1
376+
a = try InlineArray(first: I()) {
377+
i throws(LocalError) in
378+
c += 1
379+
if c < 4 {
380+
return I()
381+
}
382+
print(I.count)
383+
throw LocalError.error
384+
}
385+
_ = a
386+
} catch {
387+
print(error, I.count)
388+
expectEqual(I.count, 0)
389+
}
390+
}
391+
392+
suite.test("InlineArray initialization throws")
393+
.require(.stdlib_6_2).code {
394+
guard #available(SwiftStdlib 6.2, *) else { return }
395+
396+
enum LocalError: Error { case error }
397+
398+
class I {
399+
static var count = 0
400+
init() { Self.count += 1 }
401+
deinit { Self.count -= 1 }
402+
}
403+
404+
let a: InlineArray<4, I>
405+
do throws(LocalError) {
406+
a = try InlineArray {
407+
o throws(LocalError) in
408+
o.append(I())
409+
o.append(I())
410+
o.append(I())
411+
o.append(I())
412+
expectEqual(I.count, 4)
413+
print(I.count)
414+
throw LocalError.error
415+
}
416+
_ = a
417+
} catch {
418+
print(error, I.count)
419+
expectEqual(I.count, 0)
420+
}
421+
}
422+
#endif

0 commit comments

Comments
 (0)