Skip to content

Commit 3bd25a2

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 19ef366 commit 3bd25a2

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
@@ -408,6 +408,29 @@ extension PropertyWrapperMacro: AccessorMacro, Macro {
408408
}
409409
}
410410

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

test/Macros/macro_expand_peers.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ struct Main {
124124
}
125125
print(result2)
126126
// CHECK-EXEC: hahaha global
127+
128+
// CHECK-EXEC: MyWrapperThingy<Swift.Int>(storage: 5)
129+
print(S3(x: 5))
127130
}
128131
}
129132

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

0 commit comments

Comments
 (0)