Skip to content

Pre-Request Cleanup For Implicit Constructors #27978

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 14 additions & 19 deletions lib/Sema/CodeSynthesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -920,17 +920,6 @@ static void addImplicitInheritedConstructorsToClass(ClassDecl *decl) {

decl->setAddedImplicitInitializers();

auto &ctx = decl->getASTContext();
SmallVector<std::pair<ValueDecl *, Type>, 4> declaredInitializers;
for (auto member : decl->getMembers()) {
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
if (!ctor->isInvalid()) {
auto type = getMemberTypeForComparison(ctx, ctor, nullptr);
declaredInitializers.push_back({ctor, type});
}
}
}

// We can only inherit initializers if we have a superclass.
// FIXME: We should be bailing out earlier in the function, but unfortunately
// that currently regresses associated type inference for cases like
Expand All @@ -942,6 +931,7 @@ static void addImplicitInheritedConstructorsToClass(ClassDecl *decl) {

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

bool alreadyDeclared = false;
for (const auto &ctorAndType : declaredInitializers) {
auto *ctor = ctorAndType.first;
auto type = ctorAndType.second;
auto parentType = getMemberTypeForComparison(ctx, superclassCtor, ctor);

if (isOverrideBasedOnType(ctor, type, superclassCtor, parentType)) {
alreadyDeclared = true;
break;
for (auto *member : decl->getMembers()) {
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
// Skip any invalid constructors.
if (ctor->isInvalid())
continue;

auto type = swift::getMemberTypeForComparison(ctor, nullptr);
auto parentType = swift::getMemberTypeForComparison(superclassCtor, ctor);

if (isOverrideBasedOnType(ctor, type, superclassCtor, parentType)) {
alreadyDeclared = true;
break;
}
}
}

Expand Down
26 changes: 13 additions & 13 deletions lib/Sema/TypeCheckDeclOverride.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,14 @@ static Type dropResultOptionality(Type type, unsigned uncurryLevel) {
return FunctionType::get(parameters, resultType, fnType->getExtInfo());
}

Type swift::getMemberTypeForComparison(ASTContext &ctx, ValueDecl *member,
ValueDecl *derivedDecl) {
Type swift::getMemberTypeForComparison(const ValueDecl *member,
const ValueDecl *derivedDecl) {
auto *method = dyn_cast<AbstractFunctionDecl>(member);
ConstructorDecl *ctor = nullptr;
if (method)
ctor = dyn_cast<ConstructorDecl>(method);
auto *ctor = dyn_cast_or_null<ConstructorDecl>(method);

auto abstractStorage = dyn_cast<AbstractStorageDecl>(member);
assert((method || abstractStorage) && "Not a method or abstractStorage?");
SubscriptDecl *subscript = dyn_cast_or_null<SubscriptDecl>(abstractStorage);
auto *subscript = dyn_cast_or_null<SubscriptDecl>(abstractStorage);

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

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

bool swift::isOverrideBasedOnType(ValueDecl *decl, Type declTy,
ValueDecl *parentDecl, Type parentDeclTy) {
bool swift::isOverrideBasedOnType(const ValueDecl *decl, Type declTy,
const ValueDecl *parentDecl,
Type parentDeclTy) {
auto genericSig =
decl->getInnermostDeclContext()->getGenericSignatureOfContext();

Expand Down Expand Up @@ -667,7 +667,7 @@ namespace {
/// Retrieve the type of the declaration, to be used in comparisons.
Type getDeclComparisonType() {
if (!cachedDeclType) {
cachedDeclType = getMemberTypeForComparison(ctx, decl);
cachedDeclType = getMemberTypeForComparison(decl);
}

return cachedDeclType;
Expand Down Expand Up @@ -756,7 +756,7 @@ SmallVector<OverrideMatch, 2> OverrideMatcher::match(
(void)parentStorage;

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

Expand Down Expand Up @@ -931,7 +931,7 @@ static void checkOverrideAccessControl(ValueDecl *baseDecl, ValueDecl *decl,
bool OverrideMatcher::checkOverride(ValueDecl *baseDecl,
OverrideCheckingAttempt attempt) {
auto &diags = ctx.Diags;
auto baseTy = getMemberTypeForComparison(ctx, baseDecl, decl);
auto baseTy = getMemberTypeForComparison(baseDecl, decl);
bool emittedMatchError = false;

// If the name of our match differs from the name we were looking for,
Expand Down
8 changes: 4 additions & 4 deletions lib/Sema/TypeChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -2024,13 +2024,13 @@ OverrideRequiresKeyword overrideRequiresKeyword(ValueDecl *overridden);

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

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

/// Determine whether the given declaration is an operator defined in a
/// protocol. If \p type is not null, check specifically whether \p decl
Expand Down
4 changes: 2 additions & 2 deletions validation-test/compiler_crashers_2_fixed/0124-sr5825.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend %s -emit-ir
// RUN: %target-typecheck-verify-swift

struct DefaultAssociatedType {
}
Expand All @@ -10,7 +10,7 @@ protocol Protocol {

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