@@ -34,7 +34,15 @@ public struct Unmanaged<Instance: AnyObject> {
34
34
public static func fromOpaque(
35
35
@_nonEphemeral _ value: UnsafeRawPointer
36
36
) -> Unmanaged {
37
- return Unmanaged ( _private: unsafeBitCast ( value, to: Instance . self) )
37
+ // NOTE: `value` is allowed to represent a dangling reference, so
38
+ // this function must not ever try to dereference it. For
39
+ // example, this function must NOT use the init(_private:) initializer
40
+ // because doing so requires materializing a strong reference to 'Instance'.
41
+ // This materialization would be enough to convince the compiler to add
42
+ // retain/releases which must be avoided for the opaque pointer functions.
43
+ // 'Unmanaged<Instance>' is layout compatible with 'UnsafeRawPointer' and
44
+ // casting to that will not attempt to retain the reference held at 'value'.
45
+ unsafeBitCast ( value, to: Unmanaged< Instance> . self )
38
46
}
39
47
40
48
/// Unsafely converts an unmanaged class reference to a pointer.
@@ -48,7 +56,13 @@ public struct Unmanaged<Instance: AnyObject> {
48
56
/// - Returns: An opaque pointer to the value of this unmanaged reference.
49
57
@_transparent
50
58
public func toOpaque( ) -> UnsafeMutableRawPointer {
51
- return unsafeBitCast ( _value, to: UnsafeMutableRawPointer . self)
59
+ // NOTE: `self` is allowed to be a dangling reference.
60
+ // Therefore, this function must not unsafeBitCast '_value' because
61
+ // that will get a strong reference temporary value that the compiler will
62
+ // try to retain/release. Use 'self' to avoid this. 'Unmanaged<Instance>' is
63
+ // layout compatible with 'UnsafeRawPointer' and casting from that will not
64
+ // attempt to retain the reference held at '_value'.
65
+ unsafeBitCast ( self , to: UnsafeMutableRawPointer . self)
52
66
}
53
67
54
68
/// Creates an unmanaged reference with an unbalanced retain.
0 commit comments