Skip to content

Add more defined features to make _Concurrency model parse with older compilers #36103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,8 @@ LANGUAGE_FEATURE(AsyncAwait, 296, "async/await", true)
LANGUAGE_FEATURE(MarkerProtocol, 0, "@_marker protocol", true)
LANGUAGE_FEATURE(Actors, 0, "actors", langOpts.EnableExperimentalConcurrency)
LANGUAGE_FEATURE(ConcurrentFunctions, 0, "@concurrent functions", true)
LANGUAGE_FEATURE(RethrowsProtocol, 0, "@rethrows protocol", true)
LANGUAGE_FEATURE(GlobalActors, 0, "Global actors", langOpts.EnableExperimentalConcurrency)
LANGUAGE_FEATURE(BuiltinJob, 0, "Builtin.Job type", true)

#undef LANGUAGE_FEATURE
95 changes: 95 additions & 0 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "swift/AST/ASTMangler.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/Attr.h"
#include "swift/AST/Builtins.h"
#include "swift/AST/ClangModuleLoader.h"
#include "swift/AST/Comment.h"
#include "swift/AST/Decl.h"
Expand Down Expand Up @@ -2511,6 +2512,100 @@ static bool usesFeatureConcurrentFunctions(Decl *decl) {
return false;
}

static bool usesFeatureRethrowsProtocol(
Decl *decl, SmallPtrSet<Decl *, 16> &checked) {
// Make sure we don't recurse.
if (!checked.insert(decl).second)
return false;

if (auto proto = dyn_cast<ProtocolDecl>(decl)) {
if (proto->getAttrs().hasAttribute<AtRethrowsAttr>())
return true;
}

if (auto ext = dyn_cast<ExtensionDecl>(decl)) {
if (auto proto = ext->getSelfProtocolDecl())
if (usesFeatureRethrowsProtocol(proto, checked))
return true;
}

if (auto genericSig = decl->getInnermostDeclContext()
->getGenericSignatureOfContext()) {
for (const auto &req : genericSig->getRequirements()) {
if (req.getKind() == RequirementKind::Conformance &&
usesFeatureRethrowsProtocol(
req.getSecondType()->getAs<ProtocolType>()->getDecl(), checked))
return true;
}
}

if (auto value = dyn_cast<ValueDecl>(decl)) {
if (Type type = value->getInterfaceType()) {
bool hasRethrowsProtocol = type.findIf([&](Type type) {
if (auto nominal = type->getAnyNominal()) {
if (usesFeatureRethrowsProtocol(nominal, checked))
return true;
}

return false;
});

if (hasRethrowsProtocol)
return true;
}
}

return false;
}

static bool usesFeatureRethrowsProtocol(Decl *decl) {
SmallPtrSet<Decl *, 16> checked;
return usesFeatureRethrowsProtocol(decl, checked);
}

static bool usesFeatureGlobalActors(Decl *decl) {
if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
if (nominal->getAttrs().hasAttribute<GlobalActorAttr>())
return true;
}

if (auto ext = dyn_cast<ExtensionDecl>(decl)) {
if (auto nominal = ext->getExtendedNominal())
if (usesFeatureGlobalActors(nominal))
return true;
}

return false;
}

static bool usesFeatureBuiltinJob(Decl *decl) {
auto typeHasBuiltinJob = [](Type type) {
return type.findIf([&](Type type) {
if (auto builtinTy = type->getAs<BuiltinType>())
return builtinTy->getBuiltinTypeKind() == BuiltinTypeKind::BuiltinJob;

return false;
});
};

if (auto value = dyn_cast<ValueDecl>(decl)) {
if (Type type = value->getInterfaceType()) {
if (typeHasBuiltinJob(type))
return true;
}
}

if (auto patternBinding = dyn_cast<PatternBindingDecl>(decl)) {
for (unsigned idx : range(patternBinding->getNumPatternEntries())) {
if (Type type = patternBinding->getPattern(idx)->getType())
if (typeHasBuiltinJob(type))
return true;
}
}

return false;
}

/// Determine the set of "new" features used on a given declaration.
///
/// Note: right now, all features we check for are "new". At some point, we'll
Expand Down
18 changes: 18 additions & 0 deletions test/ModuleInterface/features.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ public class OldSchool: MP {
public func takeClass() async { }
}

// CHECK: #if compiler(>=5.3) && $RethrowsProtocol
// CHECK-NEXT: @rethrows public protocol RP
@rethrows public protocol RP {
func f() throws
}

// CHECK: #if compiler(>=5.3) && $RethrowsProtocol
// CHECK-NEXT: public func acceptsRP
public func acceptsRP<T: RP>(_: T) { }

// CHECK-NOT: #if compiler(>=5.3) && $MarkerProtocol
// CHECK: extension Array : FeatureTest.MP where Element : FeatureTest.MP {
extension Array: FeatureTest.MP where Element : FeatureTest.MP { }
Expand All @@ -77,6 +87,14 @@ extension Array: FeatureTest.MP where Element : FeatureTest.MP { }
extension OldSchool: UnsafeConcurrentValue { }
// CHECK-NEXT: }

// CHECK: #if compiler(>=5.3) && $GlobalActors
// CHECK-NEXT: @globalActor public struct SomeGlobalActor
@globalActor
public struct SomeGlobalActor {
public static let shared = MyActor()
}


// CHECK: #if compiler(>=5.3) && $AsyncAwait
// CHECK-NEXT: func runSomethingSomewhere
// CHECK-NEXT: #endif
Expand Down