Skip to content

Commit 4b3c821

Browse files
authored
Merge pull request swiftlang#20836 from mikeash/anyhashable-cast-leak-fix
[Runtime] Fix leak when casting to AnyHashable.
2 parents 0ffc988 + f1f8396 commit 4b3c821

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
@@ -123,6 +123,16 @@ AnyHashableCasts.test("${valueExpr} as ${coercedType} as? ${castType}") {
123123
}
124124
% end
125125

126+
AnyHashableCasts.test("Casting to AnyHashable doesn't leak") {
127+
do {
128+
let tracked = LifetimeTracked(42)
129+
let anyHashable = AnyHashable(tracked)
130+
let anyObject = anyHashable as AnyObject
131+
_ = anyObject as? AnyHashable
132+
}
133+
expectEqual(LifetimeTracked.instances, 0)
134+
}
135+
126136
#if _runtime(_ObjC)
127137
// A wrapper type around Int that bridges to NSNumber.
128138
struct IntWrapper1: _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {

0 commit comments

Comments
 (0)