@@ -92,44 +92,19 @@ func complexAlgorithm() -> Int {
92
92
}
93
93
```
94
94
95
- This type also serves as a safer replacement to ` withUnsafeTemporaryAllocation `
96
- when the amount of things to reserve is known statically:
97
-
98
- ``` swift
99
- // Previously
100
- withUnsafeTemporaryAllocation (of : Int .self , capacity : 16 ) {
101
- $0 .initialize (repeating : 0 )
102
-
103
- for i in $0 .indices {
104
- $0 [i] = compute ()
105
- }
106
- }
107
-
108
- // Now
109
- var ints = Vector< 16 , Int > (repeating : 0 )
110
-
111
- for i in ints.indices {
112
- ints[i] = compute ()
113
- }
114
- ```
115
-
116
95
Vectors of noncopyable values will be possible by using any of the closure based
117
96
taking initializers or the literal initializer:
118
97
119
98
``` swift
120
99
// [Atomic(0), Atomic(1), Atomic(2), Atomic(3)]
121
100
let incrementingAtomics = Vector< 4 , Atomic< Int >> { i in
122
101
Atomic (i)
123
- } // [Atomic(0), Atomic(1), Atomic(2), Atomic(3)]
124
-
125
- // [Atomic(337523057234), Atomic(8726493873498347), Atomic(98573472834767364),
126
- // Atomic(72394735763974)] (maybe)
127
- let randomAtomics = Vector< 4 , _ > (expand : RNG ()) { Atomic ($0 .next ()) }
102
+ }
128
103
129
104
// [Sprite(), Sprite(), Sprite(), Sprite()]
130
- // Where the 2nd, 3rd, and 4th elements are all copies of the initial first
131
- // value
132
- let copiedSprites = Vector< 4 , _ > (unfold : Sprite ()) { $0 .copy () }
105
+ // Where the 2nd, 3rd, and 4th elements are all copies of their previous
106
+ // element.
107
+ let copiedSprites = Vector< 4 , _ > (first : Sprite ()) { $0 .copy () }
133
108
134
109
// Inferred to be Vector<3, Mutex<Int>>
135
110
let literalMutexes: Vector = [Mutex (0 ), Mutex (1 ), Mutex (2 )]
@@ -299,44 +274,25 @@ extension Vector where Element: ~Copyable {
299
274
public init <E : Error >(with next : (Int ) throws (E) -> Element ) throws (E)
300
275
301
276
/// Initializes every element in this vector by running the closure with the
302
- /// passed in mutable state.
303
- ///
304
- /// This will call the closure 'count' times, where 'count' is the static
305
- /// count of the vector, to initialize every element by passing the closure
306
- /// an inout reference to the passed state. The closure is allowed to throw
307
- /// an error at any point during initialization at which point the vector will
308
- /// stop initialization, deinitialize every currently initialized element, and
309
- /// throw the given error back out to the caller.
310
- ///
311
- /// - Parameter state: The mutable state that can be altered during each
312
- /// iteration of the closure initializing the vector.
313
- /// - Parameter next: A closure that passes in an inout reference to the
314
- /// user given mutable state which returns an owned
315
- /// `Element` instance to insert into the vector.
316
- public init <State : ~ Copyable , E : Error >(
317
- expand state : consuming State,
318
- with next : (inout State) throws (E) -> Element
319
- ) throws (E)
320
-
321
- /// Initializes every element in this vector by running the closure with the
322
- /// passed in first element.
277
+ /// previously initialized element.
323
278
///
324
279
/// This will call the closure 'count' times, where 'count' is the static
325
280
/// count of the vector, to initialize every element by passing the closure
326
- /// an immutable borrow reference to the first element given to the
327
- /// initializer. The closure is allowed to throw an error at any point during
328
- /// initialization at which point the vector will stop initialization,
329
- /// deinitialize every currently initialized element, and throw the given
330
- /// error back out to the caller.
281
+ /// an immutable borrow reference to the previously initialized element. The
282
+ /// closure is allowed to throw an error at any point during initialization at
283
+ /// which point the vector will stop initialization, deinitialize every
284
+ /// currently initialized element, and throw the given error back out to the
285
+ /// caller.
331
286
///
332
287
/// - Parameter first: The first value to insert into the vector which will be
333
288
/// passed to the closure as a borrow.
334
289
/// - Parameter next: A closure that passes in an immutable borrow reference
335
- /// of the given first element of the vector which returns
336
- /// an owned `Element` instance to insert into the vector.
290
+ /// of the previously initialized element of the vector
291
+ /// which returns an owned `Element` instance to insert into
292
+ /// the vector.
337
293
public init <E : Error >(
338
- unfold first : consuming Element ,
339
- with next : (borrowing Element ) throws (E) -> Element
294
+ first : consuming Element ,
295
+ next : (borrowing Element ) throws (E) -> Element
340
296
) throws (E)
341
297
}
342
298
@@ -364,7 +320,6 @@ collection type.
364
320
extension Vector where Element : ~Copyable {
365
321
public typealias Element = Element
366
322
public typealias Index = Int
367
- public typealias Indices = Range <Int >
368
323
369
324
/// Provides the count of the collection statically without an instance.
370
325
public static var count: Int { count }
@@ -378,11 +333,6 @@ extension Vector where Element: ~Copyable {
378
333
public borrowing func index (after i : Int ) -> Int
379
334
public borrowing func index (before i : Int ) -> Int
380
335
381
- public borrowing func reduce <Result : ~ Copyable , E : Error >(
382
- into initialResult : consuming Result,
383
- _ updateAccumulatingResult : (inout Result, borrowing Element ) throws (E) -> ()
384
- ) throws (E) -> Result
385
-
386
336
public mutating func swapAt (
387
337
_ i : Int ,
388
338
_ j : Int
@@ -392,95 +342,6 @@ extension Vector where Element: ~Copyable {
392
342
}
393
343
```
394
344
395
- ### C Interop changes
396
-
397
- With the introduction of ` Vector ` , we have a unique opportunity to fix another
398
- pain point within the language with regards to C interop. Currently, the Swift
399
- compiler imports a C array of type ` T[24] ` as a tuple of ` T ` with 24 elements.
400
- Previously, this was really the only representation that the compiler could pick
401
- to allow interfacing with C arrays. It was a real challenge working with these
402
- fields from C in Swift. Consider the following C struct:
403
-
404
- ``` c
405
- struct section_64 {
406
- char sectname[ 16] ;
407
- char segname[ 16] ;
408
- uint64_t addr;
409
- uint64_t size;
410
- uint32_t offset;
411
- uint32_t align;
412
- ...
413
- };
414
- ```
415
-
416
- Today, this gets imported as the following Swift struct:
417
-
418
- ``` swift
419
- struct section_64 {
420
- let sectname: (CChar , CChar , CChar , CChar , CChar , CChar , ... 10 more times)
421
- let segname: (CChar , CChar , CChar , CChar , CChar , CChar , ... 10 more times)
422
- let addr: UInt64
423
- let size: UInt64
424
- let offset: UInt32
425
- let align: UInt32
426
- ...
427
- }
428
- ```
429
-
430
- Using an instance of ` section_64 ` in Swift for the most part is really easy.
431
- Accessing things like ` addr ` or ` size ` are simple and easy to use, but using the
432
- ` sectname ` property introduces a level of complexity that isn't so fun to use.
433
-
434
- ``` swift
435
- func getSectionName (_ section : section_64) -> String {
436
- withUnsafePointer (to : section.sectname ) {
437
- // This is unsafe! 'sectname' isn't guaranteed to have a null byte
438
- // indicating the end of the C string!
439
- String (cString : $0 )
440
- }
441
- }
442
-
443
- func iterateSectionNameBytes (_ section : section_64) {
444
- withUnsafeBytes (to : section.sectname ) {
445
- for byte in $0 {
446
- ...
447
- }
448
- }
449
- }
450
- ```
451
-
452
- Having to resort to using very unsafe API to do anything useful with imported C
453
- arrays is not something a memory safe language like Swift should be in the
454
- business of. ` Vector ` allows us to clean up this sore spot in a very elegant and
455
- much more importantly, safe way.
456
-
457
- We plan to introduce a new _ upcoming_ feature that folks can enable whenever
458
- they'd like to via ` -enable-upcoming-feature ImportCArraysAsVectors ` . This will
459
- change the current behavior of importing C arrays as tuples, to instead import
460
- them as ` Vector ` . For the previous example, we'd instead generate the following:
461
-
462
- ``` swift
463
- struct section_64 {
464
- let sectname: Vector<16, CChar >
465
- let segname: Vector<16, CChar >
466
- let addr: UInt64
467
- let size: UInt64
468
- let offset: UInt32
469
- let align: UInt32
470
- ...
471
- }
472
- ```
473
-
474
- By introducing an upcoming feature, it lets folks who are ready to migrate their
475
- codebase using a C interface to use ` Vector ` entirely, while still allowing
476
- dependencies or dependents to use the old behavior with the same C interface.
477
-
478
- In a future Swift language mode, we plan to make this behavior the default and
479
- drop importing C array fields as tuples and only as ` Vector ` . This approach
480
- allows developers to get the new behavior early if they'd like to use it, which
481
- will make the language mode transition much smoother because there would be no
482
- source break with regards to this feature.
483
-
484
345
## Source compatibility
485
346
486
347
` Vector ` is a brand new type in the standard library, so source should still be
@@ -758,6 +619,85 @@ Some syntax suggestions:
758
619
Note that it may make more sense to have the length appear before the type. I
759
620
discuss this more in depth in [ Reorder the generic arguments] ( #reorder-the-generic-arguments-vectort-n-instead-of-vectorn-t ) .
760
621
622
+ ### C Interop changes
623
+
624
+ With the introduction of ` Vector ` , we have a unique opportunity to fix another
625
+ pain point within the language with regards to C interop. Currently, the Swift
626
+ compiler imports a C array of type ` T[24] ` as a tuple of ` T ` with 24 elements.
627
+ Previously, this was really the only representation that the compiler could pick
628
+ to allow interfacing with C arrays. It was a real challenge working with these
629
+ fields from C in Swift. Consider the following C struct:
630
+
631
+ ``` c
632
+ struct section_64 {
633
+ char sectname[ 16] ;
634
+ char segname[ 16] ;
635
+ uint64_t addr;
636
+ uint64_t size;
637
+ uint32_t offset;
638
+ uint32_t align;
639
+ ...
640
+ };
641
+ ```
642
+
643
+ Today, this gets imported as the following Swift struct:
644
+
645
+ ``` swift
646
+ struct section_64 {
647
+ let sectname: (CChar , CChar , CChar , CChar , CChar , CChar , ... 10 more times)
648
+ let segname: (CChar , CChar , CChar , CChar , CChar , CChar , ... 10 more times)
649
+ let addr: UInt64
650
+ let size: UInt64
651
+ let offset: UInt32
652
+ let align: UInt32
653
+ ...
654
+ }
655
+ ```
656
+
657
+ Using an instance of ` section_64 ` in Swift for the most part is really easy.
658
+ Accessing things like ` addr ` or ` size ` are simple and easy to use, but using the
659
+ ` sectname ` property introduces a level of complexity that isn't so fun to use.
660
+
661
+ ``` swift
662
+ func getSectionName (_ section : section_64) -> String {
663
+ withUnsafePointer (to : section.sectname ) {
664
+ // This is unsafe! 'sectname' isn't guaranteed to have a null byte
665
+ // indicating the end of the C string!
666
+ String (cString : $0 )
667
+ }
668
+ }
669
+
670
+ func iterateSectionNameBytes (_ section : section_64) {
671
+ withUnsafeBytes (to : section.sectname ) {
672
+ for byte in $0 {
673
+ ...
674
+ }
675
+ }
676
+ }
677
+ ```
678
+
679
+ Having to resort to using very unsafe API to do anything useful with imported C
680
+ arrays is not something a memory safe language like Swift should be in the
681
+ business of.
682
+
683
+ Ideally we could migrate the importer from using tuples to this new ` Vector `
684
+ type, however that would be massively source breaking. A previous revision of
685
+ this proposal proposed an _ upcoming_ feature flag that modules can opt into,
686
+ but this poses issues with the current importer implementation with regards to
687
+ inlinable code.
688
+
689
+ Another idea was to import struct fields with C array types twice, one with the
690
+ existing name with a tuple type (as to not break source) and another with some
691
+ ` Vector ` suffix in the name with the ` Vector ` type. This works pretty well for
692
+ struct fields and globals, but it leaves fields and functions who have pointers
693
+ to C arrays in question as well (spelt ` char (*x)[4] ` ). Do we import such
694
+ functions twice using a similar method of giving it a different name? Such a
695
+ solution would also incur a longer deprecation period to eventually having just
696
+ ` Vector ` be imported and no more tuples.
697
+
698
+ We're holding off on any C interop changes here as there are still lots of open
699
+ questions as to what the best path forward is.
700
+
761
701
## Alternatives considered
762
702
763
703
### A name other than ` Vector `
0 commit comments