Skip to content

Commit 5857334

Browse files
committed
Sema: validateExtension() builds a generic signature even if the extension is invalid
Otherwise, we crash later in code that assumes the presence of a generic parameter list implies the presence of a generic signature (and vice versa). Fixes <rdar://problem/46604393>.
1 parent 1cd8613 commit 5857334

File tree

2 files changed

+53
-42
lines changed

2 files changed

+53
-42
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4481,6 +4481,9 @@ static Type formExtensionInterfaceType(TypeChecker &tc, ExtensionDecl *ext,
44814481
Type type,
44824482
GenericParamList *genericParams,
44834483
bool &mustInferRequirements) {
4484+
if (type->is<ErrorType>())
4485+
return type;
4486+
44844487
// Find the nominal type declaration and its parent type.
44854488
Type parentType;
44864489
GenericTypeDecl *genericDecl;
@@ -4602,30 +4605,22 @@ checkExtensionGenericParams(TypeChecker &tc, ExtensionDecl *ext, Type type,
46024605
return { env, extInterfaceType };
46034606
}
46044607

4605-
void TypeChecker::validateExtension(ExtensionDecl *ext) {
4606-
// If we're currently validating, or have already validated this extension,
4607-
// there's nothing more to do now.
4608-
if (ext->hasValidationStarted())
4609-
return;
4610-
4611-
DeclValidationRAII IBV(ext);
4612-
4613-
auto dc = ext->getDeclContext();
4614-
4608+
static void validateExtendedType(ExtensionDecl *ext, TypeChecker &tc) {
46154609
// If we didn't parse a type, fill in an error type and bail out.
46164610
if (!ext->getExtendedTypeLoc().getTypeRepr()) {
46174611
ext->setInvalid();
4618-
ext->getExtendedTypeLoc().setInvalidType(Context);
4612+
ext->getExtendedTypeLoc().setInvalidType(tc.Context);
46194613
return;
46204614
}
46214615

46224616
// Validate the extended type.
46234617
TypeResolutionOptions options(TypeResolverContext::ExtensionBinding);
46244618
options |= TypeResolutionFlags::AllowUnboundGenerics;
4625-
if (validateType(ext->getExtendedTypeLoc(),
4626-
TypeResolution::forInterface(dc), options)) {
4619+
if (tc.validateType(ext->getExtendedTypeLoc(),
4620+
TypeResolution::forInterface(ext->getDeclContext()),
4621+
options)) {
46274622
ext->setInvalid();
4628-
ext->getExtendedTypeLoc().setInvalidType(Context);
4623+
ext->getExtendedTypeLoc().setInvalidType(tc.Context);
46294624
return;
46304625
}
46314626

@@ -4646,38 +4641,47 @@ void TypeChecker::validateExtension(ExtensionDecl *ext) {
46464641

46474642
// Cannot extend a metatype.
46484643
if (extendedType->is<AnyMetatypeType>()) {
4649-
diagnose(ext->getLoc(), diag::extension_metatype, extendedType)
4644+
tc.diagnose(ext->getLoc(), diag::extension_metatype, extendedType)
46504645
.highlight(ext->getExtendedTypeLoc().getSourceRange());
46514646
ext->setInvalid();
4652-
ext->getExtendedTypeLoc().setInvalidType(Context);
4647+
ext->getExtendedTypeLoc().setInvalidType(tc.Context);
46534648
return;
46544649
}
46554650

46564651
// Cannot extend a bound generic type.
46574652
if (extendedType->isSpecialized()) {
4658-
diagnose(ext->getLoc(), diag::extension_specialization,
4653+
tc.diagnose(ext->getLoc(), diag::extension_specialization,
46594654
extendedType->getAnyNominal()->getName())
46604655
.highlight(ext->getExtendedTypeLoc().getSourceRange());
46614656
ext->setInvalid();
4662-
ext->getExtendedTypeLoc().setInvalidType(Context);
4657+
ext->getExtendedTypeLoc().setInvalidType(tc.Context);
46634658
return;
46644659
}
46654660

4666-
auto *nominal = extendedType->getAnyNominal();
4667-
46684661
// Cannot extend function types, tuple types, etc.
4669-
if (nominal == nullptr) {
4670-
diagnose(ext->getLoc(), diag::non_nominal_extension, extendedType)
4662+
if (!extendedType->getAnyNominal()) {
4663+
tc.diagnose(ext->getLoc(), diag::non_nominal_extension, extendedType)
46714664
.highlight(ext->getExtendedTypeLoc().getSourceRange());
46724665
ext->setInvalid();
4673-
ext->getExtendedTypeLoc().setInvalidType(Context);
4666+
ext->getExtendedTypeLoc().setInvalidType(tc.Context);
46744667
return;
46754668
}
4669+
}
4670+
4671+
void TypeChecker::validateExtension(ExtensionDecl *ext) {
4672+
// If we're currently validating, or have already validated this extension,
4673+
// there's nothing more to do now.
4674+
if (ext->hasValidationStarted())
4675+
return;
4676+
4677+
DeclValidationRAII IBV(ext);
4678+
4679+
validateExtendedType(ext, *this);
46764680

46774681
// Extensions nested inside other declarations are invalid and we
46784682
// do not bind them.
4679-
if (!isa<SourceFile>(dc))
4680-
return;
4683+
if (!isa<SourceFile>(ext->getDeclContext()))
4684+
return;
46814685

46824686
// If this is not bound to any decls at this point, this extension is in
46834687
// inactive coditional compilation block. It's not safe to typecheck this
@@ -4686,26 +4690,25 @@ void TypeChecker::validateExtension(ExtensionDecl *ext) {
46864690
if (!ext->alreadyBoundToNominal())
46874691
return;
46884692

4689-
// Validate the nominal type declaration being extended.
4690-
validateDecl(nominal);
4693+
if (auto *nominal = ext->getExtendedNominal()) {
4694+
// Validate the nominal type declaration being extended.
4695+
validateDecl(nominal);
46914696

4692-
if (nominal->getGenericParamsOfContext()) {
4693-
auto genericParams = ext->getGenericParams();
4694-
assert(genericParams && "bindExtensionDecl didn't set generic params?");
4697+
if (nominal->getGenericParamsOfContext()) {
4698+
auto genericParams = ext->getGenericParams();
4699+
assert(genericParams && "bindExtensionDecl didn't set generic params?");
46954700

4696-
// Check generic parameters.
4697-
GenericEnvironment *env;
4698-
std::tie(env, extendedType) = checkExtensionGenericParams(
4699-
*this, ext, ext->getExtendedType(),
4700-
genericParams);
4701+
// Check generic parameters.
4702+
GenericEnvironment *env;
4703+
Type extendedType = ext->getExtendedType();
4704+
std::tie(env, extendedType) = checkExtensionGenericParams(
4705+
*this, ext, extendedType,
4706+
genericParams);
47014707

4702-
ext->getExtendedTypeLoc().setType(extendedType);
4703-
ext->setGenericEnvironment(env);
4704-
return;
4708+
ext->getExtendedTypeLoc().setType(extendedType);
4709+
ext->setGenericEnvironment(env);
4710+
}
47054711
}
4706-
4707-
assert(extendedType->is<NominalType>());
4708-
assert(!nominal->isGenericContext());
47094712
}
47104713

47114714
/// Build a default initializer string for the given pattern.

test/decl/ext/generic.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,15 @@ extension Double : P2 {
1818
typealias AssocType = Double
1919
}
2020

21-
extension X<Int, Double, String> { } // expected-error{{constrained extension must be declared on the unspecialized generic type 'X' with constraints specified by a 'where' clause}}
21+
extension X<Int, Double, String> {
22+
// expected-error@-1{{constrained extension must be declared on the unspecialized generic type 'X' with constraints specified by a 'where' clause}}
23+
let x = 0
24+
// expected-error@-1 {{extensions must not contain stored properties}}
25+
static let x = 0
26+
// expected-error@-1 {{static stored properties not supported in generic types}}
27+
func f() -> Int {}
28+
class C<T> {}
29+
}
2230

2331
typealias GGG = X<Int, Double, String>
2432

0 commit comments

Comments
 (0)