[Sema] Requestify areAllStoredPropertiesDefaultInitializable

This commit is contained in:
Hamish Knight
2019-10-22 15:26:39 -07:00
parent 0c7f1c6040
commit 704766cee3
3 changed files with 41 additions and 13 deletions

View File

@@ -1508,6 +1508,26 @@ public:
bool isCached() const { return true; } bool isCached() const { return true; }
}; };
/// Computes whether all of the stored properties in a nominal type have initial
/// values.
class AreAllStoredPropertiesDefaultInitableRequest
: public SimpleRequest<AreAllStoredPropertiesDefaultInitableRequest,
bool(NominalTypeDecl *), CacheKind::Cached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
llvm::Expected<bool> evaluate(Evaluator &evaluator,
NominalTypeDecl *decl) const;
public:
// Caching.
bool isCached() const { return true; }
};
// Allow AnyValue to compare two Type values, even though Type doesn't // Allow AnyValue to compare two Type values, even though Type doesn't
// support ==. // support ==.
template<> template<>

View File

@@ -165,3 +165,5 @@ SWIFT_REQUEST(TypeChecker, ParamSpecifierRequest,
ParamDecl::Specifier(ParamDecl *), SeparatelyCached, NoLocationInfo) ParamDecl::Specifier(ParamDecl *), SeparatelyCached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ResultTypeRequest, SWIFT_REQUEST(TypeChecker, ResultTypeRequest,
Type(ValueDecl *), SeparatelyCached, NoLocationInfo) Type(ValueDecl *), SeparatelyCached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, AreAllStoredPropertiesDefaultInitableRequest,
bool(NominalTypeDecl *), Cached, NoLocationInfo)

View File

@@ -800,9 +800,9 @@ static void diagnoseMissingRequiredInitializer(
diag::required_initializer_here); diag::required_initializer_here);
} }
static bool areAllStoredPropertiesDefaultInitializable(NominalTypeDecl *decl) { llvm::Expected<bool> AreAllStoredPropertiesDefaultInitableRequest::evaluate(
if (decl->hasClangNode()) Evaluator &evaluator, NominalTypeDecl *decl) const {
return true; assert(!decl->hasClangNode());
for (auto member : decl->getMembers()) { for (auto member : decl->getMembers()) {
// If a stored property lacks an initial value and if there is no way to // If a stored property lacks an initial value and if there is no way to
@@ -833,6 +833,15 @@ static bool areAllStoredPropertiesDefaultInitializable(NominalTypeDecl *decl) {
return true; return true;
} }
static bool areAllStoredPropertiesDefaultInitializable(Evaluator &eval,
NominalTypeDecl *decl) {
if (decl->hasClangNode())
return true;
return evaluateOrDefault(
eval, AreAllStoredPropertiesDefaultInitableRequest{decl}, false);
}
static void addImplicitConstructorsToStruct(StructDecl *decl) { static void addImplicitConstructorsToStruct(StructDecl *decl) {
assert(!decl->hasClangNode() && assert(!decl->hasClangNode() &&
"ClangImporter is responsible for adding implicit constructors"); "ClangImporter is responsible for adding implicit constructors");
@@ -864,15 +873,15 @@ static void addImplicitConstructorsToStruct(StructDecl *decl) {
} }
} }
auto &ctx = decl->getASTContext();
if (FoundMemberwiseInitializedProperty) { if (FoundMemberwiseInitializedProperty) {
// Create the implicit memberwise constructor. // Create the implicit memberwise constructor.
auto &ctx = decl->getASTContext();
auto ctor = createImplicitConstructor( auto ctor = createImplicitConstructor(
decl, ImplicitConstructorKind::Memberwise, ctx); decl, ImplicitConstructorKind::Memberwise, ctx);
decl->addMember(ctor); decl->addMember(ctor);
} }
if (areAllStoredPropertiesDefaultInitializable(decl)) if (areAllStoredPropertiesDefaultInitializable(ctx.evaluator, decl))
TypeChecker::defineDefaultConstructor(decl); TypeChecker::defineDefaultConstructor(decl);
} }
@@ -932,21 +941,18 @@ static void addImplicitConstructorsToClass(ClassDecl *decl) {
} }
} }
bool SuppressDefaultInitializer = bool defaultInitable =
!areAllStoredPropertiesDefaultInitializable(decl); areAllStoredPropertiesDefaultInitializable(ctx.evaluator, decl);
// For a class with a superclass, automatically define overrides // For a class with a superclass, automatically define overrides
// for all of the superclass's designated initializers. // for all of the superclass's designated initializers.
if (Type superclassTy = decl->getSuperclass()) { if (Type superclassTy = decl->getSuperclass()) {
bool canInheritInitializers = (!SuppressDefaultInitializer && bool canInheritInitializers = defaultInitable && !FoundDesignatedInit;
!FoundDesignatedInit);
// We can't define these overrides if we have any uninitialized // We can't define these overrides if we have any uninitialized
// stored properties. // stored properties.
if (SuppressDefaultInitializer && !FoundDesignatedInit && if (!defaultInitable && !FoundDesignatedInit && !decl->hasClangNode())
!decl->hasClangNode()) {
return; return;
}
auto *superclassDecl = superclassTy->getClassOrBoundGenericClass(); auto *superclassDecl = superclassTy->getClassOrBoundGenericClass();
assert(superclassDecl && "Superclass of class is not a class?"); assert(superclassDecl && "Superclass of class is not a class?");
@@ -1056,7 +1062,7 @@ static void addImplicitConstructorsToClass(ClassDecl *decl) {
// constructor. // constructor.
// ... unless there are uninitialized stored properties. // ... unless there are uninitialized stored properties.
if (SuppressDefaultInitializer) if (!defaultInitable)
return; return;
// Clang-imported types should never get a default constructor, just a // Clang-imported types should never get a default constructor, just a