Skip to content

Commit 011e306

Browse files
committed
Sema: Add -enable-experimental-nested-generic-types frontend flag
Also, split up test/decl/nested.swift into several files.
1 parent 7b226ad commit 011e306

File tree

11 files changed

+374
-234
lines changed

11 files changed

+374
-234
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ namespace swift {
140140
/// \brief Enable experimental property behavior feature.
141141
bool EnableExperimentalPropertyBehaviors = false;
142142

143+
/// \brief Enable experimental nested generic types feature.
144+
bool EnableExperimentalNestedGenericTypes = false;
145+
143146
/// Should we check the target OSs of serialized modules to see that they're
144147
/// new enough?
145148
bool EnableTargetOSChecking = true;

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ def enable_experimental_property_behaviors :
223223
Flag<["-"], "enable-experimental-property-behaviors">,
224224
HelpText<"Enable experimental property behaviors">;
225225

226+
def enable_experimental_nested_generic_types :
227+
Flag<["-"], "enable-experimental-nested-generic-types">,
228+
HelpText<"Enable experimental support for nested generic types">;
229+
226230
def disable_availability_checking : Flag<["-"],
227231
"disable-availability-checking">,
228232
HelpText<"Disable checking for potentially unavailable APIs">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
740740
Opts.EnableExperimentalPropertyBehaviors |=
741741
Args.hasArg(OPT_enable_experimental_property_behaviors);
742742

743+
Opts.EnableExperimentalNestedGenericTypes |=
744+
Args.hasArg(OPT_enable_experimental_nested_generic_types);
745+
743746
Opts.DisableAvailabilityChecking |=
744747
Args.hasArg(OPT_disable_availability_checking);
745748

lib/Sema/TypeCheckDecl.cpp

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3546,19 +3546,21 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
35463546
// We don't support nested types in generics yet.
35473547
if (NTD->isGenericContext()) {
35483548
auto DC = NTD->getDeclContext();
3549-
if (DC->isTypeContext()) {
3550-
if (NTD->getGenericParams())
3551-
TC.diagnose(NTD->getLoc(), diag::unsupported_generic_nested_in_type,
3552-
NTD->getName(),
3553-
DC->getDeclaredTypeOfContext());
3554-
else
3555-
TC.diagnose(NTD->getLoc(),
3556-
diag::unsupported_type_nested_in_generic_type,
3557-
NTD->getName(),
3558-
DC->getDeclaredTypeOfContext());
3559-
return true;
3549+
if (!TC.Context.LangOpts.EnableExperimentalNestedGenericTypes) {
3550+
if (DC->isTypeContext()) {
3551+
if (NTD->getGenericParams())
3552+
TC.diagnose(NTD->getLoc(), diag::unsupported_generic_nested_in_type,
3553+
NTD->getName(),
3554+
DC->getDeclaredTypeOfContext());
3555+
else
3556+
TC.diagnose(NTD->getLoc(),
3557+
diag::unsupported_type_nested_in_generic_type,
3558+
NTD->getName(),
3559+
DC->getDeclaredTypeOfContext());
3560+
return true;
3561+
}
35603562
}
3561-
3563+
35623564
if (DC->isLocalContext() && DC->isGenericContext()) {
35633565
// A local generic context is a generic function.
35643566
if (auto AFD = dyn_cast<AbstractFunctionDecl>(DC)) {

test/decl/class/classes.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,3 @@ class HDerived : H {
8585
override func f(_ x: Int) { }
8686
override class func f(_ x: Int) { }
8787
}
88-
89-
// Generic class locally defined in non-generic function (rdar://problem/20116710)
90-
func f3() {
91-
class B<T> {}
92-
}

test/decl/nested.swift

Lines changed: 0 additions & 217 deletions
This file was deleted.

test/decl/nested/protocol.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %target-parse-verify-swift -parse-as-library
2+
3+
// Protocols cannot be nested inside other types, and types cannot
4+
// be nested inside protocols
5+
6+
struct OuterGeneric<D> {
7+
protocol InnerProtocol { // expected-error{{declaration is only valid at file scope}}
8+
associatedtype Rooster
9+
func flip(_ r: Rooster)
10+
func flop(_ t: D)
11+
}
12+
}
13+
14+
class OuterGenericClass<T> {
15+
protocol InnerProtocol { // expected-error{{declaration is only valid at file scope}}
16+
associatedtype Rooster
17+
func flip(_ r: Rooster)
18+
func flop(_ t: T)
19+
}
20+
}
21+
22+
protocol OuterProtocol {
23+
associatedtype Hen
24+
protocol InnerProtocol { // expected-error{{type not allowed here}}
25+
associatedtype Rooster
26+
func flip(_ r: Rooster)
27+
func flop(_ h: Hen)
28+
}
29+
}
30+
31+
protocol Racoon {
32+
associatedtype Stripes
33+
class Claw<T> { // expected-error{{type not allowed here}}
34+
func mangle(_ s: Stripes) {}
35+
}
36+
struct Fang<T> { // expected-error{{type not allowed here}}
37+
func gnaw(_ s: Stripes) {}
38+
}
39+
}
40+
41+
enum OuterEnum {
42+
protocol C {} // expected-error{{declaration is only valid at file scope}}
43+
case C(C)
44+
}
45+

test/decl/nested/reserved_name.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-parse-verify-swift
2+
3+
struct S1 {
4+
// expected-error @+4 {{type member may not be named 'Type', since it would conflict with the 'foo.Type' expression}}
5+
// expected-error @+3 {{type member may not be named 'Type', since it would conflict with the 'foo.Type' expression}}
6+
// expected-note @+2 {{if this name is unavoidable, use backticks to escape it}} {{8-12=`Type`}}
7+
// expected-note @+1 {{if this name is unavoidable, use backticks to escape it}} {{8-12=`Type`}}
8+
enum Type {
9+
case A
10+
}
11+
}
12+
13+
struct S2 {
14+
enum `Type` {
15+
case A
16+
}
17+
}
18+
19+
let s1: S1.Type = .A // expected-error{{type of expression is ambiguous without more context}}
20+
let s2: S2.`Type` = .A // no-error

0 commit comments

Comments
 (0)