2
2
3
3
* Proposal: [ SE-0427] ( 0427-noncopyable-generics.md )
4
4
* Authors: [ Kavon Farvardin] ( https://github.com/kavon ) , [ Tim Kientzle] ( https://github.com/tbkka ) , [ Slava Pestov] ( https://github.com/slavapestov )
5
- * Review Manager: [ Holly Borla] ( https://github.com/hborla )
6
- * Status: ** Active Review (March 8 - March 22 , 2024)**
5
+ * Review Manager: [ Holly Borla] ( https://github.com/hborla ) , [ Ben Cohen ] ( https://github.com/airspeedswift )
6
+ * Status: ** Active Review (July 1 - July 10 , 2024)**
7
7
* Implementation: On ` main ` gated behind ` -enable-experimental-feature NoncopyableGenerics `
8
8
* Previous Proposal: [ SE-0390: Noncopyable structs and enums] ( 0390-noncopyable-structs-and-enums.md )
9
- * Review: ([ pitch] ( https://forums.swift.org/t/pitch-noncopyable-generics/68180 ) )
9
+ * Review: ([ pitch] ( https://forums.swift.org/t/pitch-noncopyable-generics/68180 ) ) ( [ first review ] ( https://forums.swift.org/t/se-0427-noncopyable-generics/70525 ) )
10
10
11
11
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
12
12
** Table of Contents**
23
23
- [ Default conformances and suppression] ( #default-conformances-and-suppression )
24
24
- [ Struct, enum and class extensions] ( #struct-enum-and-class-extensions )
25
25
- [ Protocol extensions] ( #protocol-extensions )
26
- - [ Associated types] ( #associated-types )
27
26
- [ Protocol inheritance] ( #protocol-inheritance )
28
27
- [ Conformance to ` Copyable ` ] ( #conformance-to-copyable )
29
28
- [ Classes] ( #classes )
32
31
- [ ABI Compatibility] ( #abi-compatibility )
33
32
- [ Alternatives Considered] ( #alternatives-considered )
34
33
- [ Alternative spellings] ( #alternative-spellings )
34
+ - [ Associated types without defaulting behavior] ( #associated-types-without-defaulting-behavior )
35
35
- [ Inferred conditional copyability] ( #inferred-conditional-copyability )
36
36
- [ Extension defaults] ( #extension-defaults )
37
37
- [ Recursive ` Copyable ` ] ( #recursive-copyable )
38
38
- [ ` ~Copyable ` as logical negation] ( #copyable-as-logical-negation )
39
39
- [ Future Directions] ( #future-directions )
40
+ - [ Suppressed associated types] ( #suppressed-associated-types )
40
41
- [ Standard library adoption] ( #standard-library-adoption )
41
42
- [ Tuples and parameter packs] ( #tuples-and-parameter-packs )
42
43
- [ ` ~Escapable ` ] ( #escapable )
@@ -81,7 +82,7 @@ We begin by recalling the restrictions from SE-0390:
81
82
82
83
1 . A noncopyable type could not appear in the generic argument of some other generic type.
83
84
2 . A noncopyable type could not conform to protocols.
84
- 3 . A noncopyable type could not witness an associated type requirement .
85
+ 3 . A noncopyable type could not be boxed as an existential .
85
86
86
87
This proposal builds on the ` ~Copyable ` notation introduced in SE-0390, and
87
88
introduces three fundamental concepts that together eliminate these
@@ -205,7 +206,7 @@ unless explicitly suppressed:
205
206
1 . A struct, enum or class declaration.
206
207
2 . A generic parameter declaration.
207
208
3 . A protocol declaration.
208
- 4 . An associated type declaration.
209
+ 4 . An associated type declaration; does not support suppression (see Future Directions) .
209
210
5 . The ` Self ` type of a protocol extension.
210
211
6 . The generic parameters of a concrete extension.
211
212
@@ -296,7 +297,7 @@ extension Horse where Hay: ~Copyable {...} // error
296
297
### Protocol extensions
297
298
298
299
Where possible, we wish to allow the user to change an existing protocol to
299
- accomodate noncopyable conforming types, without changing the meaning of existing
300
+ accommodate noncopyable conforming types, without changing the meaning of existing
300
301
code.
301
302
302
303
For this reason, an extension of a ` ~Copyable ` protocol also introduces a default
@@ -314,47 +315,14 @@ extension EventLog /* where Self: Copyable */ {
314
315
}
315
316
```
316
317
317
- To write a completely unconstrained protocol extension, suppress the conformance
318
- on ` Self ` :
318
+ To write an unconstrained protocol extension, suppress the conformance on ` Self ` :
319
319
``` swift
320
320
extension EventLog where Self : ~Copyable {
321
321
...
322
322
}
323
323
```
324
-
325
- ### Associated types
326
-
327
- The default conformance in a protocol extension applies only to ` Self ` , and not
328
- the associated types of ` Self ` . For example, we first declare a protocol with a
329
- ` ~Copyable ` associated type:
330
- ``` swift
331
- protocol Manager {
332
- associatedtype Resource : ~ Copyable
333
- }
334
- ```
335
- Now, a protocol extension of ` Manager ` does _ not_ carry an implicit
336
- ` Self.Resource: Copyable ` requirement:
337
- ``` swift
338
- extension Manager {
339
- func f (resource : Resource) {
340
- // `resource' cannot be copied here!
341
- }
342
- }
343
- ```
344
- For this reason, while adding ` ~Copyable ` to the inheritance clause of a protocol
345
- is a source-compatible change, the same with an _ associated type_ is not
346
- source compatible. The designer of a new protocol must decide which associated
347
- types are ` ~Copyable ` up-front.
348
-
349
- Requirements on associated types can be written in the associated type's
350
- inheritance clause, or in a ` where ` clause, or on the protocol itself. As
351
- with ordinary requirements, all three of the following forms define the same
352
- protocol:
353
- ``` swift
354
- protocol P { associatedtype A : ~ Copyable }
355
- protocol P { associatedtype A where A: ~Copyable }
356
- protocol P where A: ~Copyable { associatedtype A }
357
- ```
324
+ Associated types cannot have their ` Copyable ` requirement suppressed
325
+ (see Future Directions).
358
326
359
327
### Protocol inheritance
360
328
@@ -368,22 +336,6 @@ protocol CasinoToken: Token, ~Copyable {}
368
336
Again, because ` ~Copyable ` suppresses a default conformance instead of introducing
369
337
a new kind of requirement, it is not propagated through protocol inheritance.
370
338
371
- If a base protocol declares an associated type with a suppressed conformance
372
- to ` Copyable ` , and a derived protocol re-states the associated type, a
373
- default conformance is introduced in the derived protocol, unless it is again
374
- suppressed:
375
- ``` swift
376
- protocol Base {
377
- associatedtype A : ~ Copyable
378
- func f () -> A
379
- }
380
-
381
- protocol Derived : Base {
382
- associatedtype A /* : Copyable */
383
- func g () -> A
384
- }
385
- ```
386
-
387
339
### Conformance to ` Copyable `
388
340
389
341
Structs and enums conform to ` Copyable ` unconditionally by default, but a
@@ -399,11 +351,11 @@ We would like `List<Int>` to be `Copyable` since `Int` is, while still being
399
351
able to use a noncopyable element type, like ` List<FileDescriptor> ` . We do
400
352
this by declaring a _ conditional conformance_ :
401
353
``` swift
402
- extension List : Copyable /* where T: Copyable */ {}
354
+ extension List : Copyable where T: Copyable {}
403
355
```
404
- Note that no ` where ` clause needs to be written, because by the rules above,
405
- the default conformances here will already range over all generic parameters
406
- of the type .
356
+ Note that the ` where ` clause needs to be written, because a conformance to
357
+ ` Copyable ` declared in an extension does _ not _ automatically add any other
358
+ requirements, unlike other extensions .
407
359
408
360
A conditional ` Copyable ` conformance is not permitted if the
409
361
struct or enum declares a ` deinit ` . Deterministic destruction requires the
@@ -448,11 +400,6 @@ not permitted to make `Copyable` conditional on any other kind of requirement:
448
400
``` swift
449
401
extension Pair : Copyable where T == Array <Int > {} // error
450
402
```
451
- Nor can ` Copyable ` be conditional on the copyability of an associated type:
452
- ``` swift
453
- struct ManagerManager <T : Manager >: ~ Copyable {}
454
- extension ManagerManager : Copyable where T.Resource: Copyable {} // error
455
- ```
456
403
457
404
Conditional ` Copyable ` conformance must be declared in the same source
458
405
file as the struct or enum itself. Unlike conformance to other protocols,
@@ -528,6 +475,69 @@ require extreme care to use correctly.
528
475
The spelling of ` ~Copyable ` generalizes the existing syntax introduced in
529
476
SE-0390, and changing it is out of scope for this proposal.
530
477
478
+ ### Associated types without defaulting behavior
479
+
480
+ A simple design for suppressed associated types was considered, where the
481
+ default conformance in a protocol extension applies only to ` Self ` , and not
482
+ the associated types of ` Self ` . For example, we first declare a protocol with a
483
+ ` ~Copyable ` associated type:
484
+ ``` swift
485
+ protocol Manager {
486
+ associatedtype Resource : ~ Copyable
487
+ }
488
+ ```
489
+ Now, a protocol extension of ` Manager ` does _ not_ carry an implicit
490
+ ` Self.Resource: Copyable ` requirement:
491
+ ``` swift
492
+ extension Manager {
493
+ func f (resource : Resource) {
494
+ // `resource' cannot be copied here!
495
+ }
496
+ }
497
+ ```
498
+ For this reason, while adding ` ~Copyable ` to the inheritance clause of a protocol
499
+ is a source-compatible change, the same with an _ associated type_ is not
500
+ source compatible. The designer of a new protocol must decide which associated
501
+ types are ` ~Copyable ` up-front.
502
+
503
+ Requirements on associated types can be written in the associated type's
504
+ inheritance clause, or in a ` where ` clause, or on the protocol itself. As
505
+ with ordinary requirements, all three of the following forms define the same
506
+ protocol:
507
+ ``` swift
508
+ protocol P { associatedtype A : ~ Copyable }
509
+ protocol P { associatedtype A where A: ~Copyable }
510
+ protocol P where A: ~Copyable { associatedtype A }
511
+ ```
512
+
513
+ If a base protocol declares an associated type with a suppressed conformance
514
+ to ` Copyable ` , and a derived protocol re-states the associated type, a
515
+ default conformance is introduced in the derived protocol, unless it is again
516
+ suppressed:
517
+ ``` swift
518
+ protocol Base {
519
+ associatedtype A : ~ Copyable
520
+ func f () -> A
521
+ }
522
+
523
+ protocol Derived : Base {
524
+ associatedtype A /* : Copyable */
525
+ func g () -> A
526
+ }
527
+ ```
528
+
529
+ Finally, conformance to ` Copyable ` cannot be conditional on the copyability of
530
+ an associated type:
531
+ ``` swift
532
+ struct ManagerManager <T : Manager >: ~ Copyable {}
533
+ extension ManagerManager : Copyable where T.Resource: Copyable {} // error
534
+ ```
535
+
536
+ This design for associated types was initially implemented but ultimately
537
+ removed from this proposal, because of the source compatibility issues. A more
538
+ comprehensive design that allows for some way of preserving source compatibility
539
+ requires a separate proposal due to the open design issues.
540
+
531
541
### Inferred conditional copyability
532
542
533
543
A struct or enum can opt out of copyability with ` ~Copyable ` , and then possibly
@@ -594,7 +604,7 @@ The behavior of default `Copyable` conformance on associated types prevents
594
604
existing protocols from adopting `~Copyable` on their associated types in a
595
605
source compatible way.
596
606
597
- For example, suppose we attempt to change `IteratorProtocol` to accomodate
607
+ For example, suppose we attempt to change `IteratorProtocol` to accommodate
598
608
noncopyable element types:
599
609
```swift
600
610
protocol IteratorProtocol: ~ Copyable {
@@ -657,6 +667,14 @@ usable model and we have not explored this further.
657
667
658
668
## Future Directions
659
669
670
+ ### Suppressed associated types
671
+
672
+ Supporting the full generality of associated types with suppressed Copyable
673
+ requirements, while providing a mechanism to preserve source compatibility is
674
+ a highly desirable goal. At the same time, it is a large, open design problem.
675
+ A few ideas were considered (see Alternatives Considered) but it was ultimately
676
+ determined to be too complex to tackle in this proposal.
677
+
660
678
### Standard library adoption
661
679
662
680
The `Optional ` and `UnsafePointer ` family of types can support noncopyable types
0 commit comments