@@ -34,7 +34,15 @@ public struct Unmanaged<Instance: AnyObject> {
3434 public static func fromOpaque(
3535 @_nonEphemeral _ value: UnsafeRawPointer
3636 ) -> 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 )
3846 }
3947
4048 /// Unsafely converts an unmanaged class reference to a pointer.
@@ -48,7 +56,13 @@ public struct Unmanaged<Instance: AnyObject> {
4856 /// - Returns: An opaque pointer to the value of this unmanaged reference.
4957 @_transparent
5058 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)
5266 }
5367
5468 /// Creates an unmanaged reference with an unbalanced retain.
0 commit comments