Skip to content

Commit ae60618

Browse files
committed
Remove resolveExtension and validateExtension
Push the relevant work this was doing down into the callers. Most of them didn't want to validate the entire extension and force its generic parameters, they just wanted to validate the nominal type. We must eagerly validate the generic signature of extensions, though. This avoids a class of cycles where non-generic members of an extension with a generic signaure will call through to getGenericSignatureOfContext and force the generic signature anyways. When this calls through to protocol witness matching, the signature can be recursively computed.
1 parent 9913470 commit ae60618

File tree

8 files changed

+47
-61
lines changed

8 files changed

+47
-61
lines changed

include/swift/AST/LazyResolver.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,6 @@ class LazyResolver {
6060
/// consistency and provides the value a type.
6161
virtual void resolveDeclSignature(ValueDecl *VD) = 0;
6262

63-
/// Resolve the type of an extension.
64-
///
65-
/// This can be called to ensure that the members of an extension can be
66-
/// considered to be members of the extended type.
67-
virtual void resolveExtension(ExtensionDecl *ext) = 0;
68-
6963
/// Resolve any implicitly-declared constructors within the given nominal.
7064
virtual void resolveImplicitConstructors(NominalTypeDecl *nominal) = 0;
7165

lib/AST/ConformanceLookupTable.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -798,8 +798,8 @@ ConformanceLookupTable::getConformance(NominalTypeDecl *nominal,
798798
// Everything about this conformance is nailed down, so we can now ensure that
799799
// the extension is fully resolved.
800800
if (auto resolver = nominal->getASTContext().getLazyResolver()) {
801-
if (auto ED = dyn_cast<ExtensionDecl>(conformingDC)) {
802-
resolver->resolveExtension(ED);
801+
if (auto ext = dyn_cast<ExtensionDecl>(conformingDC)) {
802+
resolver->resolveDeclSignature(ext->getExtendedNominal());
803803
} else {
804804
resolver->resolveDeclSignature(cast<NominalTypeDecl>(conformingDC));
805805
}

lib/AST/Type.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,8 +1098,8 @@ CanType TypeBase::computeCanonicalType() {
10981098
assert(resolver && "Need to resolve generic parameter depth");
10991099
if (auto decl =
11001100
gpDecl->getDeclContext()->getInnermostDeclarationDeclContext())
1101-
if (auto valueDecl = dyn_cast<ValueDecl>(decl))
1102-
resolver->resolveDeclSignature(valueDecl);
1101+
if (auto valueDecl = decl->getAsGenericContext())
1102+
(void)valueDecl->getGenericSignature();
11031103
}
11041104

11051105
assert(gpDecl->getDepth() != GenericTypeParamDecl::InvalidDepth &&

lib/Sema/IDETypeCheckingRequests.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,7 @@ static bool isExtensionAppliedInternal(const DeclContext *DC, Type BaseTy,
5656
if (!ED->isConstrainedExtension())
5757
return true;
5858

59-
TypeChecker *TC = &TypeChecker::createForContext((DC->getASTContext()));
60-
TC->validateExtension(const_cast<ExtensionDecl *>(ED));
61-
59+
(void)TypeChecker::createForContext(DC->getASTContext());
6260
GenericSignature *genericSig = ED->getGenericSignature();
6361
SubstitutionMap substMap = BaseTy->getContextSubstitutionMap(
6462
DC->getParentModule(), ED->getExtendedNominal());

lib/Sema/TypeCheckDecl.cpp

Lines changed: 24 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3086,9 +3086,14 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
30863086
return;
30873087
}
30883088

3089-
TC.validateExtension(ED);
3089+
// Validate the nominal type declaration being extended.
3090+
TC.validateDecl(nominal);
3091+
// Don't bother computing the generic signature if the extended nominal
3092+
// type didn't pass validation so we don't crash.
3093+
if (!nominal->isInvalid())
3094+
(void)ED->getGenericSignature();
3095+
ED->setValidationToChecked();
30903096

3091-
extType = ED->getExtendedType();
30923097
if (extType && !extType->hasError()) {
30933098
// The first condition catches syntactic forms like
30943099
// protocol A & B { ... } // may be protocols or typealiases
@@ -3757,7 +3762,20 @@ void TypeChecker::validateDecl(ValueDecl *D) {
37573762
if (!nominal->hasValidSignature())
37583763
return;
37593764
} else if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
3760-
validateExtension(ext);
3765+
// If we're currently validating, or have already validated this extension,
3766+
// there's nothing more to do now.
3767+
if (!ext->hasValidationStarted()) {
3768+
DeclValidationRAII IBV(ext);
3769+
3770+
if (auto *nominal = ext->getExtendedNominal()) {
3771+
// Validate the nominal type declaration being extended.
3772+
validateDecl(nominal);
3773+
3774+
// Eagerly validate the generic signature of the extension.
3775+
if (!nominal->isInvalid())
3776+
(void)ext->getGenericSignature();
3777+
}
3778+
}
37613779
if (!ext->hasValidSignature())
37623780
return;
37633781
}
@@ -3819,7 +3837,7 @@ void TypeChecker::validateDecl(ValueDecl *D) {
38193837

38203838
case DeclKind::OpaqueType: {
38213839
auto opaque = cast<OpaqueTypeDecl>(D);
3822-
DeclValidationRAII IBV(opaque);
3840+
opaque->setValidationToChecked();
38233841
break;
38243842
}
38253843

@@ -3828,11 +3846,7 @@ void TypeChecker::validateDecl(ValueDecl *D) {
38283846
case DeclKind::Class: {
38293847
auto nominal = cast<NominalTypeDecl>(D);
38303848
nominal->computeType();
3831-
3832-
// Check generic parameters, if needed.
3833-
DeclValidationRAII IBV(nominal);
3834-
(void)nominal->getGenericSignature();
3835-
nominal->setSignatureIsValidated();
3849+
nominal->setValidationToChecked();
38363850

38373851
if (auto *ED = dyn_cast<EnumDecl>(nominal)) {
38383852
// @objc enums use their raw values as the value representation, so we
@@ -3848,11 +3862,7 @@ void TypeChecker::validateDecl(ValueDecl *D) {
38483862
auto proto = cast<ProtocolDecl>(D);
38493863
if (!proto->hasInterfaceType())
38503864
proto->computeType();
3851-
3852-
// Validate the generic type signature, which is just <Self : P>.
3853-
DeclValidationRAII IBV(proto);
3854-
(void)proto->getGenericSignature();
3855-
proto->setSignatureIsValidated();
3865+
proto->setValidationToChecked();
38563866

38573867
break;
38583868
}
@@ -4349,26 +4359,6 @@ ExtendedTypeRequest::evaluate(Evaluator &eval, ExtensionDecl *ext) const {
43494359
return extendedType;
43504360
}
43514361

4352-
void TypeChecker::validateExtension(ExtensionDecl *ext) {
4353-
// If we're currently validating, or have already validated this extension,
4354-
// there's nothing more to do now.
4355-
if (ext->hasValidationStarted())
4356-
return;
4357-
4358-
DeclValidationRAII IBV(ext);
4359-
4360-
if (auto *nominal = ext->getExtendedNominal()) {
4361-
// Validate the nominal type declaration being extended.
4362-
validateDecl(nominal);
4363-
4364-
// FIXME: validateExtension is going to disappear soon. In the mean time
4365-
// don't bother computing the generic signature if the extended nominal type
4366-
// didn't pass validation so we don't crash.
4367-
if (!nominal->isInvalid())
4368-
(void)ext->getGenericSignature();
4369-
}
4370-
}
4371-
43724362
/// Build a default initializer string for the given pattern.
43734363
///
43744364
/// This string is suitable for display in diagnostics.

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -188,22 +188,27 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
188188
// Invalid case.
189189
if (extendedNominal == nullptr)
190190
return true;
191-
191+
192+
// Validate the nominal type being extended.
193+
tc.validateDecl(extendedNominal);
194+
if (extendedNominal->isInvalid())
195+
return true;
196+
192197
// Assume unconstrained concrete extensions we found witnesses in are
193198
// always viable.
194199
if (!isa<ProtocolDecl>(extendedNominal))
195200
return !extension->isConstrainedExtension();
196-
197-
// Build a generic signature.
198-
tc.validateExtension(extension);
199-
201+
200202
// FIXME: The extension may not have a generic signature set up yet as
201203
// resolving signatures may trigger associated type inference. This cycle
202204
// is now detectable and we should look into untangling it
203205
// - see rdar://55263708
204206
if (!extension->hasComputedGenericSignature())
205207
return true;
206208

209+
// Build a generic signature.
210+
auto *extensionSig = extension->getGenericSignature();
211+
207212
// The condition here is a bit more fickle than
208213
// `isExtensionApplied`. That check would prematurely reject
209214
// extensions like `P where AssocType == T` if we're relying on a
@@ -212,8 +217,7 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
212217
// because those have to be explicitly declared on the type somewhere
213218
// so won't be affected by whatever answer inference comes up with.
214219
auto selfTy = extension->getSelfInterfaceType();
215-
for (const Requirement &reqt
216-
: extension->getGenericSignature()->getRequirements()) {
220+
for (const Requirement &reqt : extensionSig->getRequirements()) {
217221
switch (reqt.getKind()) {
218222
case RequirementKind::Conformance:
219223
case RequirementKind::Superclass:

lib/Sema/TypeChecker.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -614,10 +614,14 @@ void swift::typeCheckCompletionDecl(Decl *D) {
614614
DiagnosticSuppression suppression(Ctx.Diags);
615615
TypeChecker &TC = createTypeChecker(Ctx);
616616

617-
if (auto ext = dyn_cast<ExtensionDecl>(D))
618-
TC.validateExtension(ext);
619-
else
617+
if (auto ext = dyn_cast<ExtensionDecl>(D)) {
618+
if (auto *nominal = ext->getExtendedNominal()) {
619+
// Validate the nominal type declaration being extended.
620+
TC.validateDecl(nominal);
621+
}
622+
} else {
620623
TC.validateDecl(cast<ValueDecl>(D));
624+
}
621625
}
622626

623627
void swift::typeCheckPatternBinding(PatternBindingDecl *PBD,

lib/Sema/TypeChecker.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,10 +1015,6 @@ class TypeChecker final : public LazyResolver {
10151015
validateDecl(VD);
10161016
}
10171017

1018-
virtual void resolveExtension(ExtensionDecl *ext) override {
1019-
validateExtension(ext);
1020-
}
1021-
10221018
virtual void resolveImplicitConstructors(NominalTypeDecl *nominal) override {
10231019
addImplicitConstructors(nominal);
10241020
}

0 commit comments

Comments
 (0)