Skip to content

Commit 1ffc6b7

Browse files
authored
Merge pull request #73878 from hborla/invalid-accessor-macro
[Macros] Don't allow macros to add accessors to `let` variables.
2 parents 02a2039 + 3c6918a commit 1ffc6b7

File tree

4 files changed

+36
-3
lines changed

4 files changed

+36
-3
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7635,6 +7635,9 @@ ERROR(external_macro_arg_not_type_name,none,
76357635
ERROR(invalid_decl_in_macro_expansion,none,
76367636
"macro expansion cannot introduce %0",
76377637
(DescriptiveDeclKind))
7638+
ERROR(let_accessor_expansion,none,
7639+
"cannot expand accessors on variable declared with 'let'",
7640+
())
76387641
ERROR(invalid_main_type_in_macro_expansion,none,
76397642
"macro expansion cannot introduce '@main' type",
76407643
())

lib/Sema/TypeCheckMacros.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -739,12 +739,12 @@ static void validateMacroExpansion(SourceFile *expansionBuffer,
739739
};
740740

741741
for (auto item : expansionBuffer->getTopLevelItems()) {
742+
auto &ctx = expansionBuffer->getASTContext();
742743
auto *decl = item.dyn_cast<Decl *>();
743744
if (!decl) {
744745
if (role != MacroRole::CodeItem &&
745746
role != MacroRole::Preamble &&
746747
role != MacroRole::Body) {
747-
auto &ctx = expansionBuffer->getASTContext();
748748
ctx.Diags.diagnose(item.getStartLoc(),
749749
diag::expected_macro_expansion_decls);
750750
}
@@ -753,8 +753,18 @@ static void validateMacroExpansion(SourceFile *expansionBuffer,
753753
}
754754

755755
// Certain macro roles can generate special declarations.
756-
if ((isa<AccessorDecl>(decl) && role == MacroRole::Accessor) ||
757-
(isa<ExtensionDecl>(decl) && role == MacroRole::Conformance)) {
756+
if (isa<AccessorDecl>(decl) && role == MacroRole::Accessor) {
757+
auto *var = dyn_cast<VarDecl>(attachedTo);
758+
if (var && var->isLet()) {
759+
ctx.Diags.diagnose(var->getLoc(),
760+
diag::let_accessor_expansion)
761+
.warnUntilSwiftVersion(6);
762+
}
763+
764+
continue;
765+
}
766+
767+
if (isa<ExtensionDecl>(decl) && role == MacroRole::Conformance) {
758768
continue;
759769
}
760770

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2482,3 +2482,12 @@ public struct AllLexicalContextsMacro: DeclarationMacro {
24822482
}
24832483
}
24842484

2485+
public struct AddGetterMacro: AccessorMacro {
2486+
public static func expansion(
2487+
of node: AttributeSyntax,
2488+
providingAccessorsOf declaration: some DeclSyntaxProtocol,
2489+
in context: some MacroExpansionContext
2490+
) throws -> [AccessorDeclSyntax] {
2491+
return ["get { 0 }"]
2492+
}
2493+
}

test/Macros/accessor_macros.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,14 @@ struct MultipleVars {
163163
// expected-error@-1 2{{accessor macro 'AddWillSet()' can only apply to a single variable}}
164164
}
165165
#endif
166+
167+
@attached(accessor)
168+
macro addGetterMacro() =
169+
#externalMacro(module: "MacroDefinition", type: "AddGetterMacro")
170+
171+
#if TEST_DIAGNOSTICS
172+
struct S {
173+
@addGetterMacro let x: Int
174+
// expected-warning@-1 {{cannot expand accessors on variable declared with 'let'; this is an error in the Swift 6 language mode}}
175+
}
176+
#endif

0 commit comments

Comments
 (0)