Skip to content

Commit c95db1e

Browse files
committed
Allow CustomStringConvertible et al: ~Copyable
1 parent 4419ce5 commit c95db1e

File tree

7 files changed

+274
-34
lines changed

7 files changed

+274
-34
lines changed

stdlib/public/core/Mirror.swift

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,9 @@ extension String {
590590
// also preserve source compatibility for clients which accidentally
591591
// used init(stringInterpolationSegment:) through constructs like
592592
// myArray.map(String.init).
593+
//
594+
// Unfortunately they create ambiguity by being parallel to each
595+
// other, so many overloads are required.
593596

594597
/// Creates a string representing the given value.
595598
///
@@ -631,10 +634,100 @@ extension String {
631634
/// print(String(describing: p))
632635
/// // Prints "(21, 30)"
633636
@inlinable
637+
@_alwaysEmitIntoClient
638+
public init<Subject: CustomStringConvertible & ~Copyable>(describing instance: borrowing Subject) {
639+
self = instance.description
640+
}
641+
642+
/// Creates a string representing the given value.
643+
///
644+
/// Use this initializer to convert an instance of any type to its preferred
645+
/// representation as a `String` instance. The initializer creates the
646+
/// string representation of `instance` in one of the following ways,
647+
/// depending on its protocol conformance:
648+
///
649+
/// - If `instance` conforms to the `TextOutputStreamable` protocol, the
650+
/// result is obtained by calling `instance.write(to: s)` on an empty
651+
/// string `s`.
652+
/// - If `instance` conforms to the `CustomStringConvertible` protocol, the
653+
/// result is `instance.description`.
654+
/// - If `instance` conforms to the `CustomDebugStringConvertible` protocol,
655+
/// the result is `instance.debugDescription`.
656+
/// - An unspecified result is supplied automatically by the Swift standard
657+
/// library.
658+
///
659+
/// For example, this custom `Point` struct uses the default representation
660+
/// supplied by the standard library.
661+
///
662+
/// struct Point {
663+
/// let x: Int, y: Int
664+
/// }
665+
///
666+
/// let p = Point(x: 21, y: 30)
667+
/// print(String(describing: p))
668+
/// // Prints "Point(x: 21, y: 30)"
669+
///
670+
/// After adding `CustomStringConvertible` conformance by implementing the
671+
/// `description` property, `Point` provides its own custom representation.
672+
///
673+
/// extension Point: CustomStringConvertible {
674+
/// var description: String {
675+
/// return "(\(x), \(y))"
676+
/// }
677+
/// }
678+
///
679+
/// print(String(describing: p))
680+
/// // Prints "(21, 30)"
634681
public init<Subject: CustomStringConvertible>(describing instance: Subject) {
635682
self = instance.description
636683
}
637684

685+
/// Creates a string representing the given value.
686+
///
687+
/// Use this initializer to convert an instance of any type to its preferred
688+
/// representation as a `String` instance. The initializer creates the
689+
/// string representation of `instance` in one of the following ways,
690+
/// depending on its protocol conformance:
691+
///
692+
/// - If `instance` conforms to the `TextOutputStreamable` protocol, the
693+
/// result is obtained by calling `instance.write(to: s)` on an empty
694+
/// string `s`.
695+
/// - If `instance` conforms to the `CustomStringConvertible` protocol, the
696+
/// result is `instance.description`.
697+
/// - If `instance` conforms to the `CustomDebugStringConvertible` protocol,
698+
/// the result is `instance.debugDescription`.
699+
/// - An unspecified result is supplied automatically by the Swift standard
700+
/// library.
701+
///
702+
/// For example, this custom `Point` struct uses the default representation
703+
/// supplied by the standard library.
704+
///
705+
/// struct Point {
706+
/// let x: Int, y: Int
707+
/// }
708+
///
709+
/// let p = Point(x: 21, y: 30)
710+
/// print(String(describing: p))
711+
/// // Prints "Point(x: 21, y: 30)"
712+
///
713+
/// After adding `CustomStringConvertible` conformance by implementing the
714+
/// `description` property, `Point` provides its own custom representation.
715+
///
716+
/// extension Point: CustomStringConvertible {
717+
/// var description: String {
718+
/// return "(\(x), \(y))"
719+
/// }
720+
/// }
721+
///
722+
/// print(String(describing: p))
723+
/// // Prints "(21, 30)"
724+
@inlinable
725+
@_alwaysEmitIntoClient
726+
public init<Subject: TextOutputStreamable & ~Copyable>(describing instance: borrowing Subject) {
727+
self.init()
728+
instance.write(to: &self)
729+
}
730+
638731
/// Creates a string representing the given value.
639732
///
640733
/// Use this initializer to convert an instance of any type to its preferred
@@ -680,6 +773,53 @@ extension String {
680773
instance.write(to: &self)
681774
}
682775

776+
/// Creates a string representing the given value.
777+
///
778+
/// Use this initializer to convert an instance of any type to its preferred
779+
/// representation as a `String` instance. The initializer creates the
780+
/// string representation of `instance` in one of the following ways,
781+
/// depending on its protocol conformance:
782+
///
783+
/// - If `instance` conforms to the `TextOutputStreamable` protocol, the
784+
/// result is obtained by calling `instance.write(to: s)` on an empty
785+
/// string `s`.
786+
/// - If `instance` conforms to the `CustomStringConvertible` protocol, the
787+
/// result is `instance.description`.
788+
/// - If `instance` conforms to the `CustomDebugStringConvertible` protocol,
789+
/// the result is `instance.debugDescription`.
790+
/// - An unspecified result is supplied automatically by the Swift standard
791+
/// library.
792+
///
793+
/// For example, this custom `Point` struct uses the default representation
794+
/// supplied by the standard library.
795+
///
796+
/// struct Point {
797+
/// let x: Int, y: Int
798+
/// }
799+
///
800+
/// let p = Point(x: 21, y: 30)
801+
/// print(String(describing: p))
802+
/// // Prints "Point(x: 21, y: 30)"
803+
///
804+
/// After adding `CustomStringConvertible` conformance by implementing the
805+
/// `description` property, `Point` provides its own custom representation.
806+
///
807+
/// extension Point: CustomStringConvertible {
808+
/// var description: String {
809+
/// return "(\(x), \(y))"
810+
/// }
811+
/// }
812+
///
813+
/// print(String(describing: p))
814+
/// // Prints "(21, 30)"
815+
@inlinable
816+
@_alwaysEmitIntoClient
817+
public init<Subject>(describing instance: borrowing Subject)
818+
where Subject: CustomStringConvertible & TextOutputStreamable & ~Copyable
819+
{
820+
self = instance.description
821+
}
822+
683823
/// Creates a string representing the given value.
684824
///
685825
/// Use this initializer to convert an instance of any type to its preferred

stdlib/public/core/OutputStream.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ extension TextOutputStream {
9999
/// To add `TextOutputStreamable` conformance to a custom type, implement the
100100
/// required `write(to:)` method. Call the given output stream's `write(_:)`
101101
/// method in your implementation.
102-
public protocol TextOutputStreamable {
102+
public protocol TextOutputStreamable: ~Copyable {
103103
/// Writes a textual representation of this instance into the given output
104104
/// stream.
105105
func write<Target: TextOutputStream>(to target: inout Target)
@@ -147,7 +147,7 @@ public protocol TextOutputStreamable {
147147
///
148148
/// print(p)
149149
/// // Prints "(21, 30)"
150-
public protocol CustomStringConvertible {
150+
public protocol CustomStringConvertible: ~Copyable {
151151
/// A textual representation of this instance.
152152
///
153153
/// Calling this property directly is discouraged. Instead, convert an
@@ -182,7 +182,7 @@ public protocol CustomStringConvertible {
182182
/// The description property of a conforming type must be a value-preserving
183183
/// representation of the original value. As such, it should be possible to
184184
/// re-create an instance from its string representation.
185-
public protocol LosslessStringConvertible: CustomStringConvertible {
185+
public protocol LosslessStringConvertible: CustomStringConvertible, ~Copyable {
186186
/// Instantiates an instance of the conforming type from a string
187187
/// representation.
188188
init?(_ description: String)
@@ -239,7 +239,7 @@ public protocol LosslessStringConvertible: CustomStringConvertible {
239239
///
240240
/// print(String(reflecting: p))
241241
/// // Prints "(21, 30)"
242-
public protocol CustomDebugStringConvertible {
242+
public protocol CustomDebugStringConvertible: ~Copyable {
243243
/// A textual representation of this instance, suitable for debugging.
244244
///
245245
/// Calling this property directly is discouraged. Instead, convert an

stdlib/public/core/StringInterpolation.swift

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,9 @@ public struct DefaultStringInterpolation: StringInterpolationProtocol, Sendable
105105
/// print(message)
106106
/// // Prints "If one cookie costs 2 dollars, 3 cookies cost 6 dollars."
107107
@inlinable
108-
public mutating func appendInterpolation<T>(_ value: T)
109-
where T: TextOutputStreamable, T: CustomStringConvertible
108+
@_preInverseGenerics
109+
public mutating func appendInterpolation<T>(_ value: borrowing T)
110+
where T: TextOutputStreamable, T: CustomStringConvertible, T: ~Copyable
110111
{
111112
value.write(to: &self)
112113
}
@@ -127,8 +128,9 @@ public struct DefaultStringInterpolation: StringInterpolationProtocol, Sendable
127128
/// print(message)
128129
/// // Prints "If one cookie costs 2 dollars, 3 cookies cost 6 dollars."
129130
@inlinable
130-
public mutating func appendInterpolation<T>(_ value: T)
131-
where T: TextOutputStreamable
131+
@_preInverseGenerics
132+
public mutating func appendInterpolation<T>(_ value: borrowing T)
133+
where T: TextOutputStreamable & ~Copyable
132134
{
133135
value.write(to: &self)
134136
}
@@ -151,8 +153,9 @@ public struct DefaultStringInterpolation: StringInterpolationProtocol, Sendable
151153
/// print(message)
152154
/// // Prints "If one cookie costs 2 dollars, 3 cookies cost 6 dollars."
153155
@inlinable
154-
public mutating func appendInterpolation<T>(_ value: T)
155-
where T: CustomStringConvertible
156+
@_preInverseGenerics
157+
public mutating func appendInterpolation<T>(_ value: borrowing T)
158+
where T: CustomStringConvertible, T: ~Copyable
156159
{
157160
value.description.write(to: &self)
158161
}
@@ -175,7 +178,7 @@ public struct DefaultStringInterpolation: StringInterpolationProtocol, Sendable
175178
/// print(message)
176179
/// // Prints "If one cookie costs 2 dollars, 3 cookies cost 6 dollars."
177180
@inlinable
178-
public mutating func appendInterpolation<T>(_ value: T) {
181+
public mutating func appendInterpolation<T>(_ value: borrowing T) {
179182
#if !$Embedded
180183
_print_unlocked(value, &self)
181184
#else
@@ -217,13 +220,15 @@ extension DefaultStringInterpolation {
217220
/// - value: The value to include in a string interpolation, if non-`nil`.
218221
/// - default: The string to include if `value` is `nil`.
219222
@_alwaysEmitIntoClient
223+
@_preInverseGenerics
220224
public mutating func appendInterpolation<T>(
221-
_ value: T?,
225+
_ value: borrowing T?,
222226
default: @autoclosure () -> some StringProtocol
223-
) where T: TextOutputStreamable, T: CustomStringConvertible {
224-
if let value {
227+
) where T: TextOutputStreamable, T: CustomStringConvertible, T: ~Copyable {
228+
switch value {
229+
case let value?:
225230
self.appendInterpolation(value)
226-
} else {
231+
case nil:
227232
self.appendInterpolation(`default`())
228233
}
229234
}
@@ -247,13 +252,15 @@ extension DefaultStringInterpolation {
247252
/// - value: The value to include in a string interpolation, if non-`nil`.
248253
/// - default: The string to include if `value` is `nil`.
249254
@_alwaysEmitIntoClient
255+
@_preInverseGenerics
250256
public mutating func appendInterpolation<T>(
251-
_ value: T?,
257+
_ value: borrowing T?,
252258
default: @autoclosure () -> some StringProtocol
253-
) where T: TextOutputStreamable {
254-
if let value {
259+
) where T: TextOutputStreamable & ~Copyable {
260+
switch value {
261+
case let value?:
255262
self.appendInterpolation(value)
256-
} else {
263+
case nil:
257264
self.appendInterpolation(`default`())
258265
}
259266
}
@@ -277,13 +284,15 @@ extension DefaultStringInterpolation {
277284
/// - value: The value to include in a string interpolation, if non-`nil`.
278285
/// - default: The string to include if `value` is `nil`.
279286
@_alwaysEmitIntoClient
287+
@_preInverseGenerics
280288
public mutating func appendInterpolation<T>(
281-
_ value: T?,
289+
_ value: borrowing T?,
282290
default: @autoclosure () -> some StringProtocol
283-
) where T: CustomStringConvertible {
284-
if let value {
291+
) where T: CustomStringConvertible, T: ~Copyable {
292+
switch value {
293+
case let value?:
285294
self.appendInterpolation(value)
286-
} else {
295+
case nil:
287296
self.appendInterpolation(`default`())
288297
}
289298
}
@@ -311,9 +320,10 @@ extension DefaultStringInterpolation {
311320
_ value: T?,
312321
default: @autoclosure () -> some StringProtocol
313322
) {
314-
if let value {
323+
switch value {
324+
case let value?:
315325
self.appendInterpolation(value)
316-
} else {
326+
case nil:
317327
self.appendInterpolation(`default`())
318328
}
319329
}

test/api-digester/Outputs/stability-stdlib-source-base.swift.expected

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ Constructor ContiguousArray.init(unsafeUninitializedCapacity:initializingWith:)
5353
Constructor ContiguousArray.init(unsafeUninitializedCapacity:initializingWith:) has parameter 1 type change from (inout Swift.UnsafeMutableBufferPointer<Element>, inout Swift.Int) throws -> Swift.Void to (inout Swift.UnsafeMutableBufferPointer<Element>, inout Swift.Int) throws(E) -> Swift.Void
5454
Constructor ContiguousArray.init(unsafeUninitializedCapacity:initializingWith:) is now without rethrows
5555

56+
Protocol LosslessStringConvertible has generic signature change from <Self : Swift.CustomStringConvertible> to <Self : Swift.CustomStringConvertible, Self : ~Copyable>
5657
Protocol SIMDScalar has generic signature change from <Self == Self.SIMD16Storage.Scalar, Self.SIMD16Storage : Swift.SIMDStorage, Self.SIMD2Storage : Swift.SIMDStorage, Self.SIMD32Storage : Swift.SIMDStorage, Self.SIMD4Storage : Swift.SIMDStorage, Self.SIMD64Storage : Swift.SIMDStorage, Self.SIMD8Storage : Swift.SIMDStorage, Self.SIMDMaskScalar : Swift.FixedWidthInteger, Self.SIMDMaskScalar : Swift.SIMDScalar, Self.SIMDMaskScalar : Swift.SignedInteger, Self.SIMD16Storage.Scalar == Self.SIMD2Storage.Scalar, Self.SIMD2Storage.Scalar == Self.SIMD32Storage.Scalar, Self.SIMD32Storage.Scalar == Self.SIMD4Storage.Scalar, Self.SIMD4Storage.Scalar == Self.SIMD64Storage.Scalar, Self.SIMD64Storage.Scalar == Self.SIMD8Storage.Scalar> to <Self : Swift.BitwiseCopyable, Self == Self.SIMD16Storage.Scalar, Self.SIMD16Storage : Swift.SIMDStorage, Self.SIMD2Storage : Swift.SIMDStorage, Self.SIMD32Storage : Swift.SIMDStorage, Self.SIMD4Storage : Swift.SIMDStorage, Self.SIMD64Storage : Swift.SIMDStorage, Self.SIMD8Storage : Swift.SIMDStorage, Self.SIMDMaskScalar : Swift.FixedWidthInteger, Self.SIMDMaskScalar : Swift.SIMDScalar, Self.SIMDMaskScalar : Swift.SignedInteger, Self.SIMDMaskScalar == Self.SIMDMaskScalar.SIMDMaskScalar, Self.SIMD16Storage.Scalar == Self.SIMD2Storage.Scalar, Self.SIMD2Storage.Scalar == Self.SIMD32Storage.Scalar, Self.SIMD32Storage.Scalar == Self.SIMD4Storage.Scalar, Self.SIMD4Storage.Scalar == Self.SIMD64Storage.Scalar, Self.SIMD64Storage.Scalar == Self.SIMD8Storage.Scalar>
5758

5859
Protocol AdditiveArithmetic has added inherited protocol Copyable
@@ -72,15 +73,13 @@ Protocol CodingKey has added inherited protocol Escapable
7273
Protocol Collection has added inherited protocol Copyable
7374
Protocol Collection has added inherited protocol Escapable
7475
Protocol Comparable has added inherited protocol Escapable
75-
Protocol CustomDebugStringConvertible has added inherited protocol Copyable
7676
Protocol CustomDebugStringConvertible has added inherited protocol Escapable
7777
Protocol CustomLeafReflectable has added inherited protocol Copyable
7878
Protocol CustomLeafReflectable has added inherited protocol Escapable
7979
Protocol CustomPlaygroundDisplayConvertible has added inherited protocol Copyable
8080
Protocol CustomPlaygroundDisplayConvertible has added inherited protocol Escapable
8181
Protocol CustomReflectable has added inherited protocol Copyable
8282
Protocol CustomReflectable has added inherited protocol Escapable
83-
Protocol CustomStringConvertible has added inherited protocol Copyable
8483
Protocol CustomStringConvertible has added inherited protocol Escapable
8584
Protocol Decodable has added inherited protocol Copyable
8685
Protocol Decodable has added inherited protocol Escapable
@@ -129,7 +128,6 @@ Protocol LazyCollectionProtocol has added inherited protocol Copyable
129128
Protocol LazyCollectionProtocol has added inherited protocol Escapable
130129
Protocol LazySequenceProtocol has added inherited protocol Copyable
131130
Protocol LazySequenceProtocol has added inherited protocol Escapable
132-
Protocol LosslessStringConvertible has added inherited protocol Copyable
133131
Protocol LosslessStringConvertible has added inherited protocol Escapable
134132
Protocol MirrorPath has added inherited protocol Copyable
135133
Protocol MirrorPath has added inherited protocol Escapable
@@ -176,7 +174,6 @@ Protocol StringProtocol has added inherited protocol Copyable
176174
Protocol StringProtocol has added inherited protocol Escapable
177175
Protocol TextOutputStream has added inherited protocol Copyable
178176
Protocol TextOutputStream has added inherited protocol Escapable
179-
Protocol TextOutputStreamable has added inherited protocol Copyable
180177
Protocol TextOutputStreamable has added inherited protocol Escapable
181178
Protocol UnicodeCodec has added inherited protocol Copyable
182179
Protocol UnicodeCodec has added inherited protocol Escapable
@@ -401,3 +398,12 @@ Func Comparable.>=(_:_:) has generic signature change from <Self where Self : Sw
401398
Func Comparable.>=(_:_:) has parameter 0 changing from Default to Shared
402399
Func Comparable.>=(_:_:) has parameter 1 changing from Default to Shared
403400

401+
// CustomStringConvertible etc: ~Copyable
402+
Accessor CustomDebugStringConvertible.debugDescription.Get() has generic signature change from <Self where Self : Swift.CustomDebugStringConvertible> to <Self where Self : Swift.CustomDebugStringConvertible, Self : ~Copyable>
403+
Accessor CustomStringConvertible.description.Get() has generic signature change from <Self where Self : Swift.CustomStringConvertible> to <Self where Self : Swift.CustomStringConvertible, Self : ~Copyable>
404+
Constructor LosslessStringConvertible.init(_:) has generic signature change from <Self where Self : Swift.LosslessStringConvertible> to <Self where Self : Swift.LosslessStringConvertible, Self : ~Copyable>
405+
Func DefaultStringInterpolation.appendInterpolation(_:) has generic signature change from <T where T : Swift.CustomStringConvertible, T : Swift.TextOutputStreamable> to <T where T : Swift.CustomStringConvertible, T : Swift.TextOutputStreamable, T : ~Copyable>
406+
Func DefaultStringInterpolation.appendInterpolation(_:) has generic signature change from <T where T : Swift.CustomStringConvertible> to <T where T : Swift.CustomStringConvertible, T : ~Copyable>
407+
Func DefaultStringInterpolation.appendInterpolation(_:) has generic signature change from <T where T : Swift.TextOutputStreamable> to <T where T : Swift.TextOutputStreamable, T : ~Copyable>
408+
Func DefaultStringInterpolation.appendInterpolation(_:) has parameter 0 changing from Default to Shared
409+
Func TextOutputStreamable.write(to:) has generic signature change from <Self, Target where Self : Swift.TextOutputStreamable, Target : Swift.TextOutputStream> to <Self, Target where Self : Swift.TextOutputStreamable, Target : Swift.TextOutputStream, Self : ~Copyable>

0 commit comments

Comments
 (0)