Skip to content

Commit 68bfc0d

Browse files
committed
Make NonEscapableTypes as a suppressible experimental feature
1 parent 9184923 commit 68bfc0d

File tree

6 files changed

+217
-14
lines changed

6 files changed

+217
-14
lines changed

include/swift/AST/PrintOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,9 @@ struct PrintOptions {
387387
/// Replace BitwiseCopyable with _BitwiseCopyable.
388388
bool SuppressBitwiseCopyable = false;
389389

390+
/// Suppress ~Escapable types and lifetime dependence annotations
391+
bool SuppressNonEscapableTypes = false;
392+
390393
/// List of attribute kinds that should not be printed.
391394
std::vector<AnyAttrKind> ExcludeAttrList = {
392395
DeclAttrKind::Transparent, DeclAttrKind::Effects,

include/swift/Basic/Features.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ EXPERIMENTAL_FEATURE(StructLetDestructuring, true)
358358

359359
/// Enable non-escapable type attributes and function attributes that support
360360
/// lifetime-dependent results.
361-
EXPERIMENTAL_FEATURE(NonescapableTypes, true)
361+
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(NonescapableTypes, true)
362362

363363
/// Enable the `@_staticExclusiveOnly` attribute.
364364
EXPERIMENTAL_FEATURE(StaticExclusiveOnly, true)

lib/AST/ASTPrinter.cpp

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,6 +1978,11 @@ void PrintAST::printSingleDepthOfGenericSignature(
19781978
if (dependsOnOpaque(inverse.subject))
19791979
continue;
19801980

1981+
if (inverse.getKind() == InvertibleProtocolKind::Escapable &&
1982+
Options.SuppressNonEscapableTypes) {
1983+
continue;
1984+
}
1985+
19811986
if (isFirstReq) {
19821987
if (printRequirements)
19831988
Printer << " " << tok::kw_where << " ";
@@ -3099,6 +3104,16 @@ suppressingFeatureAllowUnsafeAttribute(PrintOptions &options,
30993104
options.ExcludeAttrList.resize(originalExcludeAttrCount);
31003105
}
31013106

3107+
static void
3108+
suppressingFeatureNonescapableTypes(PrintOptions &options,
3109+
llvm::function_ref<void()> action) {
3110+
unsigned originalExcludeAttrCount = options.ExcludeAttrList.size();
3111+
options.ExcludeAttrList.push_back(DeclAttrKind::Lifetime);
3112+
llvm::SaveAndRestore<bool> scope(options.SuppressNonEscapableTypes, true);
3113+
action();
3114+
options.ExcludeAttrList.resize(originalExcludeAttrCount);
3115+
}
3116+
31023117
/// Suppress the printing of a particular feature.
31033118
static void suppressingFeature(PrintOptions &options, Feature feature,
31043119
llvm::function_ref<void()> action) {
@@ -4107,10 +4122,12 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
41074122
Printer.printDeclResultTypePre(decl, ResultTyLoc);
41084123
Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
41094124
{
4110-
if (auto *typeRepr = dyn_cast_or_null<LifetimeDependentTypeRepr>(
4111-
decl->getResultTypeRepr())) {
4112-
for (auto &dep : typeRepr->getLifetimeDependencies()) {
4113-
Printer << " " << dep.getDependsOnString() << " ";
4125+
if (!Options.SuppressNonEscapableTypes) {
4126+
if (auto *typeRepr = dyn_cast_or_null<LifetimeDependentTypeRepr>(
4127+
decl->getResultTypeRepr())) {
4128+
for (auto &dep : typeRepr->getLifetimeDependencies()) {
4129+
Printer << " " << dep.getDependsOnString() << " ";
4130+
}
41144131
}
41154132
}
41164133
}
@@ -4330,15 +4347,17 @@ void PrintAST::visitConstructorDecl(ConstructorDecl *decl) {
43304347

43314348
printGenericDeclGenericParams(decl);
43324349
printFunctionParameters(decl);
4333-
if (decl->hasLifetimeDependentReturn()) {
4334-
Printer << " -> ";
4335-
auto *typeRepr =
4336-
cast<LifetimeDependentTypeRepr>(decl->getResultTypeRepr());
4337-
for (auto &dep : typeRepr->getLifetimeDependencies()) {
4338-
Printer << dep.getDependsOnString() << " ";
4350+
if (!Options.SuppressNonEscapableTypes) {
4351+
if (decl->hasLifetimeDependentReturn()) {
4352+
Printer << " -> ";
4353+
auto *typeRepr =
4354+
cast<LifetimeDependentTypeRepr>(decl->getResultTypeRepr());
4355+
for (auto &dep : typeRepr->getLifetimeDependencies()) {
4356+
Printer << dep.getDependsOnString() << " ";
4357+
}
4358+
// TODO: Handle failable initializers with lifetime dependent returns
4359+
Printer << "Self";
43394360
}
4340-
// TODO: Handle failable initializers with lifetime dependent returns
4341-
Printer << "Self";
43424361
}
43434362
});
43444363

@@ -7796,7 +7815,28 @@ swift::getInheritedForPrinting(
77967815
}
77977816
continue;
77987817
}
7818+
7819+
// Suppress Escapable and ~Escapable.
7820+
if (options.SuppressNonEscapableTypes) {
7821+
if (auto pct = ty->getAs<ProtocolCompositionType>()) {
7822+
auto inverses = pct->getInverses();
7823+
if (inverses.contains(InvertibleProtocolKind::Escapable)) {
7824+
inverses.remove(InvertibleProtocolKind::Escapable);
7825+
ty = ProtocolCompositionType::get(decl->getASTContext(),
7826+
pct->getMembers(), inverses,
7827+
pct->hasExplicitAnyObject());
7828+
if (ty->isAny())
7829+
continue;
7830+
}
7831+
}
7832+
7833+
if (auto protoTy = ty->getAs<ProtocolType>())
7834+
if (protoTy->getDecl()->isSpecificProtocol(
7835+
KnownProtocolKind::Escapable))
7836+
continue;
7837+
}
77997838
}
7839+
78007840
if (options.SuppressConformanceSuppression &&
78017841
inherited.getEntry(i).isSuppressed()) {
78027842
continue;

lib/AST/FeatureSet.cpp

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,75 @@ UNINTERESTING_FEATURE(Embedded)
130130
UNINTERESTING_FEATURE(Volatile)
131131
UNINTERESTING_FEATURE(SuppressedAssociatedTypes)
132132
UNINTERESTING_FEATURE(StructLetDestructuring)
133-
UNINTERESTING_FEATURE(NonescapableTypes)
133+
134+
static bool usesFeatureNonescapableTypes(Decl *decl) {
135+
auto containsNonEscapable =
136+
[](SmallVectorImpl<InverseRequirement> &inverseReqs) {
137+
auto foundIt =
138+
llvm::find_if(inverseReqs, [](InverseRequirement inverseReq) {
139+
if (inverseReq.getKind() == InvertibleProtocolKind::Escapable) {
140+
return true;
141+
}
142+
return false;
143+
});
144+
return foundIt != inverseReqs.end();
145+
};
146+
147+
if (auto *valueDecl = dyn_cast<ValueDecl>(decl)) {
148+
if (isa<StructDecl, EnumDecl, ClassDecl>(decl)) {
149+
auto *nominalDecl = cast<NominalTypeDecl>(valueDecl);
150+
InvertibleProtocolSet inverses;
151+
bool anyObject = false;
152+
getDirectlyInheritedNominalTypeDecls(nominalDecl, inverses, anyObject);
153+
if (inverses.containsEscapable()) {
154+
return true;
155+
}
156+
}
157+
158+
if (auto proto = dyn_cast<ProtocolDecl>(decl)) {
159+
auto reqSig = proto->getRequirementSignature();
160+
161+
SmallVector<Requirement, 2> reqs;
162+
SmallVector<InverseRequirement, 2> inverses;
163+
reqSig.getRequirementsWithInverses(proto, reqs, inverses);
164+
if (containsNonEscapable(inverses))
165+
return true;
166+
}
167+
168+
if (isa<AbstractFunctionDecl>(valueDecl) ||
169+
isa<AbstractStorageDecl>(valueDecl)) {
170+
if (valueDecl->getInterfaceType().findIf([&](Type type) -> bool {
171+
if (auto *nominalDecl = type->getAnyNominal()) {
172+
if (isa<StructDecl, EnumDecl, ClassDecl>(nominalDecl))
173+
return usesFeatureNonescapableTypes(nominalDecl);
174+
}
175+
return false;
176+
})) {
177+
return true;
178+
}
179+
}
180+
}
181+
182+
if (auto *ext = dyn_cast<ExtensionDecl>(decl)) {
183+
if (auto *nominal = ext->getExtendedNominal())
184+
if (usesFeatureNonescapableTypes(nominal))
185+
return true;
186+
}
187+
188+
if (auto *genCtx = decl->getAsGenericContext()) {
189+
if (auto genericSig = genCtx->getGenericSignature()) {
190+
SmallVector<Requirement, 2> reqs;
191+
SmallVector<InverseRequirement, 2> inverseReqs;
192+
genericSig->getRequirementsWithInverses(reqs, inverseReqs);
193+
if (containsNonEscapable(inverseReqs)) {
194+
return true;
195+
}
196+
}
197+
}
198+
199+
return false;
200+
}
201+
134202
UNINTERESTING_FEATURE(StaticExclusiveOnly)
135203
UNINTERESTING_FEATURE(ExtractConstantsFromMembers)
136204
UNINTERESTING_FEATURE(FixedArrays)

test/ModuleInterface/noncopyable_generics.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,11 @@ import NoncopyableGenerics_Misc
117117
// CHECK-MISC: extension {{.*}}.Outer.InnerVariation2 : Swift.Escapable where D : Swift.Escapable {
118118

119119
// CHECK-MISC: extension {{.*}}.Outer.InnerStruct {
120+
// CHECK-MISC-NEXT: #if compiler(>=5.3) && $NonescapableTypes
120121
// CHECK-MISC-NEXT: public func hello<T>(_ t: T) where T : ~Escapable
122+
// CHECK-MISC-NEXT: #else
123+
// CHECK-MISC-NEXT: public func hello<T>(_ t: T)
124+
// CHECK-MISC-NEXT: #endif
121125

122126
// CHECK-MISC: @_preInverseGenerics public func old_swap<T>(_ a: inout T, _ b: inout T) where T : ~Copyable
123127

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -module-name Test -enable-experimental-feature NonescapableTypes
3+
// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name Test
4+
// RUN: %FileCheck %s < %t.swiftinterface
5+
6+
// CHECK: #if compiler(>=5.3) && $NonescapableTypes
7+
// CHECK: public protocol P : ~Escapable {
8+
// CHECK: associatedtype A
9+
// CHECK: }
10+
// CHECK: #else
11+
// CHECK: public protocol P {
12+
// CHECK: associatedtype A
13+
// CHECK: }
14+
// CHECK: #endif
15+
public protocol P: ~Escapable {
16+
associatedtype A
17+
}
18+
19+
// CHECK: #if compiler(>=5.3) && $NonescapableTypes
20+
// CHECK: public struct X<T> : ~Swift.Escapable where T : ~Escapable {
21+
// CHECK: }
22+
// CHECK: #else
23+
// CHECK: public struct X<T> {
24+
// CHECK: }
25+
// CHECK: #endif
26+
public struct X<T: ~Escapable>: ~Escapable { }
27+
28+
// CHECK: #if compiler(>=5.3) && $NonescapableTypes
29+
// CHECK: extension Test.X {
30+
// CHECK-NEXT: func f()
31+
// CHECK: }
32+
// CHECK: #else
33+
// CHECK: extension Test.X {
34+
// CHECK-NEXT: func f()
35+
// CHECK: }
36+
extension X where T: Escapable {
37+
public func f() { }
38+
}
39+
40+
// CHECK: #if compiler(>=5.3) && $NonescapableTypes
41+
// CHECK: extension Test.X where T : ~Escapable {
42+
// CHECK: public func g(other: borrowing T)
43+
// CHECK: }
44+
// CHECK: #else
45+
// CHECK: extension Test.X {
46+
// CHECK: public func g(other: borrowing T)
47+
// CHECK: }
48+
// CHECK: #endif
49+
extension X where T: ~Escapable {
50+
public func g(other: borrowing T) { }
51+
}
52+
53+
// CHECK: #if compiler(>=5.3) && $NonescapableTypes
54+
// CHECK: public enum Y<T> : ~Swift.Escapable where T : ~Escapable {
55+
// CHECK: case none
56+
// CHECK: case some(T)
57+
// CHECK: }
58+
// CHECK: #else
59+
// CHECK: public enum Y<T> {
60+
// CHECK: case none
61+
// CHECK: case some(T)
62+
// CHECK: }
63+
public enum Y<T: ~Escapable>: ~Escapable {
64+
case none
65+
case some(T)
66+
}
67+
68+
extension Y: Escapable where T: Escapable { }
69+
70+
// CHECK: #if compiler(>=5.3) && $NonescapableTypes
71+
// CHECK: @lifetime(y)
72+
// CHECK: public func derive<T>(_ y: Test.Y<T>) -> Test.Y<T> where T : ~Escapable
73+
// CHECK: #else
74+
// CHECK: public func derive<T>(_ y: Test.Y<T>) -> Test.Y<T>
75+
// CHECK: #endif
76+
@lifetime(y)
77+
public func derive<T : ~Escapable>(_ y: Y<T>) -> Y<T> {
78+
y
79+
}
80+
81+
// CHECK: #if compiler(>=5.3) && $NonescapableTypes
82+
// CHECK: public func derive<T>(_ x: Test.X<T>) -> dependsOn(x) Test.X<T> where T : ~Escapable
83+
// CHECK: #else
84+
// CHECK: public func derive<T>(_ x: Test.X<T>) -> Test.X<T>
85+
// CHECK: #endif
86+
public func derive<T : ~Escapable>(_ x: X<T>) -> dependsOn(x) X<T> {
87+
x
88+
}

0 commit comments

Comments
 (0)