Skip to content

Commit dbb5a48

Browse files
authored
Merge pull request swiftlang#60941 from xedin/type-wrapper-user-defined-inits-with-inst-reuse
[Sema/SIL] Implement type wrapper support in user-defined initializers
2 parents 6c518bd + 99cfbf7 commit dbb5a48

31 files changed

+1791
-221
lines changed

include/swift/AST/Decl.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3775,10 +3775,19 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
37753775
/// applicable property access routing).
37763776
VarDecl *getTypeWrapperProperty() const;
37773777

3778-
/// Get an initializer that could be used to instantiate a
3779-
/// type wrapped type.
3778+
/// If this declaration has a type wrapper, return `$Storage`
3779+
/// declaration that contains all the stored properties managed
3780+
/// by the wrapper.
3781+
NominalTypeDecl *getTypeWrapperStorageDecl() const;
3782+
3783+
/// If this declaration is a type wrapper, retrieve
3784+
/// its required initializer - `init(storage:)`.
37803785
ConstructorDecl *getTypeWrapperInitializer() const;
37813786

3787+
/// Get a memberwise initializer that could be used to instantiate a
3788+
/// type wrapped type.
3789+
ConstructorDecl *getTypeWrappedTypeMemberwiseInitializer() const;
3790+
37823791
// Implement isa/cast/dyncast/etc.
37833792
static bool classof(const Decl *D) {
37843793
return D->getKind() >= DeclKind::First_NominalTypeDecl &&
@@ -7649,6 +7658,12 @@ class ConstructorDecl : public AbstractFunctionDecl {
76497658
/// \endcode
76507659
bool isObjCZeroParameterWithLongSelector() const;
76517660

7661+
/// If this is a user-defined constructor that belongs to
7662+
/// a type wrapped type return a local `_storage` variable
7663+
/// injected by the compiler for aid with type wrapper
7664+
/// initialization.
7665+
VarDecl *getLocalTypeWrapperStorageVar() const;
7666+
76527667
static bool classof(const Decl *D) {
76537668
return D->getKind() == DeclKind::Constructor;
76547669
}

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: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3673,8 +3673,8 @@ class IsPropertyAccessedViaTypeWrapper
36733673
bool isCached() const { return true; }
36743674
};
36753675

3676-
class SynthesizeTypeWrapperInitializer
3677-
: public SimpleRequest<SynthesizeTypeWrapperInitializer,
3676+
class SynthesizeTypeWrappedTypeMemberwiseInitializer
3677+
: public SimpleRequest<SynthesizeTypeWrappedTypeMemberwiseInitializer,
36783678
ConstructorDecl *(NominalTypeDecl *),
36793679
RequestFlags::Cached> {
36803680
public:
@@ -3689,8 +3689,8 @@ class SynthesizeTypeWrapperInitializer
36893689
bool isCached() const { return true; }
36903690
};
36913691

3692-
class SynthesizeTypeWrapperInitializerBody
3693-
: public SimpleRequest<SynthesizeTypeWrapperInitializerBody,
3692+
class SynthesizeTypeWrappedTypeMemberwiseInitializerBody
3693+
: public SimpleRequest<SynthesizeTypeWrappedTypeMemberwiseInitializerBody,
36943694
BraceStmt *(ConstructorDecl *),
36953695
RequestFlags::Cached> {
36963696
public:
@@ -3705,6 +3705,37 @@ 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+
3723+
class GetTypeWrapperInitializer
3724+
: public SimpleRequest<GetTypeWrapperInitializer,
3725+
ConstructorDecl *(NominalTypeDecl *),
3726+
RequestFlags::Cached> {
3727+
public:
3728+
using SimpleRequest::SimpleRequest;
3729+
3730+
private:
3731+
friend SimpleRequest;
3732+
3733+
ConstructorDecl *evaluate(Evaluator &evaluator, NominalTypeDecl *) const;
3734+
3735+
public:
3736+
bool isCached() const { return true; }
3737+
};
3738+
37083739
void simple_display(llvm::raw_ostream &out, ASTNode node);
37093740
void simple_display(llvm::raw_ostream &out, Type value);
37103741
void simple_display(llvm::raw_ostream &out, const TypeRepr *TyR);

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,9 +428,15 @@ SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrappedPropertySetterBody,
428428
SWIFT_REQUEST(TypeChecker, IsPropertyAccessedViaTypeWrapper,
429429
bool(VarDecl *),
430430
Cached, NoLocationInfo)
431-
SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrapperInitializer,
431+
SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrappedTypeMemberwiseInitializer,
432432
ConstructorDecl *(NominalTypeDecl *),
433433
Cached, NoLocationInfo)
434-
SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrapperInitializerBody,
434+
SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrappedTypeMemberwiseInitializerBody,
435435
BraceStmt *(ConstructorDecl *),
436436
Cached, NoLocationInfo)
437+
SWIFT_REQUEST(TypeChecker, SynthesizeLocalVariableForTypeWrapperStorage,
438+
VarDecl *(ConstructorDecl *),
439+
Cached, NoLocationInfo)
440+
SWIFT_REQUEST(TypeChecker, GetTypeWrapperInitializer,
441+
ConstructorDecl *(NominalTypeDecl *),
442+
Cached, NoLocationInfo)

include/swift/SIL/SILBuilder.h

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -883,14 +883,30 @@ class SILBuilder {
883883
Qualifier));
884884
}
885885

886-
AssignByWrapperInst *createAssignByWrapper(SILLocation Loc,
887-
SILValue Src, SILValue Dest,
888-
SILValue Initializer,
889-
SILValue Setter,
890-
AssignByWrapperInst::Mode mode) {
886+
AssignByWrapperInst *
887+
createAssignByPropertyWrapper(SILLocation Loc, SILValue Src, SILValue Dest,
888+
SILValue Initializer, SILValue Setter,
889+
AssignByWrapperInst::Mode mode) {
890+
return createAssignByWrapper(
891+
Loc, AssignByWrapperInst::Originator::PropertyWrapper, Src, Dest,
892+
Initializer, Setter, mode);
893+
}
894+
895+
AssignByWrapperInst *
896+
createAssignByTypeWrapper(SILLocation Loc, SILValue Src, SILValue Dest,
897+
SILValue Setter, AssignByWrapperInst::Mode mode) {
898+
return createAssignByWrapper(
899+
Loc, AssignByWrapperInst::Originator::TypeWrapper, Src, Dest,
900+
SILUndef::get(Dest->getType(), getModule()), Setter, mode);
901+
}
902+
903+
AssignByWrapperInst *
904+
createAssignByWrapper(SILLocation Loc, AssignByWrapperInst::Originator origin,
905+
SILValue Src, SILValue Dest, SILValue Initializer,
906+
SILValue Setter, AssignByWrapperInst::Mode mode) {
891907
return insert(new (getModule())
892-
AssignByWrapperInst(getSILDebugLocation(Loc), Src, Dest,
893-
Initializer, Setter, mode));
908+
AssignByWrapperInst(getSILDebugLocation(Loc), origin, Src,
909+
Dest, Initializer, Setter, mode));
894910
}
895911

896912
StoreBorrowInst *createStoreBorrow(SILLocation Loc, SILValue Src,

include/swift/SIL/SILCloner.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,12 +1242,11 @@ template <typename ImplClass>
12421242
void SILCloner<ImplClass>::visitAssignByWrapperInst(AssignByWrapperInst *Inst) {
12431243
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
12441244
recordClonedInstruction(
1245-
Inst, getBuilder().createAssignByWrapper(getOpLocation(Inst->getLoc()),
1246-
getOpValue(Inst->getSrc()),
1247-
getOpValue(Inst->getDest()),
1248-
getOpValue(Inst->getInitializer()),
1249-
getOpValue(Inst->getSetter()),
1250-
Inst->getMode()));
1245+
Inst, getBuilder().createAssignByWrapper(
1246+
getOpLocation(Inst->getLoc()), Inst->getOriginator(),
1247+
getOpValue(Inst->getSrc()), getOpValue(Inst->getDest()),
1248+
getOpValue(Inst->getInitializer()),
1249+
getOpValue(Inst->getSetter()), Inst->getMode()));
12511250
}
12521251

12531252
template<typename ImplClass>

include/swift/SIL/SILInstruction.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4677,6 +4677,9 @@ class AssignByWrapperInst
46774677
USE_SHARED_UINT8;
46784678

46794679
public:
4680+
/// The kind of a wrapper that is being applied.
4681+
enum class Originator : uint8_t { TypeWrapper, PropertyWrapper };
4682+
46804683
enum Mode {
46814684
/// The mode is not decided yet (by DefiniteInitialization).
46824685
Unknown,
@@ -4696,13 +4699,18 @@ class AssignByWrapperInst
46964699
};
46974700

46984701
private:
4699-
AssignByWrapperInst(SILDebugLocation DebugLoc, SILValue Src, SILValue Dest,
4700-
SILValue Initializer, SILValue Setter, Mode mode);
4702+
Originator originator;
4703+
4704+
AssignByWrapperInst(SILDebugLocation DebugLoc, Originator origin,
4705+
SILValue Src, SILValue Dest, SILValue Initializer,
4706+
SILValue Setter, Mode mode);
47014707

47024708
public:
47034709
SILValue getInitializer() { return Operands[2].get(); }
47044710
SILValue getSetter() { return Operands[3].get(); }
47054711

4712+
Originator getOriginator() const { return originator; }
4713+
47064714
Mode getMode() const {
47074715
return Mode(sharedUInt8().AssignByWrapperInst.mode);
47084716
}

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/SIL/IR/SILInstructions.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,12 +1164,13 @@ AssignInst::AssignInst(SILDebugLocation Loc, SILValue Src, SILValue Dest,
11641164
}
11651165

11661166
AssignByWrapperInst::AssignByWrapperInst(SILDebugLocation Loc,
1167-
SILValue Src, SILValue Dest,
1168-
SILValue Initializer,
1169-
SILValue Setter,
1170-
AssignByWrapperInst::Mode mode) :
1171-
AssignInstBase(Loc, Src, Dest, Initializer, Setter) {
1172-
assert(Initializer->getType().is<SILFunctionType>());
1167+
AssignByWrapperInst::Originator origin,
1168+
SILValue Src, SILValue Dest,
1169+
SILValue Initializer, SILValue Setter,
1170+
AssignByWrapperInst::Mode mode)
1171+
: AssignInstBase(Loc, Src, Dest, Initializer, Setter), originator(origin) {
1172+
assert(Initializer->getType().is<SILFunctionType>() ||
1173+
(isa<SILUndef>(Initializer) && originator == Originator::TypeWrapper));
11731174
sharedUInt8().AssignByWrapperInst.mode = uint8_t(mode);
11741175
}
11751176

lib/SIL/IR/SILPrinter.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1687,6 +1687,20 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
16871687
}
16881688

16891689
void visitAssignByWrapperInst(AssignByWrapperInst *AI) {
1690+
{
1691+
*this << "origin ";
1692+
1693+
switch (AI->getOriginator()) {
1694+
case AssignByWrapperInst::Originator::TypeWrapper:
1695+
*this << "type_wrapper";
1696+
break;
1697+
case AssignByWrapperInst::Originator::PropertyWrapper:
1698+
*this << "property_wrapper";
1699+
}
1700+
1701+
*this << ", ";
1702+
}
1703+
16901704
*this << getIDAndType(AI->getSrc()) << " to ";
16911705
switch (AI->getMode()) {
16921706
case AssignByWrapperInst::Unknown:
@@ -1701,9 +1715,13 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
17011715
*this << "[assign_wrapped_value] ";
17021716
break;
17031717
}
1704-
*this << getIDAndType(AI->getDest())
1705-
<< ", init " << getIDAndType(AI->getInitializer())
1706-
<< ", set " << getIDAndType(AI->getSetter());
1718+
1719+
*this << getIDAndType(AI->getDest());
1720+
1721+
if (AI->getOriginator() == AssignByWrapperInst::Originator::PropertyWrapper)
1722+
*this << ", init " << getIDAndType(AI->getInitializer());
1723+
1724+
*this << ", set " << getIDAndType(AI->getSetter());
17071725
}
17081726

17091727
void visitMarkUninitializedInst(MarkUninitializedInst *MU) {

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,6 +2200,35 @@ bool SILParser::parseSILDebugLocation(SILLocation &L, SILBuilder &B) {
22002200
return false;
22012201
}
22022202

2203+
static bool
2204+
parseAssignByWrapperOriginator(AssignByWrapperInst::Originator &Result,
2205+
SILParser &P) {
2206+
if (P.parseVerbatim("origin"))
2207+
return true;
2208+
2209+
SourceLoc loc;
2210+
Identifier origin;
2211+
2212+
if (P.parseSILIdentifier(origin, loc, diag::expected_in_attribute_list))
2213+
return true;
2214+
2215+
// Then try to parse one of our other initialization kinds. We do not support
2216+
// parsing unknown here so we use that as our fail value.
2217+
auto Tmp =
2218+
llvm::StringSwitch<Optional<AssignByWrapperInst::Originator>>(
2219+
origin.str())
2220+
.Case("type_wrapper", AssignByWrapperInst::Originator::TypeWrapper)
2221+
.Case("property_wrapper",
2222+
AssignByWrapperInst::Originator::PropertyWrapper)
2223+
.Default(None);
2224+
2225+
if (!Tmp)
2226+
return true;
2227+
2228+
Result = *Tmp;
2229+
return false;
2230+
}
2231+
22032232
static bool parseAssignByWrapperMode(AssignByWrapperInst::Mode &Result,
22042233
SILParser &P) {
22052234
StringRef Str;
@@ -4174,13 +4203,30 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
41744203
case SILInstructionKind::AssignByWrapperInst: {
41754204
SILValue Src, DestAddr, InitFn, SetFn;
41764205
SourceLoc DestLoc;
4206+
AssignByWrapperInst::Originator originator;
41774207
AssignByWrapperInst::Mode mode;
4208+
4209+
if (parseAssignByWrapperOriginator(originator, *this))
4210+
return true;
4211+
4212+
if (P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
4213+
return true;
4214+
41784215
if (parseTypedValueRef(Src, B) || parseVerbatim("to") ||
41794216
parseAssignByWrapperMode(mode, *this) ||
4180-
parseTypedValueRef(DestAddr, DestLoc, B) ||
4181-
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
4182-
parseVerbatim("init") || parseTypedValueRef(InitFn, B) ||
4183-
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
4217+
parseTypedValueRef(DestAddr, DestLoc, B))
4218+
return true;
4219+
4220+
if (originator == AssignByWrapperInst::Originator::PropertyWrapper) {
4221+
if (P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
4222+
parseVerbatim("init") || parseTypedValueRef(InitFn, B))
4223+
return true;
4224+
} else {
4225+
assert(originator == AssignByWrapperInst::Originator::TypeWrapper);
4226+
InitFn = SILUndef::get(DestAddr->getType(), B.getModule());
4227+
}
4228+
4229+
if (P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
41844230
parseVerbatim("set") || parseTypedValueRef(SetFn, B) ||
41854231
parseSILDebugLocation(InstLoc, B))
41864232
return true;
@@ -4191,8 +4237,8 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
41914237
return true;
41924238
}
41934239

4194-
ResultVal = B.createAssignByWrapper(InstLoc, Src, DestAddr, InitFn, SetFn,
4195-
mode);
4240+
ResultVal = B.createAssignByWrapper(InstLoc, originator, Src, DestAddr,
4241+
InitFn, SetFn, mode);
41964242
break;
41974243
}
41984244

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2510,11 +2510,13 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
25102510
"assign instruction can only exist in raw SIL");
25112511
require(Dest->getType().isAddress(), "Must store to an address dest");
25122512

2513-
SILValue initFn = AI->getInitializer();
2514-
CanSILFunctionType initTy = initFn->getType().castTo<SILFunctionType>();
2515-
SILFunctionConventions initConv(initTy, AI->getModule());
2516-
checkAssignByWrapperArgs(Src->getType(), initConv);
2517-
switch (initConv.getNumIndirectSILResults()) {
2513+
if (AI->getOriginator() ==
2514+
AssignByWrapperInst::Originator::PropertyWrapper) {
2515+
SILValue initFn = AI->getInitializer();
2516+
CanSILFunctionType initTy = initFn->getType().castTo<SILFunctionType>();
2517+
SILFunctionConventions initConv(initTy, AI->getModule());
2518+
checkAssignByWrapperArgs(Src->getType(), initConv);
2519+
switch (initConv.getNumIndirectSILResults()) {
25182520
case 0:
25192521
require(initConv.getNumDirectSILResults() == 1,
25202522
"wrong number of init function results");
@@ -2535,6 +2537,13 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
25352537
break;
25362538
default:
25372539
require(false, "wrong number of indirect init function results");
2540+
}
2541+
} else {
2542+
require(AI->getOriginator() ==
2543+
AssignByWrapperInst::Originator::TypeWrapper,
2544+
"wrong originator");
2545+
require(isa<SILUndef>(AI->getInitializer()),
2546+
"assignment via type wrapper does not have initializer");
25382547
}
25392548

25402549
SILValue setterFn = AI->getSetter();

0 commit comments

Comments
 (0)