[SE-0470] Prohibit isolated conformances in dynamic casts marked as such

Certain dynamic casts cannot work safely with isolated conformances,
regardless of what executor the code runs on. For such cases, reject
all attempts to conform to the type.
This commit is contained in:
Doug Gregor
2025-03-26 22:29:12 -07:00
parent e0b52cd20e
commit 43df05a89c
8 changed files with 202 additions and 84 deletions

View File

@@ -42,8 +42,11 @@ using namespace swift;
using namespace irgen;
/// Compute the flags to pass to swift_dynamicCast.
static DynamicCastFlags getDynamicCastFlags(CastConsumptionKind consumptionKind,
CheckedCastMode mode) {
static DynamicCastFlags getDynamicCastFlags(
CastConsumptionKind consumptionKind,
CheckedCastMode mode,
CastingIsolatedConformances isolatedConformances
) {
DynamicCastFlags flags = DynamicCastFlags::Default;
if (mode == CheckedCastMode::Unconditional)
@@ -53,6 +56,14 @@ static DynamicCastFlags getDynamicCastFlags(CastConsumptionKind consumptionKind,
if (shouldTakeOnSuccess(consumptionKind))
flags |= DynamicCastFlags::TakeOnSuccess;
switch (isolatedConformances) {
case CastingIsolatedConformances::Allow:
break;
case CastingIsolatedConformances::Prohibit:
flags |= DynamicCastFlags::ProhibitIsolatedConformances;
break;
}
return flags;
}
@@ -63,10 +74,12 @@ llvm::Value *irgen::emitCheckedCast(IRGenFunction &IGF,
Address dest,
CanType targetType,
CastConsumptionKind consumptionKind,
CheckedCastMode mode) {
CheckedCastMode mode,
CastingIsolatedConformances isolatedConformances) {
// TODO: attempt to specialize this based on the known types.
DynamicCastFlags flags = getDynamicCastFlags(consumptionKind, mode);
DynamicCastFlags flags = getDynamicCastFlags(consumptionKind, mode,
isolatedConformances);
// Cast both addresses to opaque pointer type.
dest = IGF.Builder.CreateElementBitCast(dest, IGF.IGM.OpaqueTy);
@@ -847,6 +860,7 @@ void irgen::emitScalarCheckedCast(IRGenFunction &IGF,
SILType targetLoweredType,
CanType targetFormalType,
CheckedCastMode mode,
CastingIsolatedConformances isolatedConformances,
Explosion &out) {
assert(sourceLoweredType.isObject());
assert(targetLoweredType.isObject());
@@ -976,7 +990,7 @@ void irgen::emitScalarCheckedCast(IRGenFunction &IGF,
src, sourceFormalType,
dest, targetFormalType,
CastConsumptionKind::TakeAlways,
mode);
mode, isolatedConformances);
llvm::Value *successResult = IGF.Builder.CreateLoad(dest);
llvm::Value *failureResult = llvm::ConstantPointerNull::get(destPtrType);
llvm::Value *result = IGF.Builder.CreateSelect(success, successResult, failureResult);