Skip to content

Commit 314cf64

Browse files
committed
[Runtime] Fix leak when casting to AnyHashable.
_dynamicCastToAnyHashable assumed that _swift_convertToAnyHashableIndirect takes its argument at +1, but that is no longer the case. rdar://problem/44686587
1 parent af392c4 commit 314cf64

File tree

2 files changed

+13
-13
lines changed

2 files changed

+13
-13
lines changed

stdlib/public/runtime/Casting.cpp

Lines changed: 3 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.

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)