Skip to content

Commit ef82cd7

Browse files
committed
Sema: Merge bindExtensionDecl() into validateExtension()
1 parent 26fddb7 commit ef82cd7

File tree

5 files changed

+70
-96
lines changed

5 files changed

+70
-96
lines changed

lib/AST/DeclContext.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,11 @@ GenericTypeParamType *DeclContext::getProtocolSelfType() const {
9292
const_cast<ProtocolDecl *>(proto)->createGenericParamsIfMissing();
9393
}
9494

95-
return getGenericParamsOfContext()->getParams().front()
95+
auto *genericParams = getGenericParamsOfContext();
96+
if (genericParams == nullptr)
97+
return nullptr;
98+
99+
return genericParams->getParams().front()
96100
->getDeclaredInterfaceType()
97101
->castTo<GenericTypeParamType>();
98102
}

lib/AST/NameLookup.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,9 @@ SelfBoundsFromWhereClauseRequest::evaluate(Evaluator &evaluator,
564564

565565
ASTContext &ctx = proto->getASTContext();
566566
TinyPtrVector<NominalTypeDecl *> result;
567+
if (!ext->getGenericParams())
568+
return result;
569+
567570
for (const auto &req : ext->getGenericParams()->getTrailingRequirements()) {
568571
// We only care about type constraints.
569572
if (req.getKind() != RequirementReprKind::TypeConstraint)

lib/Sema/TypeCheckDecl.cpp

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4877,31 +4877,78 @@ void TypeChecker::validateExtension(ExtensionDecl *ext) {
48774877
if (ext->hasValidationStarted())
48784878
return;
48794879

4880-
bindExtension(ext);
4881-
48824880
DeclValidationRAII IBV(ext);
48834881

4884-
// If the extension is already known to be invalid, we're done.
4885-
if (ext->isInvalid())
4882+
auto dc = ext->getDeclContext();
4883+
4884+
// If we didn't parse a type, fill in an error type and bail out.
4885+
if (!ext->getExtendedTypeLoc().getTypeRepr()) {
4886+
ext->setInvalid();
4887+
ext->getExtendedTypeLoc().setInvalidType(Context);
4888+
return;
4889+
}
4890+
4891+
// Validate the extended type.
4892+
TypeResolutionOptions options(TypeResolverContext::ExtensionBinding);
4893+
options |= TypeResolutionFlags::AllowUnboundGenerics;
4894+
if (validateType(ext->getExtendedTypeLoc(),
4895+
TypeResolution::forContextual(dc), options)) {
4896+
ext->setInvalid();
4897+
ext->getExtendedTypeLoc().setInvalidType(Context);
48864898
return;
4899+
}
48874900

4888-
// FIXME: We need to check whether anything is specialized, because
4889-
// the innermost extended type might itself be a non-generic type
4890-
// within a generic type.
4901+
// Dig out the extended type.
48914902
auto extendedType = ext->getExtendedType();
48924903

4893-
if (extendedType.isNull() || extendedType->hasError())
4904+
// Hack to allow extending a generic typealias.
4905+
if (auto *unboundGeneric = extendedType->getAs<UnboundGenericType>()) {
4906+
if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getDecl())) {
4907+
auto extendedNominal = aliasDecl->getDeclaredInterfaceType()->getAnyNominal();
4908+
if (extendedNominal) {
4909+
extendedType = extendedNominal->getDeclaredType();
4910+
if (!isPassThroughTypealias(aliasDecl))
4911+
ext->getExtendedTypeLoc().setType(extendedType);
4912+
}
4913+
}
4914+
}
4915+
4916+
// Cannot extend a metatype.
4917+
if (extendedType->is<AnyMetatypeType>()) {
4918+
diagnose(ext->getLoc(), diag::extension_metatype, extendedType)
4919+
.highlight(ext->getExtendedTypeLoc().getSourceRange());
4920+
ext->setInvalid();
4921+
ext->getExtendedTypeLoc().setInvalidType(Context);
48944922
return;
4923+
}
48954924

4896-
// Validate the nominal type declaration being extended.
4897-
NominalTypeDecl *nominal = extendedType->getAnyNominal();
4898-
if (!nominal) {
4899-
auto unbound = cast<UnboundGenericType>(extendedType.getPointer());
4900-
auto typealias = cast<TypeAliasDecl>(unbound->getDecl());
4901-
validateDecl(typealias);
4925+
// Cannot extend a bound generic type.
4926+
if (extendedType->isSpecialized()) {
4927+
diagnose(ext->getLoc(), diag::extension_specialization,
4928+
extendedType->getAnyNominal()->getName())
4929+
.highlight(ext->getExtendedTypeLoc().getSourceRange());
4930+
ext->setInvalid();
4931+
ext->getExtendedTypeLoc().setInvalidType(Context);
4932+
return;
4933+
}
4934+
4935+
auto *nominal = extendedType->getAnyNominal();
49024936

4903-
nominal = typealias->getUnderlyingTypeLoc().getType()->getAnyNominal();
4937+
// Cannot extend function types, tuple types, etc.
4938+
if (nominal == nullptr) {
4939+
diagnose(ext->getLoc(), diag::non_nominal_extension, extendedType)
4940+
.highlight(ext->getExtendedTypeLoc().getSourceRange());
4941+
ext->setInvalid();
4942+
ext->getExtendedTypeLoc().setInvalidType(Context);
4943+
return;
49044944
}
4945+
4946+
// Extensions nested inside other declarations are invalid and we
4947+
// do not bind them.
4948+
if (!isa<SourceFile>(dc))
4949+
return;
4950+
4951+
// Validate the nominal type declaration being extended.
49054952
validateDecl(nominal);
49064953

49074954
if (nominal->getGenericParamsOfContext()) {

lib/Sema/TypeChecker.cpp

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -346,80 +346,6 @@ static void bindExtensionToNominal(ExtensionDecl *ext,
346346
nominal->addExtension(ext);
347347
}
348348

349-
static void bindExtensionDecl(ExtensionDecl *ED, TypeChecker &TC) {
350-
if (ED->getExtendedType())
351-
return;
352-
353-
// If we didn't parse a type, fill in an error type and bail out.
354-
if (!ED->getExtendedTypeLoc().getTypeRepr()) {
355-
ED->setInvalid();
356-
ED->getExtendedTypeLoc().setInvalidType(TC.Context);
357-
return;
358-
}
359-
360-
auto dc = ED->getDeclContext();
361-
362-
// Validate the representation.
363-
// FIXME: Perform some kind of "shallow" validation here?
364-
TypeResolutionOptions options(TypeResolverContext::ExtensionBinding);
365-
options |= TypeResolutionFlags::AllowUnboundGenerics;
366-
if (TC.validateType(ED->getExtendedTypeLoc(),
367-
TypeResolution::forContextual(dc), options)) {
368-
ED->setInvalid();
369-
ED->getExtendedTypeLoc().setInvalidType(TC.Context);
370-
return;
371-
}
372-
373-
// Dig out the extended type.
374-
auto extendedType = ED->getExtendedType();
375-
376-
// Hack to allow extending a generic typealias.
377-
if (auto *unboundGeneric = extendedType->getAs<UnboundGenericType>()) {
378-
if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getDecl())) {
379-
auto extendedNominal = aliasDecl->getDeclaredInterfaceType()->getAnyNominal();
380-
if (extendedNominal) {
381-
extendedType = extendedNominal->getDeclaredType();
382-
if (!isPassThroughTypealias(aliasDecl))
383-
ED->getExtendedTypeLoc().setType(extendedType);
384-
}
385-
}
386-
}
387-
388-
// Handle easy cases.
389-
390-
// Cannot extend a metatype.
391-
if (extendedType->is<AnyMetatypeType>()) {
392-
TC.diagnose(ED->getLoc(), diag::extension_metatype, extendedType)
393-
.highlight(ED->getExtendedTypeLoc().getSourceRange());
394-
ED->setInvalid();
395-
ED->getExtendedTypeLoc().setInvalidType(TC.Context);
396-
return;
397-
}
398-
399-
// Cannot extend a bound generic type.
400-
if (extendedType->isSpecialized()) {
401-
TC.diagnose(ED->getLoc(), diag::extension_specialization,
402-
extendedType->getAnyNominal()->getName())
403-
.highlight(ED->getExtendedTypeLoc().getSourceRange());
404-
ED->setInvalid();
405-
ED->getExtendedTypeLoc().setInvalidType(TC.Context);
406-
return;
407-
}
408-
409-
// Dig out the nominal type being extended.
410-
NominalTypeDecl *extendedNominal = extendedType->getAnyNominal();
411-
if (!extendedNominal) {
412-
TC.diagnose(ED->getLoc(), diag::non_nominal_extension, extendedType)
413-
.highlight(ED->getExtendedTypeLoc().getSourceRange());
414-
ED->setInvalid();
415-
ED->getExtendedTypeLoc().setInvalidType(TC.Context);
416-
return;
417-
}
418-
assert(extendedNominal && "Should have the nominal type being extended");
419-
420-
bindExtensionToNominal(ED, extendedNominal);
421-
}
422-
423349
static void bindExtensions(SourceFile &SF, TypeChecker &TC) {
424350
// Utility function to try and resolve the extended type without diagnosing.
425351
// If we succeed, we go ahead and bind the extension. Otherwise, return false.
@@ -471,10 +397,6 @@ static void bindExtensions(SourceFile &SF, TypeChecker &TC) {
471397
// typeCheckDecl().
472398
}
473399

474-
void TypeChecker::bindExtension(ExtensionDecl *ext) {
475-
::bindExtensionDecl(ext, *this);
476-
}
477-
478400
static void typeCheckFunctionsAndExternalDecls(SourceFile &SF, TypeChecker &TC) {
479401
unsigned currentFunctionIdx = 0;
480402
unsigned currentExternalDef = TC.Context.LastCheckedExternalDefinition;

lib/Sema/TypeChecker.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,8 +1106,6 @@ class TypeChecker final : public LazyResolver {
11061106
validateDecl(proto);
11071107
}
11081108

1109-
void bindExtension(ExtensionDecl *ext);
1110-
11111109
virtual void resolveExtension(ExtensionDecl *ext) override {
11121110
validateExtension(ext);
11131111
}

0 commit comments

Comments
 (0)