Skip to content

Commit 237dd4f

Browse files
authored
Merge pull request #71970 from rjmccall/isolated-any-availability
Fix metadata availability testing for parameterized existentials and implement it for @isolated(any) function types
2 parents bc8f42d + 0f076c0 commit 237dd4f

14 files changed

+406
-117
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6609,6 +6609,11 @@ ERROR(availability_parameterized_protocol_only_version_newer, none,
66096609
"%0 %1 or newer",
66106610
(StringRef, llvm::VersionTuple))
66116611

6612+
ERROR(availability_isolated_any_only_version_newer, none,
6613+
"runtime support for @isolated(any) function types is only available in "
6614+
"%0 %1 or newer",
6615+
(StringRef, llvm::VersionTuple))
6616+
66126617
ERROR(availability_variadic_type_only_version_newer, none,
66136618
"parameter packs in generic types are only available in %0 %1 or newer",
66146619
(StringRef, llvm::VersionTuple))

include/swift/AST/FeatureAvailability.def

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818
/// FEATURE(N, V)
1919
/// N - The name of the feature (in UpperCamelCase).
2020
/// V - The Swift version number, as a tuple, or FUTURE.
21+
///
22+
/// The feature Foo turns into two methods on ASTContext:
23+
/// getFooRuntimeAvailability(), which returns the exact version provided
24+
/// here, and getFooAvailability(), which maps that version into a version
25+
/// of the target OS. Because both of these methods exist, it is a bad idea
26+
/// to use a feature name that ends in "Runtime", or people might get very
27+
/// confused.
2128
#ifndef FEATURE
2229
#define FEATURE(N, V)
2330
#endif
@@ -48,7 +55,8 @@ FEATURE(Concurrency, (5, 5))
4855
FEATURE(MultiPayloadEnumTagSinglePayload, (5, 6))
4956
FEATURE(ObjCIsUniquelyReferenced, (5, 6))
5057

51-
FEATURE(ParameterizedExistentialRuntime, (5, 7))
58+
// Metadata and casting support for parameterized existential types
59+
FEATURE(ParameterizedExistential, (5, 7))
5260

5361
FEATURE(VariadicGenericType, (5, 9))
5462
FEATURE(SignedConformsToProtocol, (5, 9))
@@ -60,6 +68,8 @@ FEATURE(ObjCSymbolicReferences, (5, 11))
6068
FEATURE(TypedThrows, (5, 11))
6169
FEATURE(StaticReadOnlyArrays, (5, 11))
6270
FEATURE(SwiftExceptionPersonality, (5, 11))
71+
// Metadata support for @isolated(any) function types
72+
FEATURE(IsolatedAny, (5, 11))
6373

6474
FEATURE(TaskExecutor, FUTURE)
6575
FEATURE(Differentiation, FUTURE)

lib/IRGen/GenReflection.cpp

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -176,60 +176,65 @@ class PrintMetadataSource
176176

177177
std::optional<llvm::VersionTuple>
178178
getRuntimeVersionThatSupportsDemanglingType(CanType type) {
179-
// The Swift 6.0 runtime is the first version able to demangle types
180-
// that involve typed throws.
181-
bool usesTypedThrows = type.findIf([](CanType t) -> bool {
182-
if (auto fn = dyn_cast<AnyFunctionType>(t)) {
183-
if (!fn.getThrownError().isNull())
184-
return true;
185-
}
179+
enum VersionRequirement {
180+
None,
181+
Swift_5_2,
182+
Swift_5_5,
183+
Swift_6_0,
184+
185+
// Short-circuit if we find this requirement.
186+
Latest = Swift_6_0
187+
};
186188

189+
VersionRequirement latestRequirement = None;
190+
auto addRequirement = [&](VersionRequirement req) -> bool {
191+
if (req > latestRequirement) {
192+
latestRequirement = req;
193+
return req == Latest;
194+
}
187195
return false;
188-
});
189-
if (usesTypedThrows) {
190-
return llvm::VersionTuple(6, 0);
191-
}
196+
};
192197

193-
// The Swift 5.5 runtime is the first version able to demangle types
194-
// related to concurrency.
195-
bool needsConcurrency = type.findIf([](CanType t) -> bool {
198+
(void) type.findIf([&](CanType t) -> bool {
196199
if (auto fn = dyn_cast<AnyFunctionType>(t)) {
197-
if (fn->isAsync() || fn->isSendable() || fn->hasGlobalActor())
198-
return true;
199-
200-
for (const auto &param : fn->getParams()) {
201-
if (param.isIsolated())
202-
return true;
203-
}
200+
// The Swift 6.0 runtime is the first version able to demangle types
201+
// that involve typed throws or @isolated(any), or for that matter
202+
// represent them at all at runtime.
203+
if (!fn.getThrownError().isNull() || fn->getIsolation().isErased())
204+
return addRequirement(Swift_6_0);
205+
206+
// The Swift 5.5 runtime is the first version able to demangle types
207+
// related to concurrency.
208+
if (fn->isAsync() || fn->isSendable() ||
209+
!fn->getIsolation().isNonIsolated())
210+
return addRequirement(Swift_5_5);
204211

205212
return false;
206213
}
214+
215+
if (auto opaqueArchetype = dyn_cast<OpaqueTypeArchetypeType>(t)) {
216+
// Associated types of opaque types weren't mangled in a usable
217+
// form by the Swift 5.1 runtime, so we needed to add a new
218+
// mangling in 5.2.
219+
if (opaqueArchetype->getInterfaceType()->is<DependentMemberType>())
220+
return addRequirement(Swift_5_2);
221+
222+
// Although opaque types in general were only added in Swift 5.1,
223+
// declarations that use them are already covered by availability
224+
// guards, so we don't need to limit availability of mangled names
225+
// involving them.
226+
}
227+
207228
return false;
208229
});
209-
if (needsConcurrency) {
210-
return llvm::VersionTuple(5, 5);
211-
}
212230

213-
// Associated types of opaque types weren't mangled in a usable form by the
214-
// Swift 5.1 runtime, so we needed to add a new mangling in 5.2.
215-
if (type->hasOpaqueArchetype()) {
216-
auto hasOpaqueAssocType = type.findIf([](CanType t) -> bool {
217-
if (auto a = dyn_cast<ArchetypeType>(t)) {
218-
return isa<OpaqueTypeArchetypeType>(a) &&
219-
a->getInterfaceType()->is<DependentMemberType>();
220-
}
221-
return false;
222-
});
223-
224-
if (hasOpaqueAssocType)
225-
return llvm::VersionTuple(5, 2);
226-
// Although opaque types in general were only added in Swift 5.1,
227-
// declarations that use them are already covered by availability
228-
// guards, so we don't need to limit availability of mangled names
229-
// involving them.
231+
switch (latestRequirement) {
232+
case Swift_6_0: return llvm::VersionTuple(6, 0);
233+
case Swift_5_5: return llvm::VersionTuple(5, 5);
234+
case Swift_5_2: return llvm::VersionTuple(5, 2);
235+
case None: return std::nullopt;
230236
}
231-
232-
return std::nullopt;
237+
llvm_unreachable("bad kind");
233238
}
234239

235240
// Produce a fallback mangled type name that uses an open-coded callback

lib/IRGen/IRGenModule.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,7 @@ namespace RuntimeConstants {
954954
}
955955

956956
RuntimeAvailability ParameterizedExistentialAvailability(ASTContext &Context) {
957-
auto featureAvailability = Context.getParameterizedExistentialRuntimeAvailability();
957+
auto featureAvailability = Context.getParameterizedExistentialAvailability();
958958
if (!isDeploymentAvailabilityContainedIn(Context, featureAvailability)) {
959959
return RuntimeAvailability::ConditionallyAvailable;
960960
}

lib/IRGen/MetadataRequest.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,10 +1416,15 @@ getFunctionTypeFlags(CanFunctionType type) {
14161416
break;
14171417
}
14181418

1419+
auto isolation = type->getIsolation();
1420+
14191421
auto extFlags = ExtendedFunctionTypeFlags()
14201422
.withTypedThrows(!type->getThrownError().isNull())
14211423
.withTransferringResult(type->hasTransferringResult());
14221424

1425+
if (isolation.isErased())
1426+
extFlags = extFlags.withIsolatedAny();
1427+
14231428
auto flags = FunctionTypeFlags()
14241429
.withConvention(metadataConvention)
14251430
.withAsync(type->isAsync())
@@ -1428,7 +1433,7 @@ getFunctionTypeFlags(CanFunctionType type) {
14281433
.withParameterFlags(hasParameterFlags)
14291434
.withEscaping(isEscaping)
14301435
.withDifferentiable(type->isDifferentiable())
1431-
.withGlobalActor(!type->getGlobalActor().isNull())
1436+
.withGlobalActor(isolation.isGlobalActor())
14321437
.withExtendedFlags(extFlags.getIntValue() != 0);
14331438

14341439
return std::make_pair(flags, extFlags);
@@ -1632,7 +1637,8 @@ static MetadataResponse emitFunctionTypeMetadataRef(IRGenFunction &IGF,
16321637

16331638
default:
16341639
assert((!params.empty() || type->isDifferentiable() ||
1635-
type->getGlobalActor() || type->getThrownError()) &&
1640+
!type->getIsolation().isNonIsolated() ||
1641+
type->getThrownError()) &&
16361642
"0 parameter case should be specialized unless it is a "
16371643
"differentiable function or has a global actor");
16381644

0 commit comments

Comments
 (0)