[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);

View File

@@ -28,6 +28,7 @@ namespace swift {
class SILType;
class ProtocolDecl;
enum class CastConsumptionKind : unsigned char;
enum class CastingIsolatedConformances: uint8_t;
namespace irgen {
class Address;
@@ -46,7 +47,8 @@ namespace irgen {
Address dest,
CanType toType,
CastConsumptionKind consumptionKind,
CheckedCastMode mode);
CheckedCastMode mode,
CastingIsolatedConformances isolatedConformances);
void emitScalarCheckedCast(IRGenFunction &IGF, Explosion &value,
SILType sourceLoweredType,
@@ -54,6 +56,7 @@ namespace irgen {
SILType targetLoweredType,
CanType targetFormalType,
CheckedCastMode mode,
CastingIsolatedConformances isolatedConformances,
Explosion &out);
llvm::Value *emitFastClassCastIfPossible(

View File

@@ -7186,7 +7186,8 @@ visitUncheckedRefCastAddrInst(swift::UncheckedRefCastAddrInst *i) {
src, i->getSourceFormalType(),
dest, i->getTargetFormalType(),
CastConsumptionKind::TakeAlways,
CheckedCastMode::Unconditional);
CheckedCastMode::Unconditional,
CastingIsolatedConformances::Allow);
}
void IRGenSILFunction::visitUncheckedAddrCastInst(
@@ -7416,6 +7417,7 @@ void IRGenSILFunction::visitUnconditionalCheckedCastInst(
i->getTargetLoweredType(),
i->getTargetFormalType(),
CheckedCastMode::Unconditional,
i->getIsolatedConformances(),
ex);
setLoweredExplosion(i, ex);
}
@@ -7604,7 +7606,8 @@ void IRGenSILFunction::visitUnconditionalCheckedCastAddrInst(
src, i->getSourceFormalType(),
dest, i->getTargetFormalType(),
CastConsumptionKind::TakeAlways,
CheckedCastMode::Unconditional);
CheckedCastMode::Unconditional,
i->getIsolatedConformances());
}
void IRGenSILFunction::visitCheckedCastBranchInst(
@@ -7625,6 +7628,7 @@ void IRGenSILFunction::visitCheckedCastBranchInst(
i->getTargetLoweredType(),
i->getTargetFormalType(),
CheckedCastMode::Conditional,
i->getIsolatedConformances(),
ex);
auto val = ex.claimNext();
castResult.casted = val;
@@ -7662,7 +7666,8 @@ void IRGenSILFunction::visitCheckedCastAddrBranchInst(
emitCheckedCast(*this,
src, i->getSourceFormalType(),
dest, i->getTargetFormalType(),
i->getConsumptionKind(), CheckedCastMode::Conditional);
i->getConsumptionKind(), CheckedCastMode::Conditional,
i->getIsolatedConformances());
Builder.CreateCondBr(castSucceeded,
getLoweredBB(i->getSuccessBB()).bb,
getLoweredBB(i->getFailureBB()).bb);