Skip to content

Commit 0232a0f

Browse files
authored
Merge pull request #20968 from mikeash/anyhashable-cast-leak-fix-5.0
[5.0][Runtime] Fix leak when casting to AnyHashable.
2 parents 6388ea4 + 58ab8f8 commit 0232a0f

File tree

2 files changed

+16
-13
lines changed

2 files changed

+16
-13
lines changed

stdlib/public/runtime/Casting.cpp

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -635,23 +635,13 @@ static bool _dynamicCastToAnyHashable(OpaqueValue *destination,
635635

636636
// If we do find one, the cast succeeds.
637637

638-
// The intrinsic wants the value at +1, so we have to copy it into
639-
// a temporary.
640-
ValueBuffer buffer;
641-
bool mustDeallocBuffer = false;
642-
if (!(flags & DynamicCastFlags::TakeOnSuccess)) {
643-
auto *valueAddr = sourceType->allocateBufferIn(&buffer);
644-
source = sourceType->vw_initializeWithCopy(valueAddr, source);
645-
mustDeallocBuffer = true;
646-
}
647-
648638
// Initialize the destination.
649639
_swift_convertToAnyHashableIndirect(source, destination,
650640
sourceType, hashableConformance);
651641

652-
// Deallocate the buffer if we used it.
653-
if (mustDeallocBuffer) {
654-
sourceType->deallocateBufferIn(&buffer);
642+
// Destroy the value if requested.
643+
if (flags & DynamicCastFlags::TakeOnSuccess) {
644+
sourceType->vw_destroy(source);
655645
}
656646

657647
// The cast succeeded.
@@ -1932,6 +1922,9 @@ static bool tryDynamicCastBoxedSwiftValue(OpaqueValue *dest,
19321922

19331923
#if !SWIFT_OBJC_INTEROP // __SwiftValue is a native class:
19341924
if (swift_unboxFromSwiftValueWithType(src, dest, targetType)) {
1925+
// Release the source if we need to.
1926+
if (flags & DynamicCastFlags::TakeOnSuccess)
1927+
srcType->vw_destroy(src);
19351928
return true;
19361929
}
19371930
#endif

test/stdlib/AnyHashableCasts.swift.gyb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,16 @@ AnyHashableCasts.test("${valueExpr} as ${coercedType} as? ${castType}") {
118118
}
119119
% end
120120

121+
AnyHashableCasts.test("Casting to AnyHashable doesn't leak") {
122+
do {
123+
let tracked = LifetimeTracked(42)
124+
let anyHashable = AnyHashable(tracked)
125+
let anyObject = anyHashable as AnyObject
126+
_ = anyObject as? AnyHashable
127+
}
128+
expectEqual(LifetimeTracked.instances, 0)
129+
}
130+
121131
#if _runtime(_ObjC)
122132
// A wrapper type around Int that bridges to NSNumber.
123133
struct IntWrapper1: _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {

0 commit comments

Comments
 (0)