Skip to content

Commit 6536f59

Browse files
authored
Requestify memberwise and default initializer synthesis (#27884)
Requestify memberwise and default initializer synthesis
2 parents 9edf626 + ce2c2ca commit 6536f59

File tree

9 files changed

+394
-189
lines changed

9 files changed

+394
-189
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ SWIFT_TYPEID(Requirement)
2525
SWIFT_TYPEID(ResilienceExpansion)
2626
SWIFT_TYPEID(Type)
2727
SWIFT_TYPEID(TypePair)
28+
SWIFT_TYPEID_NAMED(ConstructorDecl *, ConstructorDecl)
2829
SWIFT_TYPEID_NAMED(CustomAttr *, CustomAttr)
2930
SWIFT_TYPEID_NAMED(Decl *, Decl)
3031
SWIFT_TYPEID_NAMED(EnumDecl *, EnumDecl)

include/swift/AST/ASTTypeIDs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace swift {
2323

2424
class AbstractFunctionDecl;
2525
class BraceStmt;
26+
class ConstructorDecl;
2627
class CustomAttr;
2728
class Decl;
2829
class EnumDecl;

include/swift/AST/Decl.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3464,6 +3464,21 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
34643464
});
34653465
}
34663466

3467+
/// Whether this declaration has a synthesized memberwise initializer.
3468+
bool hasMemberwiseInitializer() const;
3469+
3470+
/// Retrieves the synthesized memberwise initializer for this declaration,
3471+
/// or \c nullptr if it does not have one.
3472+
ConstructorDecl *getMemberwiseInitializer() const;
3473+
3474+
/// Whether this declaration has a synthesized zero parameter default
3475+
/// initializer.
3476+
bool hasDefaultInitializer() const;
3477+
3478+
/// Retrieves the synthesized zero parameter default initializer for this
3479+
/// declaration, or \c nullptr if it doesn't have one.
3480+
ConstructorDecl *getDefaultInitializer() const;
3481+
34673482
// Implement isa/cast/dyncast/etc.
34683483
static bool classof(const Decl *D) {
34693484
return D->getKind() >= DeclKind::First_NominalTypeDecl &&

include/swift/AST/TypeCheckRequests.h

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,6 +1508,125 @@ class LookupPrecedenceGroupRequest
15081508
bool isCached() const { return true; }
15091509
};
15101510

1511+
/// Computes whether all of the stored properties in a nominal type have initial
1512+
/// values.
1513+
class AreAllStoredPropertiesDefaultInitableRequest
1514+
: public SimpleRequest<AreAllStoredPropertiesDefaultInitableRequest,
1515+
bool(NominalTypeDecl *), CacheKind::Cached> {
1516+
public:
1517+
using SimpleRequest::SimpleRequest;
1518+
1519+
private:
1520+
friend SimpleRequest;
1521+
1522+
// Evaluation.
1523+
llvm::Expected<bool> evaluate(Evaluator &evaluator,
1524+
NominalTypeDecl *decl) const;
1525+
1526+
public:
1527+
// Caching.
1528+
bool isCached() const { return true; }
1529+
};
1530+
1531+
/// Computes whether this type has a user-defined designated initializer. This
1532+
/// does not include a synthesized designated initializer used to satisfy a
1533+
/// conformance.
1534+
class HasUserDefinedDesignatedInitRequest
1535+
: public SimpleRequest<HasUserDefinedDesignatedInitRequest,
1536+
bool(NominalTypeDecl *), CacheKind::Cached> {
1537+
public:
1538+
using SimpleRequest::SimpleRequest;
1539+
1540+
private:
1541+
friend SimpleRequest;
1542+
1543+
// Evaluation.
1544+
llvm::Expected<bool> evaluate(Evaluator &evaluator,
1545+
NominalTypeDecl *decl) const;
1546+
1547+
public:
1548+
// Caching.
1549+
bool isCached() const { return true; }
1550+
};
1551+
1552+
/// Checks whether this type has a synthesized memberwise initializer.
1553+
class HasMemberwiseInitRequest
1554+
: public SimpleRequest<HasMemberwiseInitRequest, bool(StructDecl *),
1555+
CacheKind::Cached> {
1556+
public:
1557+
using SimpleRequest::SimpleRequest;
1558+
1559+
private:
1560+
friend SimpleRequest;
1561+
1562+
// Evaluation.
1563+
llvm::Expected<bool> evaluate(Evaluator &evaluator, StructDecl *decl) const;
1564+
1565+
public:
1566+
// Caching.
1567+
bool isCached() const { return true; }
1568+
};
1569+
1570+
/// Synthesizes a memberwise initializer for a given type.
1571+
class SynthesizeMemberwiseInitRequest
1572+
: public SimpleRequest<SynthesizeMemberwiseInitRequest,
1573+
ConstructorDecl *(NominalTypeDecl *),
1574+
CacheKind::Cached> {
1575+
public:
1576+
using SimpleRequest::SimpleRequest;
1577+
1578+
private:
1579+
friend SimpleRequest;
1580+
1581+
// Evaluation.
1582+
llvm::Expected<ConstructorDecl *> evaluate(Evaluator &evaluator,
1583+
NominalTypeDecl *decl) const;
1584+
1585+
public:
1586+
// Caching.
1587+
bool isCached() const { return true; }
1588+
};
1589+
1590+
/// Checks whether this type has a synthesized zero parameter default
1591+
/// initializer.
1592+
class HasDefaultInitRequest
1593+
: public SimpleRequest<HasDefaultInitRequest, bool(NominalTypeDecl *),
1594+
CacheKind::Cached> {
1595+
public:
1596+
using SimpleRequest::SimpleRequest;
1597+
1598+
private:
1599+
friend SimpleRequest;
1600+
1601+
// Evaluation.
1602+
llvm::Expected<bool> evaluate(Evaluator &evaluator,
1603+
NominalTypeDecl *decl) const;
1604+
1605+
public:
1606+
// Caching.
1607+
bool isCached() const { return true; }
1608+
};
1609+
1610+
/// Synthesizes a default initializer for a given type.
1611+
class SynthesizeDefaultInitRequest
1612+
: public SimpleRequest<SynthesizeDefaultInitRequest,
1613+
ConstructorDecl *(NominalTypeDecl *),
1614+
CacheKind::Cached> {
1615+
public:
1616+
using SimpleRequest::SimpleRequest;
1617+
1618+
private:
1619+
friend SimpleRequest;
1620+
1621+
// Evaluation.
1622+
llvm::Expected<ConstructorDecl *> evaluate(Evaluator &evaluator,
1623+
NominalTypeDecl *decl) const;
1624+
1625+
public:
1626+
// Caching.
1627+
bool isCached() const { return true; }
1628+
};
1629+
15111630
// Allow AnyValue to compare two Type values, even though Type doesn't
15121631
// support ==.
15131632
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,15 @@ SWIFT_REQUEST(TypeChecker, ParamSpecifierRequest,
165165
ParamDecl::Specifier(ParamDecl *), SeparatelyCached, NoLocationInfo)
166166
SWIFT_REQUEST(TypeChecker, ResultTypeRequest,
167167
Type(ValueDecl *), SeparatelyCached, NoLocationInfo)
168+
SWIFT_REQUEST(TypeChecker, AreAllStoredPropertiesDefaultInitableRequest,
169+
bool(NominalTypeDecl *), Cached, NoLocationInfo)
170+
SWIFT_REQUEST(TypeChecker, HasUserDefinedDesignatedInitRequest,
171+
bool(NominalTypeDecl *), Cached, NoLocationInfo)
172+
SWIFT_REQUEST(TypeChecker, HasMemberwiseInitRequest,
173+
bool(StructDecl *), Cached, NoLocationInfo)
174+
SWIFT_REQUEST(TypeChecker, SynthesizeMemberwiseInitRequest,
175+
ConstructorDecl *(NominalTypeDecl *), Cached, NoLocationInfo)
176+
SWIFT_REQUEST(TypeChecker, HasDefaultInitRequest,
177+
bool(NominalTypeDecl *), Cached, NoLocationInfo)
178+
SWIFT_REQUEST(TypeChecker, SynthesizeDefaultInitRequest,
179+
ConstructorDecl *(NominalTypeDecl *), Cached, NoLocationInfo)

lib/AST/Decl.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3834,6 +3834,49 @@ StructDecl::StructDecl(SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc,
38343834
Bits.StructDecl.HasUnreferenceableStorage = false;
38353835
}
38363836

3837+
bool NominalTypeDecl::hasMemberwiseInitializer() const {
3838+
// Currently only structs can have memberwise initializers.
3839+
auto *sd = dyn_cast<StructDecl>(this);
3840+
if (!sd)
3841+
return false;
3842+
3843+
auto &ctx = getASTContext();
3844+
auto *mutableThis = const_cast<StructDecl *>(sd);
3845+
return evaluateOrDefault(ctx.evaluator, HasMemberwiseInitRequest{mutableThis},
3846+
false);
3847+
}
3848+
3849+
ConstructorDecl *NominalTypeDecl::getMemberwiseInitializer() const {
3850+
if (!hasMemberwiseInitializer())
3851+
return nullptr;
3852+
3853+
auto &ctx = getASTContext();
3854+
auto *mutableThis = const_cast<NominalTypeDecl *>(this);
3855+
return evaluateOrDefault(
3856+
ctx.evaluator, SynthesizeMemberwiseInitRequest{mutableThis}, nullptr);
3857+
}
3858+
3859+
bool NominalTypeDecl::hasDefaultInitializer() const {
3860+
// Currently only structs and classes can have default initializers.
3861+
if (!isa<StructDecl>(this) && !isa<ClassDecl>(this))
3862+
return false;
3863+
3864+
auto &ctx = getASTContext();
3865+
auto *mutableThis = const_cast<NominalTypeDecl *>(this);
3866+
return evaluateOrDefault(ctx.evaluator, HasDefaultInitRequest{mutableThis},
3867+
false);
3868+
}
3869+
3870+
ConstructorDecl *NominalTypeDecl::getDefaultInitializer() const {
3871+
if (!hasDefaultInitializer())
3872+
return nullptr;
3873+
3874+
auto &ctx = getASTContext();
3875+
auto *mutableThis = const_cast<NominalTypeDecl *>(this);
3876+
return evaluateOrDefault(ctx.evaluator,
3877+
SynthesizeDefaultInitRequest{mutableThis}, nullptr);
3878+
}
3879+
38373880
ClassDecl::ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc,
38383881
MutableArrayRef<TypeLoc> Inherited,
38393882
GenericParamList *GenericParams, DeclContext *Parent)

lib/ClangImporter/ImportDecl.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2726,7 +2726,6 @@ namespace {
27262726
auto Loc = Impl.importSourceLoc(decl->getLocation());
27272727
auto structDecl = Impl.createDeclWithClangNode<StructDecl>(decl,
27282728
AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
2729-
structDecl->setAddedImplicitInitializers();
27302729

27312730
auto options = getDefaultMakeStructRawValuedOptions();
27322731
options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;
@@ -2775,7 +2774,6 @@ namespace {
27752774
C.getProtocol(KnownProtocolKind::ErrorCodeProtocol))) {
27762775
// Create the wrapper struct.
27772776
errorWrapper = new (C) StructDecl(loc, name, loc, None, nullptr, dc);
2778-
errorWrapper->setAddedImplicitInitializers();
27792777
errorWrapper->setAccess(AccessLevel::Public);
27802778
errorWrapper->getAttrs().add(
27812779
new (Impl.SwiftContext) FrozenAttr(/*IsImplicit*/true));
@@ -3203,7 +3201,6 @@ namespace {
32033201
name,
32043202
Impl.importSourceLoc(decl->getLocation()),
32053203
None, nullptr, dc);
3206-
result->setAddedImplicitInitializers();
32073204
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
32083205

32093206
// FIXME: Figure out what to do with superclasses in C++. One possible
@@ -5484,7 +5481,6 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
54845481

54855482
auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
54865483
decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
5487-
structDecl->setAddedImplicitInitializers();
54885484

54895485
// Import the type of the underlying storage
54905486
auto storedUnderlyingType = Impl.importTypeIgnoreIUO(
@@ -5760,7 +5756,6 @@ SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
57605756
// Create a struct with the underlying type as a field.
57615757
auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
57625758
decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
5763-
structDecl->setAddedImplicitInitializers();
57645759

57655760
makeStructRawValued(Impl, structDecl, underlyingType,
57665761
{KnownProtocolKind::OptionSet});

0 commit comments

Comments
 (0)