Skip to content

Commit 412915e

Browse files
committed
[AST] TypeWrappers: A request to synthesize _storage variable for an initializer
User-defined initializer would populate `_storage` incrementally so it could be passed to `<TypeWrapper>.init(memberwise:)` call to initialize the type wrapper.
1 parent c5268e2 commit 412915e

File tree

6 files changed

+81
-10
lines changed

6 files changed

+81
-10
lines changed

include/swift/AST/Decl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7649,6 +7649,12 @@ class ConstructorDecl : public AbstractFunctionDecl {
76497649
/// \endcode
76507650
bool isObjCZeroParameterWithLongSelector() const;
76517651

7652+
/// If this is a user-defined constructor that belongs to
7653+
/// a type wrapped type return a local `_storage` variable
7654+
/// injected by the compiler for aid with type wrapper
7655+
/// initialization.
7656+
VarDecl *getLocalTypeWrapperStorageVar() const;
7657+
76527658
static bool classof(const Decl *D) {
76537659
return D->getKind() == DeclKind::Constructor;
76547660
}

include/swift/AST/KnownIdentifiers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ IDENTIFIER_WITH_NAME(TypeWrapperStorage, "$Storage")
314314
IDENTIFIER_WITH_NAME(TypeWrapperProperty, "$_storage")
315315
IDENTIFIER(storageKeyPath)
316316
IDENTIFIER(memberwise)
317+
IDENTIFIER_WITH_NAME(localStorageVar, "_storage")
317318

318319
// The singleton instance of TupleTypeDecl in the Builtin module
319320
IDENTIFIER(TheTupleType)

include/swift/AST/TypeCheckRequests.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3705,6 +3705,21 @@ class SynthesizeTypeWrapperInitializerBody
37053705
bool isCached() const { return true; }
37063706
};
37073707

3708+
class SynthesizeLocalVariableForTypeWrapperStorage
3709+
: public SimpleRequest<SynthesizeLocalVariableForTypeWrapperStorage,
3710+
VarDecl *(ConstructorDecl *), RequestFlags::Cached> {
3711+
public:
3712+
using SimpleRequest::SimpleRequest;
3713+
3714+
private:
3715+
friend SimpleRequest;
3716+
3717+
VarDecl *evaluate(Evaluator &evaluator, ConstructorDecl *) const;
3718+
3719+
public:
3720+
bool isCached() const { return true; }
3721+
};
3722+
37083723
void simple_display(llvm::raw_ostream &out, ASTNode node);
37093724
void simple_display(llvm::raw_ostream &out, Type value);
37103725
void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR);

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,3 +434,6 @@ SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrapperInitializer,
434434
SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrapperInitializerBody,
435435
BraceStmt *(ConstructorDecl *),
436436
Cached, NoLocationInfo)
437+
SWIFT_REQUEST(TypeChecker, SynthesizeLocalVariableForTypeWrapperStorage,
438+
VarDecl *(ConstructorDecl *),
439+
Cached, NoLocationInfo)

lib/AST/Decl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8789,6 +8789,13 @@ bool ConstructorDecl::isObjCZeroParameterWithLongSelector() const {
87898789
return params->get(0)->getInterfaceType()->isVoid();
87908790
}
87918791

8792+
VarDecl *ConstructorDecl::getLocalTypeWrapperStorageVar() const {
8793+
auto &ctx = getASTContext();
8794+
auto *mutableSelf = const_cast<ConstructorDecl *>(this);
8795+
return evaluateOrDefault(
8796+
ctx.evaluator, SynthesizeLocalVariableForTypeWrapperStorage{mutableSelf},
8797+
nullptr);
8798+
}
87928799

87938800
DestructorDecl::DestructorDecl(SourceLoc DestructorLoc, DeclContext *Parent)
87948801
: AbstractFunctionDecl(DeclKind::Destructor, Parent,

lib/Sema/TypeCheckTypeWrapper.cpp

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,37 @@
2525

2626
using namespace swift;
2727

28-
/// Create a property declaration and inject it into the given type.
29-
static VarDecl *injectProperty(NominalTypeDecl *parent, Identifier name,
30-
Type type, VarDecl::Introducer introducer,
31-
AccessLevel accessLevel,
32-
Expr *initializer = nullptr) {
33-
auto &ctx = parent->getASTContext();
28+
static PatternBindingDecl *injectVariable(DeclContext *DC, Identifier name,
29+
Type type,
30+
VarDecl::Introducer introducer,
31+
Expr *initializer = nullptr) {
32+
auto &ctx = DC->getASTContext();
3433

3534
auto *var = new (ctx) VarDecl(/*isStatic=*/false, introducer,
36-
/*nameLoc=*/SourceLoc(), name, parent);
35+
/*nameLoc=*/SourceLoc(), name, DC);
3736

3837
var->setImplicit();
3938
var->setSynthesized();
40-
var->setAccess(accessLevel);
4139
var->setInterfaceType(type);
4240

4341
Pattern *pattern = NamedPattern::createImplicit(ctx, var);
4442
pattern->setType(type);
4543

4644
pattern = TypedPattern::createImplicit(ctx, pattern, type);
4745

48-
auto *PBD = PatternBindingDecl::createImplicit(ctx, StaticSpellingKind::None,
49-
pattern, initializer, parent);
46+
return PatternBindingDecl::createImplicit(ctx, StaticSpellingKind::None,
47+
pattern, initializer, DC);
48+
}
49+
50+
/// Create a property declaration and inject it into the given type.
51+
static VarDecl *injectProperty(NominalTypeDecl *parent, Identifier name,
52+
Type type, VarDecl::Introducer introducer,
53+
AccessLevel accessLevel,
54+
Expr *initializer = nullptr) {
55+
auto *PBD = injectVariable(parent, name, type, introducer, initializer);
56+
auto *var = PBD->getSingleVar();
57+
58+
var->setAccess(accessLevel);
5059

5160
parent->addMember(PBD);
5261
parent->addMember(var);
@@ -472,3 +481,33 @@ SynthesizeTypeWrapperInitializerBody::evaluate(Evaluator &evaluator,
472481
return BraceStmt::create(ctx, /*lbloc=*/ctor->getLoc(), body,
473482
/*rbloc=*/ctor->getLoc(), /*implicit=*/true);
474483
}
484+
485+
VarDecl *SynthesizeLocalVariableForTypeWrapperStorage::evaluate(
486+
Evaluator &evaluator, ConstructorDecl *ctor) const {
487+
auto &ctx = ctor->getASTContext();
488+
489+
if (ctor->isImplicit() || !ctor->isDesignatedInit())
490+
return nullptr;
491+
492+
auto *DC = ctor->getDeclContext()->getSelfNominalTypeDecl();
493+
if (!(DC && DC->hasTypeWrapper()))
494+
return nullptr;
495+
496+
auto *storageDecl =
497+
evaluateOrDefault(evaluator, GetTypeWrapperStorage{DC}, nullptr);
498+
assert(storageDecl);
499+
500+
SmallVector<TupleTypeElt, 4> members;
501+
for (auto *member : storageDecl->getMembers()) {
502+
if (auto *var = dyn_cast<VarDecl>(member)) {
503+
assert(var->hasStorage() &&
504+
"$Storage should have stored properties only");
505+
members.push_back({var->getValueInterfaceType(), var->getName()});
506+
}
507+
}
508+
509+
auto *PBD =
510+
injectVariable(ctor, ctx.Id_localStorageVar, TupleType::get(members, ctx),
511+
VarDecl::Introducer::Var);
512+
return PBD->getSingleVar();
513+
}

0 commit comments

Comments
 (0)