Skip to content

Commit fd06bd8

Browse files
committed
AST: Allow the extended type of an extension to refer to be a tuple type
Either directly, or via a type alias.
1 parent 85016b5 commit fd06bd8

File tree

7 files changed

+77
-46
lines changed

7 files changed

+77
-46
lines changed

lib/AST/NameLookup.cpp

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,12 +1071,19 @@ directReferencesForTypeRepr(Evaluator &evaluator, ASTContext &ctx,
10711071
/// the given type.
10721072
static DirectlyReferencedTypeDecls directReferencesForType(Type type);
10731073

1074+
enum class ResolveToNominalFlags : uint8_t {
1075+
AllowTupleType = 0x1
1076+
};
1077+
1078+
using ResolveToNominalOptions = OptionSet<ResolveToNominalFlags>;
1079+
10741080
/// Given a set of type declarations, find all of the nominal type declarations
10751081
/// that they reference, looking through typealiases as appropriate.
10761082
static TinyPtrVector<NominalTypeDecl *>
10771083
resolveTypeDeclsToNominal(Evaluator &evaluator,
10781084
ASTContext &ctx,
10791085
ArrayRef<TypeDecl *> typeDecls,
1086+
ResolveToNominalOptions options,
10801087
SmallVectorImpl<ModuleDecl *> &modulesFound,
10811088
bool &anyObject);
10821089

@@ -1130,6 +1137,7 @@ SelfBounds SelfBoundsFromWhereClauseRequest::evaluate(
11301137

11311138
SmallVector<ModuleDecl *, 2> modulesFound;
11321139
auto rhsNominals = resolveTypeDeclsToNominal(evaluator, ctx, rhsDecls,
1140+
ResolveToNominalOptions(),
11331141
modulesFound,
11341142
result.anyObject);
11351143
result.decls.insert(result.decls.end(),
@@ -1168,7 +1176,8 @@ SelfBounds SelfBoundsFromGenericSignatureRequest::evaluate(
11681176
auto rhsDecls = directReferencesForType(req.getSecondType());
11691177
SmallVector<ModuleDecl *, 2> modulesFound;
11701178
auto rhsNominals = resolveTypeDeclsToNominal(
1171-
evaluator, ctx, rhsDecls, modulesFound, result.anyObject);
1179+
evaluator, ctx, rhsDecls, ResolveToNominalOptions(),
1180+
modulesFound, result.anyObject);
11721181
result.decls.insert(result.decls.end(), rhsNominals.begin(),
11731182
rhsNominals.end());
11741183
}
@@ -2651,6 +2660,7 @@ static TinyPtrVector<NominalTypeDecl *>
26512660
resolveTypeDeclsToNominal(Evaluator &evaluator,
26522661
ASTContext &ctx,
26532662
ArrayRef<TypeDecl *> typeDecls,
2663+
ResolveToNominalOptions options,
26542664
SmallVectorImpl<ModuleDecl *> &modulesFound,
26552665
bool &anyObject,
26562666
llvm::SmallPtrSetImpl<TypeAliasDecl *> &typealiases) {
@@ -2664,6 +2674,14 @@ resolveTypeDeclsToNominal(Evaluator &evaluator,
26642674
for (auto typeDecl : typeDecls) {
26652675
// Nominal type declarations get copied directly.
26662676
if (auto nominalDecl = dyn_cast<NominalTypeDecl>(typeDecl)) {
2677+
// ... unless it's the special Builtin.TheTupleType that we return
2678+
// when resolving a TupleTypeRepr, and the caller isn't asking for
2679+
// that.
2680+
if (!options.contains(ResolveToNominalFlags::AllowTupleType) &&
2681+
isa<BuiltinTupleDecl>(nominalDecl)) {
2682+
continue;
2683+
}
2684+
26672685
addNominalDecl(nominalDecl);
26682686
continue;
26692687
}
@@ -2680,7 +2698,7 @@ resolveTypeDeclsToNominal(Evaluator &evaluator,
26802698

26812699
auto underlyingNominalReferences
26822700
= resolveTypeDeclsToNominal(evaluator, ctx, underlyingTypeReferences,
2683-
modulesFound, anyObject, typealiases);
2701+
options, modulesFound, anyObject, typealiases);
26842702
std::for_each(underlyingNominalReferences.begin(),
26852703
underlyingNominalReferences.end(),
26862704
addNominalDecl);
@@ -2731,11 +2749,12 @@ static TinyPtrVector<NominalTypeDecl *>
27312749
resolveTypeDeclsToNominal(Evaluator &evaluator,
27322750
ASTContext &ctx,
27332751
ArrayRef<TypeDecl *> typeDecls,
2752+
ResolveToNominalOptions options,
27342753
SmallVectorImpl<ModuleDecl *> &modulesFound,
27352754
bool &anyObject) {
27362755
llvm::SmallPtrSet<TypeAliasDecl *, 4> typealiases;
2737-
return resolveTypeDeclsToNominal(evaluator, ctx, typeDecls, modulesFound,
2738-
anyObject, typealiases);
2756+
return resolveTypeDeclsToNominal(evaluator, ctx, typeDecls, options,
2757+
modulesFound, anyObject, typealiases);
27392758
}
27402759

27412760
/// Perform unqualified name lookup for types at the given location.
@@ -2839,8 +2858,9 @@ directReferencesForQualifiedTypeLookup(Evaluator &evaluator,
28392858
SmallVector<ModuleDecl *, 2> moduleDecls;
28402859
bool anyObject = false;
28412860
auto nominalTypeDecls =
2842-
resolveTypeDeclsToNominal(ctx.evaluator, ctx, baseTypes, moduleDecls,
2843-
anyObject);
2861+
resolveTypeDeclsToNominal(ctx.evaluator, ctx, baseTypes,
2862+
ResolveToNominalOptions(),
2863+
moduleDecls, anyObject);
28442864

28452865
dc->lookupQualified(nominalTypeDecls, name, loc, options, members);
28462866

@@ -2956,6 +2976,8 @@ directReferencesForTypeRepr(Evaluator &evaluator,
29562976
return directReferencesForTypeRepr(evaluator, ctx,
29572977
tupleRepr->getElementType(0), dc,
29582978
allowUsableFromInline);
2979+
} else {
2980+
return { 1, ctx.getBuiltinTupleDecl() };
29592981
}
29602982
return { };
29612983
}
@@ -3019,6 +3041,9 @@ static DirectlyReferencedTypeDecls directReferencesForType(Type type) {
30193041
if (auto genericDecl = type->getAnyGeneric())
30203042
return { 1, genericDecl };
30213043

3044+
if (dyn_cast<TupleType>(type.getPointer()))
3045+
return { 1, type->getASTContext().getBuiltinTupleDecl() };
3046+
30223047
if (type->isExistentialType()) {
30233048
DirectlyReferencedTypeDecls result;
30243049
const auto &layout = type->getExistentialLayout();
@@ -3122,7 +3147,8 @@ SuperclassDeclRequest::evaluate(Evaluator &evaluator,
31223147
bool anyObject = false;
31233148
auto inheritedNominalTypes
31243149
= resolveTypeDeclsToNominal(evaluator, Ctx,
3125-
inheritedTypes, modulesFound, anyObject);
3150+
inheritedTypes, ResolveToNominalOptions(),
3151+
modulesFound, anyObject);
31263152

31273153
// Look for a class declaration.
31283154
ClassDecl *superclass = nullptr;
@@ -3191,9 +3217,10 @@ NominalTypeDecl *
31913217
ExtendedNominalRequest::evaluate(Evaluator &evaluator,
31923218
ExtensionDecl *ext) const {
31933219
auto typeRepr = ext->getExtendedTypeRepr();
3194-
if (!typeRepr)
3220+
if (!typeRepr) {
31953221
// We must've seen 'extension { ... }' during parsing.
31963222
return nullptr;
3223+
}
31973224

31983225
ASTContext &ctx = ext->getASTContext();
31993226
DirectlyReferencedTypeDecls referenced =
@@ -3204,8 +3231,9 @@ ExtendedNominalRequest::evaluate(Evaluator &evaluator,
32043231
SmallVector<ModuleDecl *, 2> modulesFound;
32053232
bool anyObject = false;
32063233
auto nominalTypes
3207-
= resolveTypeDeclsToNominal(evaluator, ctx, referenced, modulesFound,
3208-
anyObject);
3234+
= resolveTypeDeclsToNominal(evaluator, ctx, referenced,
3235+
ResolveToNominalFlags::AllowTupleType,
3236+
modulesFound, anyObject);
32093237

32103238
// If there is more than 1 element, we will emit a warning or an error
32113239
// elsewhere, so don't handle that case here.
@@ -3518,6 +3546,7 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator,
35183546
SmallVector<ModuleDecl *, 2> modulesFound;
35193547
bool anyObject = false;
35203548
auto nominals = resolveTypeDeclsToNominal(evaluator, ctx, decls,
3549+
ResolveToNominalOptions(),
35213550
modulesFound, anyObject);
35223551
if (nominals.size() == 1 && !isa<ProtocolDecl>(nominals.front()))
35233552
return nominals.front();
@@ -3535,6 +3564,7 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator,
35353564
identTypeRepr->getNameRef(), identTypeRepr->getLoc(), dc,
35363565
LookupOuterResults::Included);
35373566
nominals = resolveTypeDeclsToNominal(evaluator, ctx, decls,
3567+
ResolveToNominalOptions(),
35383568
modulesFound, anyObject);
35393569
if (nominals.size() == 1 && !isa<ProtocolDecl>(nominals.front())) {
35403570
auto nominal = nominals.front();
@@ -3584,8 +3614,9 @@ void swift::getDirectlyInheritedNominalTypeDecls(
35843614
// Resolve those type declarations to nominal type declarations.
35853615
SmallVector<ModuleDecl *, 2> modulesFound;
35863616
auto nominalTypes
3587-
= resolveTypeDeclsToNominal(ctx.evaluator, ctx, referenced, modulesFound,
3588-
anyObject);
3617+
= resolveTypeDeclsToNominal(ctx.evaluator, ctx, referenced,
3618+
ResolveToNominalOptions(),
3619+
modulesFound, anyObject);
35893620

35903621
// Dig out the source location
35913622
// FIXME: This is a hack. We need cooperation from
@@ -3772,8 +3803,9 @@ ProtocolDecl *ImplementsAttrProtocolRequest::evaluate(
37723803
SmallVector<ModuleDecl *, 2> modulesFound;
37733804
bool anyObject = false;
37743805
auto nominalTypes
3775-
= resolveTypeDeclsToNominal(evaluator, ctx, referenced, modulesFound,
3776-
anyObject);
3806+
= resolveTypeDeclsToNominal(evaluator, ctx, referenced,
3807+
ResolveToNominalOptions(),
3808+
modulesFound, anyObject);
37773809

37783810
if (nominalTypes.empty())
37793811
return nullptr;

test/CAS/educational-notes.swift

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ let x = 1 +
1313
// NO-COLOR-NOT: {{-+$}}
1414

1515
// A diagnostic with an educational note using supported markdown features
16-
extension (Int, Int) {}
17-
// CHECK:{{.*}}[0merror: non-nominal type '(Int, Int)' cannot be extended
18-
// CHECK-NEXT:extension (Int, Int) {}
19-
// CHECK-NEXT:^ ~~~~~~~~~~
16+
typealias Crap = () -> ()
17+
extension Crap {}
18+
// CHECK:{{.*}}[0merror: non-nominal type 'Crap' (aka '() -> ()') cannot be extended
19+
// CHECK-NEXT:extension Crap {}
20+
// CHECK-NEXT:^ ~~~~
2021
// CHECK-NEXT:Nominal Types
2122
// CHECK-NEXT:--------------
2223
// CHECK-EMPTY:
@@ -42,9 +43,9 @@ extension (Int, Int) {}
4243
// CHECK-NEXT:Header 1
4344
// CHECK-NEXT:Header 3
4445

45-
// NO-COLOR:{{.*}}error: non-nominal type '(Int, Int)' cannot be extended
46-
// NO-COLOR-NEXT:extension (Int, Int) {}
47-
// NO-COLOR-NEXT:^ ~~~~~~~~~~
46+
// NO-COLOR:{{.*}}error: non-nominal type 'Crap' (aka '() -> ()') cannot be extended
47+
// NO-COLOR-NEXT:extension Crap {}
48+
// NO-COLOR-NEXT:^ ~~~~
4849
// NO-COLOR-NEXT:Nominal Types
4950
// NO-COLOR-NEXT:--------------
5051
// NO-COLOR-EMPTY:
@@ -72,15 +73,15 @@ extension (Int, Int) {}
7273

7374
// CHECK-DESCRIPTIVE: educational-notes.swift
7475
// CHECK-DESCRIPTIVE-NEXT: | // A diagnostic with an educational note
75-
// CHECK-DESCRIPTIVE-NEXT: | extension (Int, Int) {}
76+
// CHECK-DESCRIPTIVE-NEXT: | extension Crap {}
7677
// CHECK-DESCRIPTIVE-NEXT: | ^ error: expected expression after operator
7778
// CHECK-DESCRIPTIVE-NEXT: |
7879

7980
// CHECK-DESCRIPTIVE: educational-notes.swift
8081
// CHECK-DESCRIPTIVE-NEXT: | // A diagnostic with an educational note
81-
// CHECK-DESCRIPTIVE-NEXT: | extension (Int, Int) {}
82-
// CHECK-DESCRIPTIVE-NEXT: | ~~~~~~~~~~
83-
// CHECK-DESCRIPTIVE-NEXT: | ^ error: non-nominal type '(Int, Int)' cannot be extended
82+
// CHECK-DESCRIPTIVE-NEXT: | extension Crap {}
83+
// CHECK-DESCRIPTIVE-NEXT: | ~~~~
84+
// CHECK-DESCRIPTIVE-NEXT: | ^ error: non-nominal type 'Crap' (aka '() -> ()') cannot be extended
8485
// CHECK-DESCRIPTIVE-NEXT: |
8586
// CHECK-DESCRIPTIVE-NEXT: Nominal Types
8687
// CHECK-DESCRIPTIVE-NEXT: -------------

test/SourceKit/Sema/educational_note_diags.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
extension (Int, Int) {}
1+
typealias Crap = () -> ()
2+
extension Crap {}
23

34
// RUN: %sourcekitd-test -req=sema %s -- %s | %FileCheck %s -check-prefix=NO_OVERRIDE
45

test/attr/ApplicationMain/attr_main_tuple_extension.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %target-swift-frontend -typecheck -parse-as-library -verify %s
22

33
@main
4-
extension (Int, String) { // expected-error {{non-nominal type '(Int, String)' cannot be extended}}
4+
extension Int.Type { // expected-error {{cannot extend a metatype 'Int.Type'}}
55
static func main() {
66
}
77
}

test/decl/ext/extensions.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,6 @@ protocol P1 {}
8787

8888
protocol P2 {}
8989

90-
extension () {} // expected-error {{non-nominal type '()' cannot be extended}} {{educational-notes=nominal-types}}
91-
92-
typealias TupleAlias = (x: Int, y: Int)
93-
extension TupleAlias {} // expected-error{{non-nominal type 'TupleAlias' (aka '(x: Int, y: Int)') cannot be extended}} {{educational-notes=nominal-types}}
94-
9590
// Test property accessors in extended types
9691
class C {}
9792
extension C {

test/diagnostics/educational-notes.swift

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ let x = 1 +
1010
// NO-COLOR-NOT: {{-+$}}
1111

1212
// A diagnostic with an educational note using supported markdown features
13-
extension (Int, Int) {}
14-
// CHECK:{{.*}}[0merror: non-nominal type '(Int, Int)' cannot be extended
15-
// CHECK-NEXT:extension (Int, Int) {}
16-
// CHECK-NEXT:^ ~~~~~~~~~~
13+
typealias Crap = () -> ()
14+
extension Crap {}
15+
// CHECK:{{.*}}[0merror: non-nominal type 'Crap' (aka '() -> ()') cannot be extended
16+
// CHECK-NEXT:extension Crap {}
17+
// CHECK-NEXT:^ ~~~~
1718
// CHECK-NEXT:Nominal Types
1819
// CHECK-NEXT:--------------
1920
// CHECK-EMPTY:
@@ -39,9 +40,9 @@ extension (Int, Int) {}
3940
// CHECK-NEXT:Header 1
4041
// CHECK-NEXT:Header 3
4142

42-
// NO-COLOR:{{.*}}error: non-nominal type '(Int, Int)' cannot be extended
43-
// NO-COLOR-NEXT:extension (Int, Int) {}
44-
// NO-COLOR-NEXT:^ ~~~~~~~~~~
43+
// NO-COLOR:{{.*}}error: non-nominal type 'Crap' (aka '() -> ()') cannot be extended
44+
// NO-COLOR-NEXT:extension Crap {}
45+
// NO-COLOR-NEXT:^ ~~~~
4546
// NO-COLOR-NEXT:Nominal Types
4647
// NO-COLOR-NEXT:--------------
4748
// NO-COLOR-EMPTY:
@@ -69,15 +70,15 @@ extension (Int, Int) {}
6970

7071
// CHECK-DESCRIPTIVE: educational-notes.swift
7172
// CHECK-DESCRIPTIVE-NEXT: | // A diagnostic with an educational note
72-
// CHECK-DESCRIPTIVE-NEXT: | extension (Int, Int) {}
73+
// CHECK-DESCRIPTIVE-NEXT: | extension Crap {}
7374
// CHECK-DESCRIPTIVE-NEXT: | ^ error: expected expression after operator
7475
// CHECK-DESCRIPTIVE-NEXT: |
7576

7677
// CHECK-DESCRIPTIVE: educational-notes.swift
7778
// CHECK-DESCRIPTIVE-NEXT: | // A diagnostic with an educational note
78-
// CHECK-DESCRIPTIVE-NEXT: | extension (Int, Int) {}
79-
// CHECK-DESCRIPTIVE-NEXT: | ~~~~~~~~~~
80-
// CHECK-DESCRIPTIVE-NEXT: | ^ error: non-nominal type '(Int, Int)' cannot be extended
79+
// CHECK-DESCRIPTIVE-NEXT: | extension Crap {}
80+
// CHECK-DESCRIPTIVE-NEXT: | ~~~~
81+
// CHECK-DESCRIPTIVE-NEXT: | ^ error: non-nominal type 'Crap' (aka '() -> ()') cannot be extended
8182
// CHECK-DESCRIPTIVE-NEXT: |
8283
// CHECK-DESCRIPTIVE-NEXT: Nominal Types
8384
// CHECK-DESCRIPTIVE-NEXT: -------------

test/diagnostics/verifier.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,14 @@ func b() {
3333
// CHECK: unexpected warning produced: initialization of immutable value 'c' was never used
3434
// CHECK-WARNINGS-AS-ERRORS: unexpected error produced: initialization of immutable value 'c' was never used
3535

36-
extension (Int, Int) {} // expected-error {{non-nominal type '(Int, Int)' cannot be extended}} {{educational-notes=foo-bar-baz}}
36+
typealias Crap = () -> ()
37+
extension Crap {} // expected-error {{non-nominal type 'Crap' (aka '() -> ()') cannot be extended}} {{educational-notes=foo-bar-baz}}
3738
// CHECK: error: expected educational note(s) not seen; actual educational note(s): {{[{][{]}}educational-notes=nominal-types{{[}][}]}}
3839

39-
extension (Bool, Int) {} // expected-error {{non-nominal type '(Bool, Int)' cannot be extended}} {{educational-notes=nominal-types}} {{educational-notes=nominal-types}}
40+
extension Crap {} // expected-error {{non-nominal type 'Crap' (aka '() -> ()') cannot be extended}} {{educational-notes=nominal-types}} {{educational-notes=nominal-types}}
4041
// CHECK: error: each verified diagnostic may only have one {{[{][{]}}educational-notes=<#notes#>{{[}][}]}} declaration
4142

42-
extension (Bool, Bool) {} // expected-error {{non-nominal type '(Bool, Bool)' cannot be extended}} {{educational-notes=nominal-types,foo-bar-baz}}
43+
extension Crap {} // expected-error {{non-nominal type 'Crap' (aka '() -> ()') cannot be extended}} {{educational-notes=nominal-types,foo-bar-baz}}
4344
// CHECK: error: expected educational note(s) not seen; actual educational note(s): {{[{][{]}}educational-notes=nominal-types{{[}][}]}}
4445

4546
// Verify the serialized diags have the right magic at the top.

0 commit comments

Comments
 (0)