Skip to content

Commit f21c609

Browse files
committed
Add feature for rethrows protocols and use it in module interface generation
1 parent 267838d commit f21c609

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
lines changed

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@ LANGUAGE_FEATURE(AsyncAwait, 296, "async/await", true)
3939
LANGUAGE_FEATURE(MarkerProtocol, 0, "@_marker protocol", true)
4040
LANGUAGE_FEATURE(Actors, 0, "actors", langOpts.EnableExperimentalConcurrency)
4141
LANGUAGE_FEATURE(ConcurrentFunctions, 0, "@concurrent functions", true)
42+
LANGUAGE_FEATURE(RethrowsProtocol, 0, "@rethrows protocol", true)
4243

4344
#undef LANGUAGE_FEATURE

lib/AST/ASTPrinter.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2511,6 +2511,57 @@ static bool usesFeatureConcurrentFunctions(Decl *decl) {
25112511
return false;
25122512
}
25132513

2514+
static bool usesFeatureRethrowsProtocol(
2515+
Decl *decl, SmallPtrSet<Decl *, 16> &checked) {
2516+
// Make sure we don't recurse.
2517+
if (!checked.insert(decl).second)
2518+
return false;
2519+
2520+
if (auto proto = dyn_cast<ProtocolDecl>(decl)) {
2521+
if (proto->getAttrs().hasAttribute<AtRethrowsAttr>())
2522+
return true;
2523+
}
2524+
2525+
if (auto ext = dyn_cast<ExtensionDecl>(decl)) {
2526+
if (auto proto = ext->getSelfProtocolDecl())
2527+
if (usesFeatureRethrowsProtocol(proto, checked))
2528+
return true;
2529+
}
2530+
2531+
if (auto genericSig = decl->getInnermostDeclContext()
2532+
->getGenericSignatureOfContext()) {
2533+
for (const auto &req : genericSig->getRequirements()) {
2534+
if (req.getKind() == RequirementKind::Conformance &&
2535+
usesFeatureRethrowsProtocol(
2536+
req.getSecondType()->getAs<ProtocolType>()->getDecl(), checked))
2537+
return true;
2538+
}
2539+
}
2540+
2541+
if (auto value = dyn_cast<ValueDecl>(decl)) {
2542+
if (Type type = value->getInterfaceType()) {
2543+
bool hasRethrowsProtocol = type.findIf([&](Type type) {
2544+
if (auto nominal = type->getAnyNominal()) {
2545+
if (usesFeatureRethrowsProtocol(nominal, checked))
2546+
return true;
2547+
}
2548+
2549+
return false;
2550+
});
2551+
2552+
if (hasRethrowsProtocol)
2553+
return true;
2554+
}
2555+
}
2556+
2557+
return false;
2558+
}
2559+
2560+
static bool usesFeatureRethrowsProtocol(Decl *decl) {
2561+
SmallPtrSet<Decl *, 16> checked;
2562+
return usesFeatureRethrowsProtocol(decl, checked);
2563+
}
2564+
25142565
/// Determine the set of "new" features used on a given declaration.
25152566
///
25162567
/// Note: right now, all features we check for are "new". At some point, we'll

test/ModuleInterface/features.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,16 @@ public class OldSchool: MP {
6767
public func takeClass() async { }
6868
}
6969

70+
// CHECK: #if compiler(>=5.3) && $RethrowsProtocol
71+
// CHECK-NEXT: @rethrows public protocol RP
72+
@rethrows public protocol RP {
73+
func f() throws
74+
}
75+
76+
// CHECK: #if compiler(>=5.3) && $RethrowsProtocol
77+
// CHECK-NEXT: public func acceptsRP
78+
public func acceptsRP<T: RP>(_: T) { }
79+
7080
// CHECK-NOT: #if compiler(>=5.3) && $MarkerProtocol
7181
// CHECK: extension Array : FeatureTest.MP where Element : FeatureTest.MP {
7282
extension Array: FeatureTest.MP where Element : FeatureTest.MP { }

0 commit comments

Comments
 (0)