Skip to content

Commit aff9751

Browse files
committed
Walk auxiliary declarations when gathering stored properties
Make sure we walk auxiliary declarations when gathering stored properties. This ensures that we will get any stored properties introduced by peer macros. Fixes rdar://108534298.
1 parent 593c236 commit aff9751

File tree

3 files changed

+77
-12
lines changed

3 files changed

+77
-12
lines changed

lib/Sema/TypeCheckStorage.cpp

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -169,14 +169,23 @@ static void computeLoweredStoredProperties(NominalTypeDecl *decl,
169169
static void enumerateStoredPropertiesAndMissing(
170170
NominalTypeDecl *decl,
171171
IterableDeclContext *implDecl,
172-
llvm::function_ref<void(VarDecl *)> addStoredProperty,
172+
llvm::function_ref<void(VarDecl *)> _addStoredProperty,
173173
llvm::function_ref<void(MissingMemberDecl *)> addMissing) {
174+
// Add a variable as a stored properties.
175+
llvm::SmallSet<VarDecl *, 8> knownStoredProperties;
176+
auto addStoredProperty = [&](VarDecl *var) {
177+
if (!var->isStatic() && var->hasStorage()) {
178+
if (knownStoredProperties.insert(var).second)
179+
_addStoredProperty(var);
180+
}
181+
};
182+
174183
// If we have a distributed actor, find the id and actorSystem
175184
// properties. We always want them first, and in a specific
176185
// order.
177-
VarDecl *distributedActorId = nullptr;
178-
VarDecl *distributedActorSystem = nullptr;
179186
if (decl->isDistributedActor()) {
187+
VarDecl *distributedActorId = nullptr;
188+
VarDecl *distributedActorSystem = nullptr;
180189
ASTContext &ctx = decl->getASTContext();
181190
for (auto *member : implDecl->getMembers()) {
182191
if (auto *var = dyn_cast<VarDecl>(member)) {
@@ -201,17 +210,14 @@ static void enumerateStoredPropertiesAndMissing(
201210

202211
for (auto *member : implDecl->getMembers()) {
203212
if (auto *var = dyn_cast<VarDecl>(member)) {
204-
if (!var->isStatic() && var->hasStorage()) {
205-
// Skip any properties that we already emitted explicitly
206-
if (var == distributedActorId)
207-
continue;
208-
if (var == distributedActorSystem)
209-
continue;
210-
211-
addStoredProperty(var);
212-
}
213+
addStoredProperty(var);
213214
}
214215

216+
member->visitAuxiliaryDecls([&](Decl *auxDecl) {
217+
if (auto auxVar = dyn_cast<VarDecl>(auxDecl))
218+
addStoredProperty(auxVar);
219+
});
220+
215221
if (auto missing = dyn_cast<MissingMemberDecl>(member))
216222
if (missing->getNumberOfFieldOffsetVectorEntries() > 0)
217223
addMissing(missing);

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,29 @@ extension PropertyWrapperMacro: AccessorMacro, Macro {
406406
}
407407
}
408408

409+
extension PropertyWrapperMacro: PeerMacro {
410+
public static func expansion(
411+
of node: AttributeSyntax,
412+
providingPeersOf declaration: some DeclSyntaxProtocol,
413+
in context: some MacroExpansionContext
414+
) throws -> [DeclSyntax] {
415+
guard let varDecl = declaration.as(VariableDeclSyntax.self),
416+
let binding = varDecl.bindings.first,
417+
let identifier = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier,
418+
binding.accessor == nil,
419+
let type = binding.typeAnnotation?.type
420+
else {
421+
return []
422+
}
423+
424+
return [
425+
"""
426+
var _\(raw: identifier.trimmedDescription): MyWrapperThingy<\(type)>
427+
"""
428+
]
429+
}
430+
}
431+
409432
public struct WrapAllProperties: MemberAttributeMacro {
410433
public static func expansion(
411434
of node: AttributeSyntax,

test/Macros/macro_expand_peers.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ struct Main {
128128
}
129129
print(result2)
130130
// CHECK-EXEC: hahaha global
131+
132+
// CHECK-EXEC: MyWrapperThingy<Swift.Int>(storage: 5)
133+
print(S3(x: 5))
131134
}
132135
}
133136

@@ -156,3 +159,36 @@ struct S2 {
156159
}
157160
#endif
158161
}
162+
163+
// Stored properties generated by a peer macro
164+
@attached(accessor)
165+
@attached(peer, names: prefixed(_))
166+
macro myPropertyWrapper() =
167+
#externalMacro(module: "MacroDefinition", type: "PropertyWrapperMacro")
168+
169+
struct Date { }
170+
171+
struct MyWrapperThingy<T> {
172+
var storage: T
173+
174+
var wrappedValue: T {
175+
get {
176+
print("Getting value \(storage)")
177+
return storage
178+
}
179+
180+
set {
181+
print("Setting value \(newValue)")
182+
storage = newValue
183+
}
184+
}
185+
}
186+
187+
struct S3 {
188+
@myPropertyWrapper
189+
var x: Int = 0
190+
191+
init(x: Int) {
192+
self._x = MyWrapperThingy(storage: x)
193+
}
194+
}

0 commit comments

Comments
 (0)