Skip to content

Commit a61c400

Browse files
authored
Merge pull request #80337 from DougGregor/cast-prohibits-isolated-conformances
[SE-0470] Prohibit isolated conformances in dynamic casts that can't safely use them
2 parents d644044 + edd118a commit a61c400

37 files changed

+715
-217
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,14 @@ private extension AllocStackInst {
213213
builder.createCheckedCastAddrBranch(
214214
source: newAlloc, sourceFormalType: concreteFormalType,
215215
destination: cab.destination, targetFormalType: cab.targetFormalType,
216+
isolatedConformances: cab.isolatedConformances,
216217
consumptionKind: cab.consumptionKind,
217218
successBlock: cab.successBlock, failureBlock: cab.failureBlock)
218219
context.erase(instruction: cab)
219220
case let ucca as UnconditionalCheckedCastAddrInst:
220221
let builder = Builder(before: ucca, context)
221222
builder.createUnconditionalCheckedCastAddr(
223+
isolatedConformances: ucca.isolatedConformances,
222224
source: newAlloc, sourceFormalType: concreteFormalType,
223225
destination: ucca.destination, targetFormalType: ucca.targetFormalType)
224226
context.erase(instruction: ucca)

SwiftCompilerSources/Sources/SIL/Builder.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ public struct Builder {
180180
public func createCheckedCastAddrBranch(
181181
source: Value, sourceFormalType: CanonicalType,
182182
destination: Value, targetFormalType: CanonicalType,
183-
consumptionKind: CheckedCastAddrBranchInst.CastConsumptionKind,
183+
isolatedConformances: CastingIsolatedConformances,
184+
consumptionKind: CheckedCastAddrBranchInst.CastConsumptionKind,
184185
successBlock: BasicBlock,
185186
failureBlock: BasicBlock
186187
) -> CheckedCastAddrBranchInst {
@@ -191,20 +192,26 @@ public struct Builder {
191192
case .TakeOnSuccess: bridgedConsumption = .TakeOnSuccess
192193
case .CopyOnSuccess: bridgedConsumption = .CopyOnSuccess
193194
}
195+
194196
let cast = bridged.createCheckedCastAddrBranch(source.bridged, sourceFormalType.bridged,
195197
destination.bridged, targetFormalType.bridged,
198+
isolatedConformances.bridged,
196199
bridgedConsumption,
197200
successBlock.bridged, failureBlock.bridged)
198201
return notifyNew(cast.getAs(CheckedCastAddrBranchInst.self))
199202
}
200203

201204
@discardableResult
202205
public func createUnconditionalCheckedCastAddr(
206+
isolatedConformances: CastingIsolatedConformances,
203207
source: Value, sourceFormalType: CanonicalType,
204208
destination: Value, targetFormalType: CanonicalType
205209
) -> UnconditionalCheckedCastAddrInst {
206-
let cast = bridged.createUnconditionalCheckedCastAddr(source.bridged, sourceFormalType.bridged,
207-
destination.bridged, targetFormalType.bridged)
210+
let cast = bridged.createUnconditionalCheckedCastAddr(
211+
isolatedConformances.bridged, source.bridged,
212+
sourceFormalType.bridged,
213+
destination.bridged, targetFormalType.bridged
214+
)
208215
return notifyNew(cast.getAs(UnconditionalCheckedCastAddrInst.self))
209216
}
210217

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,14 @@ final public class UnconditionalCheckedCastAddrInst : Instruction, SourceDestAdd
528528
public var isTakeOfSrc: Bool { true }
529529
public var isInitializationOfDest: Bool { true }
530530
public override var mayTrap: Bool { true }
531+
532+
public var isolatedConformances: CastingIsolatedConformances {
533+
switch bridged.UnconditionalCheckedCastAddr_getIsolatedConformances() {
534+
case .Allow: .allow
535+
case .Prohibit: .prohibit
536+
@unknown default: fatalError("Unhandled CastingIsolatedConformances")
537+
}
538+
}
531539
}
532540

533541
final public class BeginDeallocRefInst : SingleValueInstruction, UnaryInstruction {
@@ -1032,6 +1040,14 @@ class UnconditionalCheckedCastInst : SingleValueInstruction, UnaryInstruction {
10321040
public var targetFormalType: CanonicalType {
10331041
CanonicalType(bridged: bridged.UnconditionalCheckedCast_getTargetFormalType())
10341042
}
1043+
1044+
public var isolatedConformances: CastingIsolatedConformances {
1045+
switch bridged.UnconditionalCheckedCast_getIsolatedConformances() {
1046+
case .Allow: .allow
1047+
case .Prohibit: .prohibit
1048+
@unknown default: fatalError("Unhandled CastingIsolatedConformances")
1049+
}
1050+
}
10351051
}
10361052

10371053
final public
@@ -1771,6 +1787,18 @@ final public class DynamicMethodBranchInst : TermInst {
17711787
final public class AwaitAsyncContinuationInst : TermInst, UnaryInstruction {
17721788
}
17731789

1790+
public enum CastingIsolatedConformances {
1791+
case allow
1792+
case prohibit
1793+
1794+
var bridged: BridgedInstruction.CastingIsolatedConformances {
1795+
switch self {
1796+
case .allow: return .Allow
1797+
case .prohibit: return .Prohibit
1798+
}
1799+
}
1800+
}
1801+
17741802
final public class CheckedCastBranchInst : TermInst, UnaryInstruction {
17751803
public var source: Value { operand.value }
17761804
public var successBlock: BasicBlock { bridged.CheckedCastBranch_getSuccessBlock().block }
@@ -1779,6 +1807,14 @@ final public class CheckedCastBranchInst : TermInst, UnaryInstruction {
17791807
public func updateSourceFormalTypeFromOperandLoweredType() {
17801808
bridged.CheckedCastBranch_updateSourceFormalTypeFromOperandLoweredType()
17811809
}
1810+
1811+
public var isolatedConformances: CastingIsolatedConformances {
1812+
switch bridged.CheckedCastBranch_getIsolatedConformances() {
1813+
case .Allow: return .allow
1814+
case .Prohibit: return .prohibit
1815+
default: fatalError("Bad CastingIsolatedConformances value")
1816+
}
1817+
}
17821818
}
17831819

17841820
final public class CheckedCastAddrBranchInst : TermInst {
@@ -1819,6 +1855,14 @@ final public class CheckedCastAddrBranchInst : TermInst {
18191855
fatalError("invalid cast consumption kind")
18201856
}
18211857
}
1858+
1859+
public var isolatedConformances: CastingIsolatedConformances {
1860+
switch bridged.CheckedCastAddrBranch_getIsolatedConformances() {
1861+
case .Allow: .allow
1862+
case .Prohibit: .prohibit
1863+
@unknown default: fatalError("Unhandled CastingIsolatedConformances")
1864+
}
1865+
}
18221866
}
18231867

18241868
final public class ThunkInst : Instruction {

docs/SIL/Instructions.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4851,7 +4851,9 @@ on whether the cast succeeds or not.
48514851
### unconditional_checked_cast
48524852

48534853
```
4854-
sil-instruction ::= 'unconditional_checked_cast' sil-operand 'to' sil-type
4854+
sil-instruction ::= 'unconditional_checked_cast'
4855+
sil-prohibit-isolated-conformances?
4856+
sil-operand 'to' sil-type
48554857
48564858
%1 = unconditional_checked_cast %0 : $A to $B
48574859
%1 = unconditional_checked_cast %0 : $*A to $*B
@@ -4867,8 +4869,9 @@ ownership are unsupported.
48674869

48684870
```
48694871
sil-instruction ::= 'unconditional_checked_cast_addr'
4870-
sil-type 'in' sil-operand 'to'
4871-
sil-type 'in' sil-operand
4872+
sil-prohibit-isolated-conformances?
4873+
sil-type 'in' sil-operand 'to'
4874+
sil-type 'in' sil-operand
48724875
48734876
unconditional_checked_cast_addr $A in %0 : $*@thick A to $B in %1 : $*@thick B
48744877
// $A and $B must be both addresses
@@ -5231,10 +5234,12 @@ instruction branches to `bb2`.
52315234

52325235
```
52335236
sil-terminator ::= 'checked_cast_br' sil-checked-cast-exact?
5237+
sil-prohibit-isolated-conformances?
52345238
sil-type 'in'
52355239
sil-operand 'to' sil-type ','
52365240
sil-identifier ',' sil-identifier
52375241
sil-checked-cast-exact ::= '[' 'exact' ']'
5242+
sil-prohibit-isolated-conformances ::= '[' 'prohibit_isolated_conformances' ']'
52385243
52395244
checked_cast_br A in %0 : $A to $B, bb1, bb2
52405245
checked_cast_br *A in %0 : $*A to $*B, bb1, bb2
@@ -5253,10 +5258,14 @@ An exact cast checks whether the dynamic type is exactly the target
52535258
type, not any possible subtype of it. The source and target types must
52545259
be class types.
52555260

5261+
A cast can specify that the runtime should prohibit all uses of isolated
5262+
conformances when attempting to satisfy protocol requirements of existentials.
5263+
52565264
### checked_cast_addr_br
52575265

52585266
```
52595267
sil-terminator ::= 'checked_cast_addr_br'
5268+
sil-prohibit-isolated-conformances?
52605269
sil-cast-consumption-kind
52615270
sil-type 'in' sil-operand 'to'
52625271
sil-stype 'in' sil-operand ','

include/swift/ABI/MetadataValues.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,11 @@ enum class DynamicCastFlags : size_t {
313313
/// True if the cast should destroy the source value on failure;
314314
/// false if the value should be left in place.
315315
DestroyOnFailure = 0x4,
316+
317+
/// True if the cast should prohibit the use of any isolated conformances,
318+
/// for example because there is a Sendable constraint on the existential
319+
/// type we're casting to.
320+
ProhibitIsolatedConformances = 0x8,
316321
};
317322
inline bool operator&(DynamicCastFlags a, DynamicCastFlags b) {
318323
return (size_t(a) & size_t(b)) != 0;

include/swift/SIL/DynamicCasts.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ bool canIRGenUseScalarCheckedCastInstructions(SILModule &M,
103103
/// using a scalar cast operation.
104104
void emitIndirectConditionalCastWithScalar(
105105
SILBuilder &B, ModuleDecl *M, SILLocation loc,
106+
CastingIsolatedConformances isolatedConformances,
106107
CastConsumptionKind consumption, SILValue src, CanType sourceType,
107108
SILValue dest, CanType targetType, SILBasicBlock *trueBB,
108109
SILBasicBlock *falseBB, ProfileCounter TrueCount = ProfileCounter(),
@@ -452,6 +453,21 @@ struct SILDynamicCastInst {
452453
return swift::canSILUseScalarCheckedCastInstructions(
453454
getModule(), getSourceFormalType(), getTargetFormalType());
454455
}
456+
457+
CastingIsolatedConformances getIsolatedConformances() const {
458+
switch (getKind()) {
459+
case SILDynamicCastKind::CheckedCastAddrBranchInst:
460+
return cast<CheckedCastAddrBranchInst>(inst)->getIsolatedConformances();
461+
case SILDynamicCastKind::CheckedCastBranchInst:
462+
return cast<CheckedCastBranchInst>(inst)->getIsolatedConformances();
463+
case SILDynamicCastKind::UnconditionalCheckedCastAddrInst:
464+
return cast<UnconditionalCheckedCastAddrInst>(inst)
465+
->getIsolatedConformances();
466+
case SILDynamicCastKind::UnconditionalCheckedCastInst:
467+
return cast<UnconditionalCheckedCastInst>(inst)
468+
->getIsolatedConformances();
469+
}
470+
}
455471
};
456472

457473
} // end namespace swift

include/swift/SIL/SILBridging.h

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,11 @@ struct BridgedInstruction {
696696
CopyOnSuccess
697697
};
698698

699+
enum class CastingIsolatedConformances {
700+
Allow,
701+
Prohibit
702+
};
703+
699704
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedStringRef CondFailInst_getMessage() const;
700705
BRIDGED_INLINE SwiftInt LoadInst_getLoadOwnership() const ;
701706
BRIDGED_INLINE bool LoadBorrowInst_isUnchecked() const ;
@@ -802,14 +807,22 @@ struct BridgedInstruction {
802807
BRIDGED_INLINE void LoadInst_setOwnership(SwiftInt ownership) const;
803808
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedCanType UnconditionalCheckedCast_getSourceFormalType() const;
804809
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedCanType UnconditionalCheckedCast_getTargetFormalType() const;
810+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE CastingIsolatedConformances
811+
UnconditionalCheckedCast_getIsolatedConformances() const;
805812
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedCanType UnconditionalCheckedCastAddr_getSourceFormalType() const;
806813
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedCanType UnconditionalCheckedCastAddr_getTargetFormalType() const;
814+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE CastingIsolatedConformances
815+
UnconditionalCheckedCastAddr_getIsolatedConformances() const;
807816
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock CheckedCastBranch_getSuccessBlock() const;
808817
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock CheckedCastBranch_getFailureBlock() const;
818+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE CastingIsolatedConformances
819+
CheckedCastBranch_getIsolatedConformances() const;
809820
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedCanType CheckedCastAddrBranch_getSourceFormalType() const;
810821
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedCanType CheckedCastAddrBranch_getTargetFormalType() const;
811822
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock CheckedCastAddrBranch_getSuccessBlock() const;
812823
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock CheckedCastAddrBranch_getFailureBlock() const;
824+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE CastingIsolatedConformances
825+
CheckedCastAddrBranch_getIsolatedConformances() const;
813826
BRIDGED_INLINE void CheckedCastBranch_updateSourceFormalTypeFromOperandLoweredType() const;
814827
BRIDGED_INLINE CastConsumptionKind CheckedCastAddrBranch_getConsumptionKind() const;
815828
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedSubstitutionMap ApplySite_getSubstitutionMap() const;
@@ -1122,13 +1135,15 @@ struct BridgedBuilder{
11221135
BridgedType type) const;
11231136
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createUpcast(BridgedValue op, BridgedType type) const;
11241137
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createCheckedCastAddrBranch(
1125-
BridgedValue source, BridgedCanType sourceFormalType,
1126-
BridgedValue destination, BridgedCanType targetFormalType,
1127-
BridgedInstruction::CastConsumptionKind consumptionKind,
1128-
BridgedBasicBlock successBlock, BridgedBasicBlock failureBlock) const;
1138+
BridgedValue source, BridgedCanType sourceFormalType,
1139+
BridgedValue destination, BridgedCanType targetFormalType,
1140+
BridgedInstruction::CastingIsolatedConformances isolatedConformances,
1141+
BridgedInstruction::CastConsumptionKind consumptionKind,
1142+
BridgedBasicBlock successBlock, BridgedBasicBlock failureBlock) const;
11291143
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createUnconditionalCheckedCastAddr(
1130-
BridgedValue source, BridgedCanType sourceFormalType,
1131-
BridgedValue destination, BridgedCanType targetFormalType) const;
1144+
BridgedInstruction::CastingIsolatedConformances isolatedConformances,
1145+
BridgedValue source, BridgedCanType sourceFormalType,
1146+
BridgedValue destination, BridgedCanType targetFormalType) const;
11321147
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createLoad(BridgedValue op, SwiftInt ownership) const;
11331148
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createLoadBorrow(BridgedValue op) const;
11341149
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createBeginDeallocRef(BridgedValue reference,

include/swift/SIL/SILBridgingImpl.h

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,12 @@ BridgedCanType BridgedInstruction::UnconditionalCheckedCast_getTargetFormalType(
14751475
return {getAs<swift::UnconditionalCheckedCastInst>()->getTargetFormalType()};
14761476
}
14771477

1478+
BridgedInstruction::CastingIsolatedConformances
1479+
BridgedInstruction::UnconditionalCheckedCast_getIsolatedConformances() const {
1480+
return static_cast<BridgedInstruction::CastingIsolatedConformances>(
1481+
getAs<swift::UnconditionalCheckedCastInst>()->getIsolatedConformances());
1482+
}
1483+
14781484
BridgedCanType BridgedInstruction::UnconditionalCheckedCastAddr_getSourceFormalType() const {
14791485
return {getAs<swift::UnconditionalCheckedCastAddrInst>()->getSourceFormalType()};
14801486
}
@@ -1483,6 +1489,12 @@ BridgedCanType BridgedInstruction::UnconditionalCheckedCastAddr_getTargetFormalT
14831489
return {getAs<swift::UnconditionalCheckedCastAddrInst>()->getTargetFormalType()};
14841490
}
14851491

1492+
BridgedInstruction::CastingIsolatedConformances
1493+
BridgedInstruction::UnconditionalCheckedCastAddr_getIsolatedConformances() const {
1494+
return static_cast<BridgedInstruction::CastingIsolatedConformances>(
1495+
getAs<swift::UnconditionalCheckedCastAddrInst>()->getIsolatedConformances());
1496+
}
1497+
14861498
BridgedBasicBlock BridgedInstruction::CheckedCastBranch_getSuccessBlock() const {
14871499
return {getAs<swift::CheckedCastBranchInst>()->getSuccessBB()};
14881500
}
@@ -1491,6 +1503,12 @@ BridgedBasicBlock BridgedInstruction::CheckedCastBranch_getFailureBlock() const
14911503
return {getAs<swift::CheckedCastBranchInst>()->getFailureBB()};
14921504
}
14931505

1506+
BridgedInstruction::CastingIsolatedConformances
1507+
BridgedInstruction::CheckedCastBranch_getIsolatedConformances() const {
1508+
return static_cast<BridgedInstruction::CastingIsolatedConformances>(
1509+
getAs<swift::CheckedCastBranchInst>()->getIsolatedConformances());
1510+
}
1511+
14941512
BridgedCanType BridgedInstruction::CheckedCastAddrBranch_getSourceFormalType() const {
14951513
return {getAs<swift::CheckedCastAddrBranchInst>()->getSourceFormalType()};
14961514
}
@@ -1519,6 +1537,11 @@ BridgedInstruction::CastConsumptionKind BridgedInstruction::CheckedCastAddrBranc
15191537
getAs<swift::CheckedCastAddrBranchInst>()->getConsumptionKind());
15201538
}
15211539

1540+
BridgedInstruction::CastingIsolatedConformances
1541+
BridgedInstruction::CheckedCastAddrBranch_getIsolatedConformances() const {
1542+
return static_cast<BridgedInstruction::CastingIsolatedConformances>(
1543+
getAs<swift::CheckedCastAddrBranchInst>()->getIsolatedConformances());
1544+
}
15221545

15231546
BridgedSubstitutionMap BridgedInstruction::ApplySite_getSubstitutionMap() const {
15241547
auto as = swift::ApplySite(unbridged());
@@ -2065,25 +2088,31 @@ BridgedInstruction BridgedBuilder::createUpcast(BridgedValue op, BridgedType typ
20652088
}
20662089

20672090
BridgedInstruction BridgedBuilder::createCheckedCastAddrBranch(
2068-
BridgedValue source, BridgedCanType sourceFormalType,
2069-
BridgedValue destination, BridgedCanType targetFormalType,
2070-
BridgedInstruction::CastConsumptionKind consumptionKind,
2071-
BridgedBasicBlock successBlock, BridgedBasicBlock failureBlock) const
2091+
BridgedValue source, BridgedCanType sourceFormalType,
2092+
BridgedValue destination, BridgedCanType targetFormalType,
2093+
BridgedInstruction::CastingIsolatedConformances isolatedConformances,
2094+
BridgedInstruction::CastConsumptionKind consumptionKind,
2095+
BridgedBasicBlock successBlock, BridgedBasicBlock failureBlock) const
20722096
{
20732097
return {unbridged().createCheckedCastAddrBranch(
2074-
regularLoc(), (swift::CastConsumptionKind)consumptionKind,
2075-
source.getSILValue(), sourceFormalType.unbridged(),
2076-
destination.getSILValue(), targetFormalType.unbridged(),
2077-
successBlock.unbridged(), failureBlock.unbridged())};
2098+
regularLoc(),
2099+
(swift::CastingIsolatedConformances)isolatedConformances,
2100+
(swift::CastConsumptionKind)consumptionKind,
2101+
source.getSILValue(), sourceFormalType.unbridged(),
2102+
destination.getSILValue(), targetFormalType.unbridged(),
2103+
successBlock.unbridged(), failureBlock.unbridged())};
20782104
}
20792105

20802106
BridgedInstruction BridgedBuilder::createUnconditionalCheckedCastAddr(
2081-
BridgedValue source, BridgedCanType sourceFormalType,
2082-
BridgedValue destination, BridgedCanType targetFormalType) const
2107+
BridgedInstruction::CastingIsolatedConformances isolatedConformances,
2108+
BridgedValue source, BridgedCanType sourceFormalType,
2109+
BridgedValue destination, BridgedCanType targetFormalType) const
20832110
{
20842111
return {unbridged().createUnconditionalCheckedCastAddr(
2085-
regularLoc(), source.getSILValue(), sourceFormalType.unbridged(),
2086-
destination.getSILValue(), targetFormalType.unbridged())};
2112+
regularLoc(),
2113+
(swift::CastingIsolatedConformances)isolatedConformances,
2114+
source.getSILValue(), sourceFormalType.unbridged(),
2115+
destination.getSILValue(), targetFormalType.unbridged())};
20872116
}
20882117

20892118
BridgedInstruction BridgedBuilder::createLoad(BridgedValue op, SwiftInt ownership) const {

0 commit comments

Comments
 (0)