@@ -951,15 +951,58 @@ For existing Swift code, this proposal is additive.
951
951
952
952
## Effect on ABI stability
953
953
954
+ ### Adding or removing `@noncopyable ` breaks ABI
955
+
954
956
An existing copyable struct or enum cannot be made `@noncopyable ` without
955
- breaking ABI, since existing clients may copy values of the type. However,
956
- an noncopyable type can be made copyable without breaking its ABI.
957
+ breaking ABI, since existing clients may copy values of the type.
958
+
959
+ Ideally, we would allow noncopyable types to become copyable without breaking
960
+ ABI; however, we cannot promise this, due to existing implementation choices we
961
+ have made in the ABI that cause the copyability of a type to have unavoidable
962
+ knock- on effects. In particular, when properties are declared in classes,
963
+ protocols, or public non- `@frozen ` structs, we define the property's ABI to use
964
+ accessors even if the property is stored, with the idea that it should be
965
+ possible to change a property's implementation to change it from a stored to
966
+ computed property, or vice versa, without breaking ABI.
967
+
968
+ The accessors used as ABI today are the traditional `get ` and `set `
969
+ computed accessors, as well as a `_modify` coroutine which can optimize `inout `
970
+ operations and projections into stored properties. `_modify` and `set ` are
971
+ not problematic for noncopyable types. However, `get ` behaves like a
972
+ function, producing the property's value by returning it like a function would,
973
+ and returning requires * consuming * the return value to transfer it to the
974
+ caller. This is not possible for noncopyable stored properties, since the
975
+ value of the property cannot be copied in order to return a copy without
976
+ invalidating the entire containing struct or object.
977
+
978
+ Therefore, properties of noncopyable type need a different ABI in order to
979
+ properly abstract them. In particular, instead of exposing a `get ` accessor
980
+ through abstract interfaces, they must use a `_read` coroutine, which is the
981
+ read- only analog to `_modify`, allowing the implementation to yield a borrow of
982
+ the property value in - place instead of returning by value. This allows for
983
+ noncopyable stored properties to be exposed while still being abstracted enough
984
+ that they can be replaced by a computed implementation, since a `get `- based
985
+ implementation could still work underneath the `read` coroutine by evaluating
986
+ the getter, yielding a borrow of the returned value, then disposing of the
987
+ temporary value.
988
+
989
+ As such, we cannot simply say that making a noncopyable type copyable is an
990
+ ABI- safe change, since doing so will have knock- on effects on the ABI of any
991
+ properties of the type. We could potentially provide a " born noncopyable"
992
+ attribute to indicate that a copyable type should use the noncopyable ABI
993
+ for any properties, as a way to enable the evolution into a copyable type
994
+ while preserving existing ABI. However, it also seems unlikely to us that many
995
+ types would need to evolve between being copyable or not frequently.
996
+
997
+ ### Adding, removing, or changing `deinit ` in a struct or enum
957
998
958
999
An noncopyable type that is not `@frozen ` can add or remove its deinit without
959
- affecting the type's ABI; if frozen, then a deinit cannot be added or removed,
1000
+ affecting the type's ABI. If ` @ frozen`, a deinit cannot be added or removed,
960
1001
but the deinit implementation may change (if the deinit is not additionally
961
1002
`@inlinable `).
962
1003
1004
+ ### Adding noncopyable fields to classes
1005
+
963
1006
A class may add fields of noncopyable type without changing ABI.
964
1007
965
1008
## Effect on API resilience
0 commit comments