Skip to content

Commit 053a44e

Browse files
committed
Sema: Move most of DeclChecker::visitConstructorDecl() to validateDecl()
1 parent 9aca8e1 commit 053a44e

File tree

1 file changed

+182
-177
lines changed

1 file changed

+182
-177
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 182 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -6928,174 +6928,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
69286928
checkAccessControl(TC, CD);
69296929
return;
69306930
}
6931-
if (CD->hasInterfaceType() || CD->isBeingValidated())
6932-
return;
6933-
6934-
CD->setIsBeingValidated();
6935-
6936-
TC.checkDeclAttributesEarly(CD);
6937-
TC.computeAccessLevel(CD);
6938-
6939-
// convenience initializers are only allowed on classes and in
6940-
// extensions thereof.
6941-
if (CD->isConvenienceInit()) {
6942-
if (auto extType = CD->getDeclContext()->getDeclaredInterfaceType()) {
6943-
auto extClass = extType->getClassOrBoundGenericClass();
6944-
6945-
// Forbid convenience inits on Foreign CF types, as Swift does not yet
6946-
// support user-defined factory inits.
6947-
if (extClass &&
6948-
extClass->getForeignClassKind() == ClassDecl::ForeignKind::CFType) {
6949-
TC.diagnose(CD->getLoc(), diag::cfclass_convenience_init);
6950-
}
6951-
6952-
if (!extClass && !extType->hasError()) {
6953-
auto ConvenienceLoc =
6954-
CD->getAttrs().getAttribute<ConvenienceAttr>()->getLocation();
6955-
6956-
// Produce a tailored diagnostic for structs and enums.
6957-
bool isStruct = extType->getStructOrBoundGenericStruct() != nullptr;
6958-
if (isStruct || extType->getEnumOrBoundGenericEnum()) {
6959-
TC.diagnose(CD->getLoc(), diag::enumstruct_convenience_init,
6960-
isStruct ? "structs" : "enums")
6961-
.fixItRemove(ConvenienceLoc);
6962-
} else {
6963-
TC.diagnose(CD->getLoc(), diag::nonclass_convenience_init, extType)
6964-
.fixItRemove(ConvenienceLoc);
6965-
}
6966-
CD->setInitKind(CtorInitializerKind::Designated);
6967-
}
6968-
}
6969-
} else if (auto extType = CD->getDeclContext()->getDeclaredInterfaceType()) {
6970-
// A designated initializer for a class must be written within the class
6971-
// itself.
6972-
//
6973-
// This is because designated initializers of classes get a vtable entry,
6974-
// and extensions cannot add vtable entries to the extended type.
6975-
//
6976-
// If we implement the ability for extensions defined in the same module
6977-
// (or the same file) to add vtable entries, we can re-evaluate this
6978-
// restriction.
6979-
if (extType->getClassOrBoundGenericClass() &&
6980-
isa<ExtensionDecl>(CD->getDeclContext())) {
6981-
TC.diagnose(CD->getLoc(), diag::designated_init_in_extension, extType)
6982-
.fixItInsert(CD->getLoc(), "convenience ");
6983-
CD->setInitKind(CtorInitializerKind::Convenience);
6984-
} else if (CD->getDeclContext()->getAsProtocolExtensionContext()) {
6985-
CD->setInitKind(CtorInitializerKind::Convenience);
6986-
}
6987-
}
6988-
6989-
if (CD->getDeclContext()->isTypeContext())
6990-
configureImplicitSelf(TC, CD);
6991-
6992-
if (auto gp = CD->getGenericParams()) {
6993-
// Write up generic parameters and check the generic parameter list.
6994-
gp->setOuterParameters(CD->getDeclContext()->getGenericParamsOfContext());
6995-
6996-
auto *sig = TC.validateGenericFuncSignature(CD);
6997-
auto *env = sig->createGenericEnvironment();
6998-
CD->setGenericEnvironment(env);
6999-
7000-
// Revert the types within the signature so it can be type-checked with
7001-
// archetypes below.
7002-
TC.revertGenericFuncSignature(CD);
7003-
} else if (CD->getDeclContext()->getGenericSignatureOfContext()) {
7004-
(void)TC.validateGenericFuncSignature(CD);
70056931

7006-
// Revert all of the types within the signature of the constructor.
7007-
TC.revertGenericFuncSignature(CD);
7008-
7009-
CD->setGenericEnvironment(
7010-
CD->getDeclContext()->getGenericEnvironmentOfContext());
7011-
}
7012-
7013-
// Set the context type of 'self'.
7014-
if (CD->getDeclContext()->isTypeContext())
7015-
recordSelfContextType(CD);
7016-
7017-
// Type check the constructor parameters.
7018-
GenericTypeToArchetypeResolver resolver(CD);
7019-
if (TC.typeCheckParameterLists(CD, resolver) || CD->isInvalid()) {
7020-
CD->setInterfaceType(ErrorType::get(TC.Context));
7021-
CD->setInvalid();
7022-
} else {
7023-
if (!CD->getGenericSignatureOfContext())
7024-
TC.configureInterfaceType(CD, CD->getGenericSignature());
7025-
}
7026-
7027-
// We want the constructor to be available for name lookup as soon
7028-
// as it has a valid interface type.
7029-
CD->setIsBeingValidated(false);
7030-
7031-
validateAttributes(TC, CD);
7032-
7033-
// Check whether this initializer overrides an initializer in its
7034-
// superclass.
7035-
if (!checkOverrides(TC, CD)) {
7036-
// If an initializer has an override attribute but does not override
7037-
// anything or overrides something that doesn't need an 'override'
7038-
// keyword (e.g., a convenience initializer), complain.
7039-
// anything, or overrides something that complain.
7040-
if (auto *attr = CD->getAttrs().getAttribute<OverrideAttr>()) {
7041-
if (!CD->getOverriddenDecl()) {
7042-
TC.diagnose(CD, diag::initializer_does_not_override)
7043-
.highlight(attr->getLocation());
7044-
attr->setInvalid();
7045-
} else if (!overrideRequiresKeyword(CD->getOverriddenDecl())) {
7046-
// Special case: we are overriding a 'required' initializer, so we
7047-
// need (only) the 'required' keyword.
7048-
if (cast<ConstructorDecl>(CD->getOverriddenDecl())->isRequired()) {
7049-
if (CD->getAttrs().hasAttribute<RequiredAttr>()) {
7050-
TC.diagnose(CD, diag::required_initializer_override_keyword)
7051-
.fixItRemove(attr->getLocation());
7052-
} else {
7053-
TC.diagnose(CD, diag::required_initializer_override_wrong_keyword)
7054-
.fixItReplace(attr->getLocation(), "required");
7055-
CD->getAttrs().add(
7056-
new (TC.Context) RequiredAttr(/*IsImplicit=*/true));
7057-
}
7058-
7059-
TC.diagnose(findNonImplicitRequiredInit(CD->getOverriddenDecl()),
7060-
diag::overridden_required_initializer_here);
7061-
} else {
7062-
// We tried to override a convenience initializer.
7063-
TC.diagnose(CD, diag::initializer_does_not_override)
7064-
.highlight(attr->getLocation());
7065-
TC.diagnose(CD->getOverriddenDecl(),
7066-
diag::convenience_init_override_here);
7067-
}
7068-
}
7069-
}
7070-
7071-
// A failable initializer cannot override a non-failable one.
7072-
// This would normally be diagnosed by the covariance rules;
7073-
// however, those are disabled so that we can provide a more
7074-
// specific diagnostic here.
7075-
if (CD->getFailability() != OTK_None &&
7076-
CD->getOverriddenDecl() &&
7077-
CD->getOverriddenDecl()->getFailability() == OTK_None) {
7078-
TC.diagnose(CD, diag::failable_initializer_override,
7079-
CD->getFullName());
7080-
TC.diagnose(CD->getOverriddenDecl(),
7081-
diag::nonfailable_initializer_override_here,
7082-
CD->getOverriddenDecl()->getFullName());
7083-
}
7084-
}
7085-
7086-
// An initializer is ObjC-compatible if it's explicitly @objc or a member
7087-
// of an ObjC-compatible class.
7088-
if (CD->getDeclContext()->isTypeContext()) {
7089-
Optional<ObjCReason> isObjC = shouldMarkAsObjC(TC, CD,
7090-
/*allowImplicit=*/true);
7091-
7092-
Optional<ForeignErrorConvention> errorConvention;
7093-
if (isObjC &&
7094-
(CD->isInvalid() ||
7095-
!TC.isRepresentableInObjC(CD, *isObjC, errorConvention)))
7096-
isObjC = None;
7097-
markAsObjC(TC, CD, isObjC, errorConvention);
7098-
}
6932+
TC.validateDecl(CD);
70996933

71006934
// If this initializer overrides a 'required' initializer, it must itself
71016935
// be marked 'required'.
@@ -7137,14 +6971,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
71376971
}
71386972
}
71396973

7140-
inferDynamic(TC.Context, CD);
7141-
7142-
if (CD->getFailability() == OTK_ImplicitlyUnwrappedOptional) {
7143-
auto &C = CD->getASTContext();
7144-
CD->getAttrs().add(
7145-
new (C) ImplicitlyUnwrappedOptionalAttr(/* implicit= */ true));
7146-
}
7147-
71486974
TC.checkDeclAttributes(CD);
71496975
}
71506976

@@ -7665,12 +7491,191 @@ void TypeChecker::validateDecl(ValueDecl *D) {
76657491
}
76667492

76677493
case DeclKind::Func:
7668-
case DeclKind::Accessor:
7669-
case DeclKind::Constructor: {
7494+
case DeclKind::Accessor: {
76707495
typeCheckDecl(D, true);
76717496
break;
76727497
}
76737498

7499+
case DeclKind::Constructor: {
7500+
auto *CD = cast<ConstructorDecl>(D);
7501+
7502+
CD->setIsBeingValidated();
7503+
7504+
checkDeclAttributesEarly(CD);
7505+
computeAccessLevel(CD);
7506+
7507+
// convenience initializers are only allowed on classes and in
7508+
// extensions thereof.
7509+
if (CD->isConvenienceInit()) {
7510+
if (auto extType = CD->getDeclContext()->getDeclaredInterfaceType()) {
7511+
auto extClass = extType->getClassOrBoundGenericClass();
7512+
7513+
// Forbid convenience inits on Foreign CF types, as Swift does not yet
7514+
// support user-defined factory inits.
7515+
if (extClass &&
7516+
extClass->getForeignClassKind() == ClassDecl::ForeignKind::CFType) {
7517+
diagnose(CD->getLoc(), diag::cfclass_convenience_init);
7518+
}
7519+
7520+
if (!extClass && !extType->hasError()) {
7521+
auto ConvenienceLoc =
7522+
CD->getAttrs().getAttribute<ConvenienceAttr>()->getLocation();
7523+
7524+
// Produce a tailored diagnostic for structs and enums.
7525+
bool isStruct = extType->getStructOrBoundGenericStruct() != nullptr;
7526+
if (isStruct || extType->getEnumOrBoundGenericEnum()) {
7527+
diagnose(CD->getLoc(), diag::enumstruct_convenience_init,
7528+
isStruct ? "structs" : "enums")
7529+
.fixItRemove(ConvenienceLoc);
7530+
} else {
7531+
diagnose(CD->getLoc(), diag::nonclass_convenience_init, extType)
7532+
.fixItRemove(ConvenienceLoc);
7533+
}
7534+
CD->setInitKind(CtorInitializerKind::Designated);
7535+
}
7536+
}
7537+
} else if (auto extType = CD->getDeclContext()->getDeclaredInterfaceType()) {
7538+
// A designated initializer for a class must be written within the class
7539+
// itself.
7540+
//
7541+
// This is because designated initializers of classes get a vtable entry,
7542+
// and extensions cannot add vtable entries to the extended type.
7543+
//
7544+
// If we implement the ability for extensions defined in the same module
7545+
// (or the same file) to add vtable entries, we can re-evaluate this
7546+
// restriction.
7547+
if (extType->getClassOrBoundGenericClass() &&
7548+
isa<ExtensionDecl>(CD->getDeclContext())) {
7549+
diagnose(CD->getLoc(), diag::designated_init_in_extension, extType)
7550+
.fixItInsert(CD->getLoc(), "convenience ");
7551+
CD->setInitKind(CtorInitializerKind::Convenience);
7552+
} else if (CD->getDeclContext()->getAsProtocolExtensionContext()) {
7553+
CD->setInitKind(CtorInitializerKind::Convenience);
7554+
}
7555+
}
7556+
7557+
if (CD->getDeclContext()->isTypeContext())
7558+
configureImplicitSelf(*this, CD);
7559+
7560+
if (auto gp = CD->getGenericParams()) {
7561+
// Write up generic parameters and check the generic parameter list.
7562+
gp->setOuterParameters(CD->getDeclContext()->getGenericParamsOfContext());
7563+
7564+
auto *sig = validateGenericFuncSignature(CD);
7565+
auto *env = sig->createGenericEnvironment();
7566+
CD->setGenericEnvironment(env);
7567+
7568+
// Revert the types within the signature so it can be type-checked with
7569+
// archetypes below.
7570+
revertGenericFuncSignature(CD);
7571+
} else if (CD->getDeclContext()->getGenericSignatureOfContext()) {
7572+
(void)validateGenericFuncSignature(CD);
7573+
7574+
// Revert all of the types within the signature of the constructor.
7575+
revertGenericFuncSignature(CD);
7576+
7577+
CD->setGenericEnvironment(
7578+
CD->getDeclContext()->getGenericEnvironmentOfContext());
7579+
}
7580+
7581+
// Set the context type of 'self'.
7582+
if (CD->getDeclContext()->isTypeContext())
7583+
recordSelfContextType(CD);
7584+
7585+
// Type check the constructor parameters.
7586+
GenericTypeToArchetypeResolver resolver(CD);
7587+
if (typeCheckParameterLists(CD, resolver) || CD->isInvalid()) {
7588+
CD->setInterfaceType(ErrorType::get(Context));
7589+
CD->setInvalid();
7590+
} else {
7591+
if (!CD->getGenericSignatureOfContext())
7592+
configureInterfaceType(CD, CD->getGenericSignature());
7593+
}
7594+
7595+
// We want the constructor to be available for name lookup as soon
7596+
// as it has a valid interface type.
7597+
CD->setIsBeingValidated(false);
7598+
7599+
validateAttributes(*this, CD);
7600+
7601+
// Check whether this initializer overrides an initializer in its
7602+
// superclass.
7603+
if (!checkOverrides(*this, CD)) {
7604+
// If an initializer has an override attribute but does not override
7605+
// anything or overrides something that doesn't need an 'override'
7606+
// keyword (e.g., a convenience initializer), complain.
7607+
// anything, or overrides something that complain.
7608+
if (auto *attr = CD->getAttrs().getAttribute<OverrideAttr>()) {
7609+
if (!CD->getOverriddenDecl()) {
7610+
diagnose(CD, diag::initializer_does_not_override)
7611+
.highlight(attr->getLocation());
7612+
attr->setInvalid();
7613+
} else if (!DeclChecker::overrideRequiresKeyword(CD->getOverriddenDecl())) {
7614+
// Special case: we are overriding a 'required' initializer, so we
7615+
// need (only) the 'required' keyword.
7616+
if (cast<ConstructorDecl>(CD->getOverriddenDecl())->isRequired()) {
7617+
if (CD->getAttrs().hasAttribute<RequiredAttr>()) {
7618+
diagnose(CD, diag::required_initializer_override_keyword)
7619+
.fixItRemove(attr->getLocation());
7620+
} else {
7621+
diagnose(CD, diag::required_initializer_override_wrong_keyword)
7622+
.fixItReplace(attr->getLocation(), "required");
7623+
CD->getAttrs().add(
7624+
new (Context) RequiredAttr(/*IsImplicit=*/true));
7625+
}
7626+
7627+
diagnose(findNonImplicitRequiredInit(CD->getOverriddenDecl()),
7628+
diag::overridden_required_initializer_here);
7629+
} else {
7630+
// We tried to override a convenience initializer.
7631+
diagnose(CD, diag::initializer_does_not_override)
7632+
.highlight(attr->getLocation());
7633+
diagnose(CD->getOverriddenDecl(),
7634+
diag::convenience_init_override_here);
7635+
}
7636+
}
7637+
}
7638+
7639+
// A failable initializer cannot override a non-failable one.
7640+
// This would normally be diagnosed by the covariance rules;
7641+
// however, those are disabled so that we can provide a more
7642+
// specific diagnostic here.
7643+
if (CD->getFailability() != OTK_None &&
7644+
CD->getOverriddenDecl() &&
7645+
CD->getOverriddenDecl()->getFailability() == OTK_None) {
7646+
diagnose(CD, diag::failable_initializer_override,
7647+
CD->getFullName());
7648+
diagnose(CD->getOverriddenDecl(),
7649+
diag::nonfailable_initializer_override_here,
7650+
CD->getOverriddenDecl()->getFullName());
7651+
}
7652+
}
7653+
7654+
// An initializer is ObjC-compatible if it's explicitly @objc or a member
7655+
// of an ObjC-compatible class.
7656+
if (CD->getDeclContext()->isTypeContext()) {
7657+
Optional<ObjCReason> isObjC = shouldMarkAsObjC(*this, CD,
7658+
/*allowImplicit=*/true);
7659+
7660+
Optional<ForeignErrorConvention> errorConvention;
7661+
if (isObjC &&
7662+
(CD->isInvalid() ||
7663+
!isRepresentableInObjC(CD, *isObjC, errorConvention)))
7664+
isObjC = None;
7665+
markAsObjC(*this, CD, isObjC, errorConvention);
7666+
}
7667+
7668+
inferDynamic(Context, CD);
7669+
7670+
if (CD->getFailability() == OTK_ImplicitlyUnwrappedOptional) {
7671+
auto &C = CD->getASTContext();
7672+
CD->getAttrs().add(
7673+
new (C) ImplicitlyUnwrappedOptionalAttr(/* implicit= */ true));
7674+
}
7675+
7676+
break;
7677+
}
7678+
76747679
case DeclKind::Destructor: {
76757680
auto *DD = cast<DestructorDecl>(D);
76767681

0 commit comments

Comments
 (0)