Skip to content

Commit 8d0d9d0

Browse files
authored
[Debug] Add user friendly diagnostic when @DebugDescription is atached to a generic (#75302)
- **Explanation**: Emit a user friendly diagnostic when `@DebugDescription` is attached to a generic type definition. - **Scope**: This will not break existing code. Use of `@DebugDescription` previously produced an unhelpful error diagnostic, this change makes the error diagnostic clear. - **Original PRs**: #75307 - **Risk**: No risk. - **Testing**: Swift tests, CI - **Reviewers**: @hborla, @stephentyrone, @DougGregor
1 parent 0558998 commit 8d0d9d0

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

lib/Macros/Sources/SwiftMacros/DebugDescriptionMacro.swift

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,35 @@ import SwiftDiagnostics
1717
public enum DebugDescriptionMacro {}
1818
public enum _DebugDescriptionPropertyMacro {}
1919

20+
/// The member role is used only to perform diagnostics. The member role ensures any diagnostics are emitted once per
21+
/// type. The macro's core behavior begins with the `MemberAttributeMacro` conformance.
22+
extension DebugDescriptionMacro: MemberMacro {
23+
public static func expansion(
24+
of node: AttributeSyntax,
25+
providingMembersOf declaration: some DeclGroupSyntax,
26+
in context: some MacroExpansionContext
27+
)
28+
throws -> [DeclSyntax]
29+
{
30+
guard !declaration.is(ProtocolDeclSyntax.self) else {
31+
let message: ErrorMessage = "cannot be attached to a protocol"
32+
context.diagnose(node: node, error: message)
33+
return []
34+
}
35+
36+
guard declaration.asProtocol(WithGenericParametersSyntax.self)?.genericParameterClause == nil else {
37+
let message: ErrorMessage = "cannot be attached to a generic definition"
38+
context.diagnose(node: node, error: message)
39+
return []
40+
}
41+
42+
return []
43+
}
44+
}
45+
2046
/// A macro which orchestrates conversion of a description property to an LLDB type summary.
2147
///
22-
/// The job of conversion is split across two macros. This macro performs some analysis on the attached
48+
/// The process of conversion is split across multiple macros/roles. This role performs some analysis on the attached
2349
/// type, and then delegates to `@_DebugDescriptionProperty` to perform the conversion step.
2450
extension DebugDescriptionMacro: MemberAttributeMacro {
2551
public static func expansion(
@@ -31,8 +57,12 @@ extension DebugDescriptionMacro: MemberAttributeMacro {
3157
throws -> [AttributeSyntax]
3258
{
3359
guard !declaration.is(ProtocolDeclSyntax.self) else {
34-
let message: ErrorMessage = "cannot be attached to a protocol"
35-
context.diagnose(node: node, error: message)
60+
// Diagnostics for this case are emitted by the `MemberMacro` conformance.
61+
return []
62+
}
63+
64+
guard declaration.asProtocol(WithGenericParametersSyntax.self)?.genericParameterClause == nil else {
65+
// Diagnostics for this case are emitted by the `MemberMacro` conformance.
3666
return []
3767
}
3868

stdlib/public/core/DebuggerSupport.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import SwiftShims
6464
/// and other arbitrary computation are not supported. Of note, conditional
6565
/// logic and computed properties are not supported.
6666
/// * Overloaded string interpolation cannot be used.
67+
@attached(member)
6768
@attached(memberAttribute)
6869
public macro DebugDescription() =
6970
#externalMacro(module: "SwiftMacros", type: "DebugDescriptionMacro")
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -verify -plugin-path %swift-plugin-dir
5+
6+
// expected-error @+1 {{cannot be attached to a generic definition}}
7+
@DebugDescription
8+
struct MyGeneric<T> {
9+
var debugDescription: String {
10+
"zero zero zero"
11+
}
12+
}

0 commit comments

Comments
 (0)