Skip to content

Commit 8a2556a

Browse files
committed
Fix metadata availability testing for parameterized existentials
and implement it for @isolated(any) function types. The existing testing was pretty broken: we were diagnosing all sorts of things that don't require type metadata (like using a tuple with an extended existential in a value position in an API signature) and not diagnosing several things that do (like covariant function conversions that erase types). There's therefore some risk to this patch, but I'm not too worried because needing metadata like this is pretty uncommon, and it's likely that programs won't build correctly anyway --- it'll just get caught by the linker instead of the compiler.
1 parent 69c8f53 commit 8a2556a

11 files changed

+393
-112
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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ FEATURE(ObjCSymbolicReferences, (5, 11))
6868
FEATURE(TypedThrows, (5, 11))
6969
FEATURE(StaticReadOnlyArrays, (5, 11))
7070
FEATURE(SwiftExceptionPersonality, (5, 11))
71+
// Metadata support for @isolated(any) function types
72+
FEATURE(IsolatedAny, (5, 11))
7173

7274
FEATURE(TaskExecutor, FUTURE)
7375
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/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)