Skip to content

Commit 04a26d3

Browse files
committed
Unconditionally conform Attachment to CustomStringConvertible.
This PR adjusts `Attachment`'s conformance to `CustomStringConvertible` such that it conforms even when `AttachableValue` is not `Copyable`. We now check at runtime (by way of protocol shenanigans, of course) whether the attachable value is copyable and, if so, take a different code path than we take if it does not conform.
1 parent 992cd27 commit 04a26d3

File tree

2 files changed

+24
-13
lines changed

2 files changed

+24
-13
lines changed

Sources/Testing/Attachments/Attachment.swift

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ public struct Attachment<AttachableValue> where AttachableValue: Attachable & ~C
9797
extension Attachment: Sendable where AttachableValue: Sendable {}
9898
extension Attachment.Storage: Sendable where AttachableValue: Sendable {}
9999

100+
#if !hasFeature(Embedded)
101+
/// A protocol that describes an attachment with a copyable value.
102+
///
103+
/// We can use this protocol to make runtime decisions about attachments based
104+
/// on whether or not their attachable values are copyable.
105+
private protocol _AttachmentWithCopyableValue {
106+
associatedtype AttachableValue: Attachable & Copyable
107+
var attachableValue: AttachableValue { get }
108+
}
109+
110+
extension Attachment: _AttachmentWithCopyableValue where AttachableValue: Copyable {}
111+
#endif
112+
100113
// MARK: - Initializing an attachment
101114

102115
extension Attachment where AttachableValue: ~Copyable {
@@ -180,21 +193,19 @@ public struct AnyAttachable: AttachableWrapper, Sendable, Copyable {
180193

181194
// MARK: - Describing an attachment
182195

183-
extension Attachment where AttachableValue: ~Copyable {
184-
@_documentation(visibility: private)
185-
public var description: String {
186-
let typeInfo = TypeInfo(describing: AttachableValue.self)
187-
return #""\#(preferredName)": instance of '\#(typeInfo.unqualifiedName)'"#
188-
}
189-
}
190-
191-
extension Attachment: CustomStringConvertible {
196+
extension Attachment: CustomStringConvertible where AttachableValue: ~Copyable {
192197
/// @Metadata {
193198
/// @Available(Swift, introduced: 6.2)
194199
/// @Available(Xcode, introduced: 26.0)
195200
/// }
196201
public var description: String {
197-
#""\#(preferredName)": \#(String(describingForTest: attachableValue))"#
202+
#if !hasFeature(Embedded)
203+
if let selfCopy = self as? any _AttachmentWithCopyableValue {
204+
return #""\#(preferredName)": \#(String(describingForTest: selfCopy.attachableValue))"#
205+
}
206+
#endif
207+
let typeInfo = TypeInfo(describing: AttachableValue.self)
208+
return #""\#(preferredName)": instance of '\#(typeInfo.unqualifiedName)'"#
198209
}
199210
}
200211

Tests/TestingTests/AttachmentTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ struct AttachmentTests {
5050
let attachableValue = MySendableAttachable(string: "<!doctype html>")
5151
let attachment = Attachment(attachableValue, named: "AttachmentTests.saveValue.html")
5252
#expect(String(describing: attachment).contains(#""\#(attachment.preferredName)""#))
53-
#expect(attachment.description.contains("MySendableAttachable("))
53+
#expect(String(describing: attachment).contains("MySendableAttachable("))
5454
}
5555

5656
#if compiler(>=6.3) || !os(Windows) // WORKAROUND: swift-#84184
5757
@Test func moveOnlyDescription() {
5858
let attachableValue = MyAttachable(string: "<!doctype html>")
5959
let attachment = Attachment(attachableValue, named: "AttachmentTests.saveValue.html")
60-
#expect(attachment.description.contains(#""\#(attachment.preferredName)""#))
61-
#expect(attachment.description.contains("'MyAttachable'"))
60+
#expect(String(describing: attachment).contains(#""\#(attachment.preferredName)""#))
61+
#expect(String(describing: attachment).contains("'MyAttachable'"))
6262
}
6363
#endif
6464

0 commit comments

Comments
 (0)