Skip to content

Commit 8ec8902

Browse files
committed
[Sema] Reject tuple extensions early when feature is disabled
Tuple extensions are still an experimental feature, but we have a number of crashers in the repo for them because we still use their type-checker machinery even when disabled. Change the logic here such that we reject them early in extension binding when the feature is disabled. This will ensure we address the crashers before productizing.
1 parent d06d126 commit 8ec8902

16 files changed

+44
-17
lines changed

lib/AST/NameLookup.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3630,7 +3630,17 @@ NominalTypeDecl *ExtensionDecl::computeExtendedNominal(
36303630
if (nominalTypes.empty())
36313631
return nullptr;
36323632

3633-
return nominalTypes[0];
3633+
auto *result = nominalTypes[0];
3634+
3635+
// Tuple extensions are experimental, if the feature isn't enabled let's not
3636+
// bind this extension at all. This fixes a bunch of crashers that we don't
3637+
// yet properly handle with the feature enabled.
3638+
if (isa<BuiltinTupleDecl>(result) &&
3639+
!ctx.LangOpts.hasFeature(Feature::TupleConformances)) {
3640+
return nullptr;
3641+
}
3642+
3643+
return result;
36343644
}
36353645

36363646
NominalTypeDecl *

lib/Sema/TypeCheckDecl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3089,6 +3089,13 @@ ExtendedTypeRequest::evaluate(Evaluator &eval, ExtensionDecl *ext) const {
30893089
return error();
30903090
}
30913091

3092+
// Tuple extensions are experimental.
3093+
if (extendedType->is<TupleType>() &&
3094+
!ctx.LangOpts.hasFeature(Feature::TupleConformances)) {
3095+
diags.diagnose(ext, diag::experimental_tuple_extension);
3096+
return error();
3097+
}
3098+
30923099
// Cannot extend function types, metatypes, existentials, etc.
30933100
if (!extendedType->is<TupleType>() &&
30943101
!extendedType->getAnyNominal() &&

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3652,10 +3652,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
36523652
return;
36533653

36543654
auto &ctx = ED->getASTContext();
3655-
3656-
if (!ctx.LangOpts.hasFeature(Feature::TupleConformances)) {
3657-
ED->diagnose(diag::experimental_tuple_extension);
3658-
}
3655+
ASSERT(ctx.LangOpts.hasFeature(Feature::TupleConformances) &&
3656+
"Extension binding should not have permitted this");
36593657

36603658
if (!isValidExtendedTypeForTupleExtension(ED)) {
36613659
ED->diagnose(diag::tuple_extension_wrong_type,

validation-test/IDE/crashers/38a36bbe0fc496da.swift renamed to validation-test/IDE/crashers_fixed/38a36bbe0fc496da.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// {"kind":"complete","original":"61e9155a","signature":"swift::ide::CodeCompletionResultBuilder::takeResult()"}
2-
// RUN: not --crash %target-swift-ide-test -code-completion -batch-code-completion -skip-filecheck -code-completion-diagnostics -source-filename %s
2+
// RUN: %target-swift-ide-test -code-completion -batch-code-completion -skip-filecheck -code-completion-diagnostics -source-filename %s
33
extension ()
44
where
55
#^^# == <#type#>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// {"kind":"typecheck","original":"679d3d53","signature":"(anonymous namespace)::PrintAST::visit(swift::Decl*)"}
2-
// RUN: not --crash %target-swift-frontend -typecheck %s
2+
// RUN: not %target-swift-frontend -typecheck %s
33
extension () {
44
class let a
55
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
// {"kind":"typecheck","signature":"swift::ConditionalRequirementsRequest::evaluate(swift::Evaluator&, swift::NormalProtocolConformance*) const","signatureAssert":"Assertion failed: (typeSig.getCanonicalSignature().getGenericParams() == extensionSig.getCanonicalSignature().getGenericParams()), function evaluate"}
2-
// RUN: not --crash %target-swift-frontend -typecheck %s
2+
// RUN: not %target-swift-frontend -typecheck %s
33
protocol a typealias b<c> = () extension b : a
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
// {"kind":"typecheck","signature":"swift::NominalType::get(swift::NominalTypeDecl*, swift::Type, swift::ASTContext const&)","signatureAssert":"Assertion failed: ((!Parent || Parent->is<NominalType>() || Parent->is<BoundGenericType>() || Parent->is<UnboundGenericType>()) && \"parent must be a nominal type\"), function get"}
2-
// RUN: not --crash %target-swift-frontend -typecheck %s
2+
// RUN: not %target-swift-frontend -typecheck %s
33
extension() {
44
struct a extension a
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// {"kind":"typecheck","original":"2e2249a5","signature":"swift::TypeBase::computeCanonicalType()","signatureAssert":"Assertion failed: (Result->isCanonical()), function computeCanonicalType"}
2-
// RUN: not --crash %target-swift-frontend -typecheck %s
2+
// RUN: not %target-swift-frontend -typecheck %s
33
typealias a<b> = (
44
>extension a where b == {
55
c
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
// {"kind":"typecheck","signature":"(anonymous namespace)::DeclChecker::visit(swift::Decl*)","signatureAssert":"Assertion failed: (false && \"Huh?\"), function isValidExtendedTypeForTupleExtension"}
2-
// RUN: not --crash %target-swift-frontend -typecheck %s
2+
// RUN: not %target-swift-frontend -typecheck %s
33
extension repeat (
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// {"kind":"typecheck","original":"71a26232","signature":"swift::Decl::getDescriptiveKind() const"}
2+
// RUN: not %target-swift-frontend -typecheck %s
3+
typealias a = ()
4+
extension a {
5+
func
6+
< (b: Self, c: Self)
7+
{
8+
for (d, e) in repeat (each b each c) {
9+
d < &e
10+
}
11+
}
12+
}

0 commit comments

Comments
 (0)