Skip to content

Commit 0af3434

Browse files
committed
Pre-Request Cleanup For Implicit Constructors
Push through an easy refactoring to the way we validate and install implicit constructors. This patch would be NFC but for a regression test that now must diagnose. swiftlang#26159 changed validation order in such a way that the code in validation-test-macosx-x86_64/compiler_crashers_2_fixed/0124-sr5825.swift used to be accepted. This patch once again changes validation order, so we now reject this code, restoring the behavior seen on all prior versions of Swift. On its face, this test should work. In order for it to do so, witness matching has to be smarter about the declarations it asks for their interface type, or it will risk these circular constructions accidentally being accepted or rejected on a whim.
1 parent 64401ac commit 0af3434

File tree

4 files changed

+33
-38
lines changed

4 files changed

+33
-38
lines changed

lib/Sema/CodeSynthesis.cpp

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -920,17 +920,6 @@ static void addImplicitInheritedConstructorsToClass(ClassDecl *decl) {
920920

921921
decl->setAddedImplicitInitializers();
922922

923-
auto &ctx = decl->getASTContext();
924-
SmallVector<std::pair<ValueDecl *, Type>, 4> declaredInitializers;
925-
for (auto member : decl->getMembers()) {
926-
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
927-
if (!ctor->isInvalid()) {
928-
auto type = getMemberTypeForComparison(ctx, ctor, nullptr);
929-
declaredInitializers.push_back({ctor, type});
930-
}
931-
}
932-
}
933-
934923
// We can only inherit initializers if we have a superclass.
935924
// FIXME: We should be bailing out earlier in the function, but unfortunately
936925
// that currently regresses associated type inference for cases like
@@ -942,6 +931,7 @@ static void addImplicitInheritedConstructorsToClass(ClassDecl *decl) {
942931

943932
// Check whether the user has defined a designated initializer for this class,
944933
// and whether all of its stored properties have initial values.
934+
auto &ctx = decl->getASTContext();
945935
bool foundDesignatedInit = hasUserDefinedDesignatedInit(ctx.evaluator, decl);
946936
bool defaultInitable =
947937
areAllStoredPropertiesDefaultInitializable(ctx.evaluator, decl);
@@ -985,14 +975,19 @@ static void addImplicitInheritedConstructorsToClass(ClassDecl *decl) {
985975
// A designated or required initializer has not been overridden.
986976

987977
bool alreadyDeclared = false;
988-
for (const auto &ctorAndType : declaredInitializers) {
989-
auto *ctor = ctorAndType.first;
990-
auto type = ctorAndType.second;
991-
auto parentType = getMemberTypeForComparison(ctx, superclassCtor, ctor);
992-
993-
if (isOverrideBasedOnType(ctor, type, superclassCtor, parentType)) {
994-
alreadyDeclared = true;
995-
break;
978+
for (auto *member : decl->getMembers()) {
979+
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
980+
// Skip any invalid constructors.
981+
if (ctor->isInvalid())
982+
continue;
983+
984+
auto type = swift::getMemberTypeForComparison(ctor, nullptr);
985+
auto parentType = swift::getMemberTypeForComparison(superclassCtor, ctor);
986+
987+
if (isOverrideBasedOnType(ctor, type, superclassCtor, parentType)) {
988+
alreadyDeclared = true;
989+
break;
990+
}
996991
}
997992
}
998993

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,14 @@ static Type dropResultOptionality(Type type, unsigned uncurryLevel) {
6565
return FunctionType::get(parameters, resultType, fnType->getExtInfo());
6666
}
6767

68-
Type swift::getMemberTypeForComparison(ASTContext &ctx, ValueDecl *member,
69-
ValueDecl *derivedDecl) {
68+
Type swift::getMemberTypeForComparison(const ValueDecl *member,
69+
const ValueDecl *derivedDecl) {
7070
auto *method = dyn_cast<AbstractFunctionDecl>(member);
71-
ConstructorDecl *ctor = nullptr;
72-
if (method)
73-
ctor = dyn_cast<ConstructorDecl>(method);
71+
auto *ctor = dyn_cast_or_null<ConstructorDecl>(method);
7472

7573
auto abstractStorage = dyn_cast<AbstractStorageDecl>(member);
7674
assert((method || abstractStorage) && "Not a method or abstractStorage?");
77-
SubscriptDecl *subscript = dyn_cast_or_null<SubscriptDecl>(abstractStorage);
75+
auto *subscript = dyn_cast_or_null<SubscriptDecl>(abstractStorage);
7876

7977
auto memberType = member->getInterfaceType();
8078
if (memberType->is<ErrorType>())
@@ -112,8 +110,9 @@ Type swift::getMemberTypeForComparison(ASTContext &ctx, ValueDecl *member,
112110
return memberType;
113111
}
114112

115-
static bool areAccessorsOverrideCompatible(AbstractStorageDecl *storage,
116-
AbstractStorageDecl *parentStorage) {
113+
static bool
114+
areAccessorsOverrideCompatible(const AbstractStorageDecl *storage,
115+
const AbstractStorageDecl *parentStorage) {
117116
// It's okay for the storage to disagree about whether to use a getter or
118117
// a read accessor; we'll patch up any differences when setting overrides
119118
// for the accessors. We don't want to diagnose anything involving
@@ -143,8 +142,9 @@ static bool areAccessorsOverrideCompatible(AbstractStorageDecl *storage,
143142
return true;
144143
}
145144

146-
bool swift::isOverrideBasedOnType(ValueDecl *decl, Type declTy,
147-
ValueDecl *parentDecl, Type parentDeclTy) {
145+
bool swift::isOverrideBasedOnType(const ValueDecl *decl, Type declTy,
146+
const ValueDecl *parentDecl,
147+
Type parentDeclTy) {
148148
auto genericSig =
149149
decl->getInnermostDeclContext()->getGenericSignatureOfContext();
150150

@@ -667,7 +667,7 @@ namespace {
667667
/// Retrieve the type of the declaration, to be used in comparisons.
668668
Type getDeclComparisonType() {
669669
if (!cachedDeclType) {
670-
cachedDeclType = getMemberTypeForComparison(ctx, decl);
670+
cachedDeclType = getMemberTypeForComparison(decl);
671671
}
672672

673673
return cachedDeclType;
@@ -756,7 +756,7 @@ SmallVector<OverrideMatch, 2> OverrideMatcher::match(
756756
(void)parentStorage;
757757

758758
// Check whether the types are identical.
759-
auto parentDeclTy = getMemberTypeForComparison(ctx, parentDecl, decl);
759+
auto parentDeclTy = getMemberTypeForComparison(parentDecl, decl);
760760
if (parentDeclTy->hasError())
761761
continue;
762762

@@ -931,7 +931,7 @@ static void checkOverrideAccessControl(ValueDecl *baseDecl, ValueDecl *decl,
931931
bool OverrideMatcher::checkOverride(ValueDecl *baseDecl,
932932
OverrideCheckingAttempt attempt) {
933933
auto &diags = ctx.Diags;
934-
auto baseTy = getMemberTypeForComparison(ctx, baseDecl, decl);
934+
auto baseTy = getMemberTypeForComparison(baseDecl, decl);
935935
bool emittedMatchError = false;
936936

937937
// If the name of our match differs from the name we were looking for,

lib/Sema/TypeChecker.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2024,13 +2024,13 @@ OverrideRequiresKeyword overrideRequiresKeyword(ValueDecl *overridden);
20242024

20252025
/// Compute the type of a member that will be used for comparison when
20262026
/// performing override checking.
2027-
Type getMemberTypeForComparison(ASTContext &ctx, ValueDecl *member,
2028-
ValueDecl *derivedDecl = nullptr);
2027+
Type getMemberTypeForComparison(const ValueDecl *member,
2028+
const ValueDecl *derivedDecl = nullptr);
20292029

20302030
/// Determine whether the given declaration is an override by comparing type
20312031
/// information.
2032-
bool isOverrideBasedOnType(ValueDecl *decl, Type declTy,
2033-
ValueDecl *parentDecl, Type parentDeclTy);
2032+
bool isOverrideBasedOnType(const ValueDecl *decl, Type declTy,
2033+
const ValueDecl *parentDecl, Type parentDeclTy);
20342034

20352035
/// Determine whether the given declaration is an operator defined in a
20362036
/// protocol. If \p type is not null, check specifically whether \p decl

validation-test/compiler_crashers_2_fixed/0124-sr5825.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend %s -emit-ir
1+
// RUN: %target-typecheck-verify-swift
22

33
struct DefaultAssociatedType {
44
}
@@ -10,7 +10,7 @@ protocol Protocol {
1010

1111
final class Conformance: Protocol {
1212
private let object: AssociatedType
13-
init(object: AssociatedType) {
13+
init(object: AssociatedType) { // expected-error {{reference to invalid associated type 'AssociatedType' of type 'Conformance'}}
1414
self.object = object
1515
}
1616
}

0 commit comments

Comments
 (0)