Skip to content

Commit c0169c1

Browse files
authored
Merge pull request #16053 from slavapestov/sema-implicit-member-cleanup
More cleanups for Codable and CaseIterable
2 parents 2690560 + 1a42566 commit c0169c1

File tree

2 files changed

+18
-73
lines changed

2 files changed

+18
-73
lines changed

lib/Sema/DerivedConformanceCodable.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,7 @@ static FuncDecl *deriveEncodable_encode(TypeChecker &tc, Decl *parentDecl,
757757
// conformance from a parent class.
758758
auto *classDecl = dyn_cast<ClassDecl>(target);
759759
if (classDecl && superclassIsEncodable(classDecl)) {
760-
auto *attr = new (C) SimpleDeclAttr<DAK_Override>(/*IsImplicit=*/true);
760+
auto *attr = new (C) OverrideAttr(/*IsImplicit=*/true);
761761
encodeDecl->getAttrs().add(attr);
762762
}
763763

@@ -1090,7 +1090,7 @@ static ValueDecl *deriveDecodable_init(TypeChecker &tc, Decl *parentDecl,
10901090

10911091
// This constructor should be marked as `required` for non-final classes.
10921092
if (isa<ClassDecl>(target) && !target->getAttrs().hasAttribute<FinalAttr>()) {
1093-
auto *reqAttr = new (C) SimpleDeclAttr<DAK_Required>(/*IsImplicit=*/true);
1093+
auto *reqAttr = new (C) RequiredAttr(/*IsImplicit=*/true);
10941094
initDecl->getAttrs().add(reqAttr);
10951095
}
10961096

lib/Sema/TypeCheckDecl.cpp

Lines changed: 16 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -8748,37 +8748,8 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
87488748
bool FoundMemberwiseInitializedProperty = false;
87498749
bool SuppressDefaultInitializer = false;
87508750
bool SuppressMemberwiseInitializer = false;
8751-
bool FoundSynthesizedInit = false;
87528751
bool FoundDesignatedInit = false;
87538752

8754-
// Before we look for constructors, we need to make sure that all synthesized
8755-
// initializers are properly synthesized.
8756-
//
8757-
// NOTE: Lookups of synthesized initializers MUST come after
8758-
// decl->setAddedImplicitInitializers() in case synthesis requires
8759-
// protocol conformance checking, which might be recursive here.
8760-
// FIXME: Disable this code and prevent _any_ implicit constructors from doing
8761-
// this. Investigate why this hasn't worked otherwise.
8762-
DeclName synthesizedInitializers[1] = {
8763-
// init(from:) is synthesized by derived conformance to Decodable.
8764-
DeclName(Context, DeclBaseName::createConstructor(), Context.Id_from)
8765-
};
8766-
8767-
auto initializerIsSynthesized = [=](ConstructorDecl *initializer) {
8768-
if (!initializer->isImplicit())
8769-
return false;
8770-
8771-
for (auto &name : synthesizedInitializers)
8772-
if (initializer->getFullName() == name)
8773-
return true;
8774-
8775-
return false;
8776-
};
8777-
8778-
for (auto &name : synthesizedInitializers) {
8779-
synthesizeMemberForLookup(decl, name);
8780-
}
8781-
87828753
SmallPtrSet<CanType, 4> initializerParamTypes;
87838754
llvm::SmallPtrSet<ConstructorDecl *, 4> overriddenInits;
87848755
if (decl->hasClangNode() && isa<ClassDecl>(decl)) {
@@ -8800,13 +8771,10 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
88008771
} else {
88018772
for (auto member : decl->getMembers()) {
88028773
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
8803-
// Synthesized initializers others than the default initializer should
8804-
// not prevent default initializer synthesis.
8805-
if (initializerIsSynthesized(ctor)) {
8806-
FoundSynthesizedInit = true;
8807-
} else if (ctor->isDesignatedInit()) {
8774+
// Initializers that were synthesized to fulfill derived conformances
8775+
// should not prevent default initializer synthesis.
8776+
if (ctor->isDesignatedInit() && !ctor->isSynthesized())
88088777
FoundDesignatedInit = true;
8809-
}
88108778

88118779
if (isa<StructDecl>(decl))
88128780
continue;
@@ -8878,8 +8846,10 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
88788846
}
88798847

88808848
if (auto structDecl = dyn_cast<StructDecl>(decl)) {
8881-
if (!FoundDesignatedInit && !SuppressMemberwiseInitializer
8882-
&& !structDecl->hasUnreferenceableStorage()) {
8849+
assert(!structDecl->hasUnreferenceableStorage() &&
8850+
"User-defined structs cannot have unreferenceable storage");
8851+
8852+
if (!FoundDesignatedInit && !SuppressMemberwiseInitializer) {
88838853
// For a struct with memberwise initialized properties, we add a
88848854
// memberwise init.
88858855
if (FoundMemberwiseInitializedProperty) {
@@ -8901,12 +8871,13 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
89018871
// FIXME: Currently skipping generic classes.
89028872
auto classDecl = cast<ClassDecl>(decl);
89038873
if (classDecl->hasSuperclass()) {
8904-
bool canInheritInitializers = !FoundDesignatedInit;
8874+
bool canInheritInitializers = (!SuppressDefaultInitializer &&
8875+
!FoundDesignatedInit);
89058876

89068877
// We can't define these overrides if we have any uninitialized
89078878
// stored properties.
8908-
if (SuppressDefaultInitializer && !FoundDesignatedInit
8909-
&& !FoundSynthesizedInit && !classDecl->hasClangNode()) {
8879+
if (SuppressDefaultInitializer && !FoundDesignatedInit &&
8880+
!classDecl->hasClangNode()) {
89108881
return;
89118882
}
89128883

@@ -9019,14 +8990,9 @@ void TypeChecker::synthesizeMemberForLookup(NominalTypeDecl *target,
90198990
auto baseName = member.getBaseName();
90208991

90218992
// Checks whether the target conforms to the given protocol. If the
9022-
// conformance is incomplete, check the conformance to force synthesis, if
9023-
// possible.
9024-
//
9025-
// Swallows diagnostics if conformance checking is already in progress (so we
9026-
// don't display diagnostics twice).
8993+
// conformance is incomplete, force the conformance.
90278994
//
9028-
// Returns whether the target conforms to the protocol and the conformance is
9029-
// complete.
8995+
// Returns whether the target conforms to the protocol.
90308996
auto evaluateTargetConformanceTo = [&](ProtocolDecl *protocol) {
90318997
auto targetType = target->getDeclaredInterfaceType();
90328998
if (auto ref = conformsToProtocol(
@@ -9035,26 +9001,12 @@ void TypeChecker::synthesizeMemberForLookup(NominalTypeDecl *target,
90359001
ConformanceCheckFlags::SkipConditionalRequirements),
90369002
SourceLoc())) {
90379003
if (auto *conformance = ref->getConcrete()->getRootNormalConformance()) {
9038-
if (conformance->isIncomplete()) {
9039-
// Check conformance, forcing synthesis.
9040-
//
9041-
// If synthesizing conformance fails, this will produce diagnostics.
9042-
// If conformance checking was already in progress elsewhere, though,
9043-
// this could produce diagnostics twice.
9044-
//
9045-
// To prevent this duplication, we swallow the diagnostics if the
9046-
// state of the conformance is not Incomplete.
9047-
DiagnosticTransaction transaction(Context.Diags);
9048-
auto shouldSwallowDiagnostics =
9049-
conformance->getState() != ProtocolConformanceState::Incomplete;
9050-
9004+
if (conformance->getState() == ProtocolConformanceState::Incomplete) {
90519005
checkConformance(conformance);
9052-
if (shouldSwallowDiagnostics)
9053-
transaction.abort();
9054-
9055-
return conformance->isComplete();
90569006
}
90579007
}
9008+
9009+
return true;
90589010
}
90599011

90609012
return false;
@@ -9076,13 +9028,6 @@ void TypeChecker::synthesizeMemberForLookup(NominalTypeDecl *target,
90769028
auto *encodableProto = Context.getProtocol(KnownProtocolKind::Encodable);
90779029
if (!evaluateTargetConformanceTo(decodableProto))
90789030
(void)evaluateTargetConformanceTo(encodableProto);
9079-
} else if (baseName.getIdentifier() == Context.Id_allCases ||
9080-
baseName.getIdentifier() == Context.Id_AllCases) {
9081-
// If the target should conform to the CaseIterable protocol, check the
9082-
// conformance here to attempt synthesis.
9083-
auto *caseIterableProto
9084-
= Context.getProtocol(KnownProtocolKind::CaseIterable);
9085-
(void)evaluateTargetConformanceTo(caseIterableProto);
90869031
}
90879032
} else {
90889033
auto argumentNames = member.getArgumentNames();

0 commit comments

Comments
 (0)