[swift-evolution] RFC: Proposed rewrite of Unmanaged<T>

T.J. Usiyan griotspeak at gmail.com
Thu Dec 17 20:23:56 CST 2015

I think I see what you mean about parity. `.object` can be called multiple
times, then? Why not make `release()` slightly more verbose since it should
only be called once anyway? Something along the lines of
`.releaseAndReturnObject` or … something slightly less verbose.

My main point of contention with `.release()` is that it has the *exact*
same name as a method from the MRC strategy. Maybe this is a silly point,
but this overlap could further complicate teaching how ARC works and in
what ways it is based on MRC conventions.  I am not of the opinion that ARC
is fundamentally more difficult to understand than MRC, but I do believe
that it takes a very particular kind of faith now that we don't get to
manually write the retains and releases. This is completely worth it, in my
opinion, but  I want to avoid making it *more* confusing to explain what
ARC doing at compile time.


On Thu, Dec 17, 2015 at 9:13 PM, Dave Abrahams <dabrahams at apple.com> wrote:

> Thanks very much for the quick feedback TJ,
> On Dec 17, 2015, at 5:52 PM, T.J. Usiyan <griotspeak at gmail.com> wrote:
> Hello Dave,
> I like this change and think that it will help clarify the purpose of the
> type. As I was reading, the only concern that I had was the name. Could you
> please provide some of the names that you all have considered
> Honestly, I am sorry to say, we did that exercise almost a month ago and I
> don’t remember the ones we discussed.
> so that we can avoid suggesting the same things? My suggestion is
>     CF*Something*(*arguments…*).retainedObject() // when the result is
> returned at +1
> or
>     CF*Something*(*arguments…*).unretainedObject()    // when the result
> is returned at +0
> on the premise that the important bit of information is whether or not the
> object is already retained. No matter what names are chosen, that is the
> data which determines which method to call. `retainedObject |
> unretainedObject`, `takeRetainedObject | takeUnretainedObject`, or
>  `retained | unretained` all seem like viable options (that you have
> probably considered).
> Some issues with these names:
>    - The “ed/ing” rule
>    <https://swift.org/documentation/api-design-guidelines.html#be-grammatical> makes
>    these names suggest that the accessors are idempotent, but the first one
>    must be called exactly once.  That name should really be an active verb
>    since it is state-changing.
>    - “retainedObject” also suggests that it’s returning some underlying
>    object after retaining it, which is almost the opposite of what that API
>    does… and vice-versa for “unretainedObject"
>    - Also, the object “has been retained” in all cases, or it would have
>    been deallocated.  The question is whether the object would leak if we fail
>    to call release on it
>    - Nothing in these names connect them to what the documentation says
>    about the functions that return Unmanaged, so it’s hard to know which one
>    to call
>    - The second API is objectively safer than the first one (which causes
>    undefined behavior when overused and only leaks when underused).  The API I
>    proposed makes it clear that they are not peers, where yours implies
>    parity—though I am of two minds about the value of representing the lack of
>    parity.
> You may legitimately argue that any of these concerns are unimportant, but
> those are the ones that come up for me.
> TJ
> On Thu, Dec 17, 2015 at 8:37 PM, Dave Abrahams via swift-evolution <
> swift-evolution at swift.org> wrote:
>> Hi Everybody,
>> We’ve been working on a rewrite of the Unmanaged<T> component, and are
>> soliciting comments.  First, a little background:
>>    - Unmanaged
>>    <https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6-ID79> is
>>    primarily used as a return type from imported CoreFoundation functions that
>>    haven’t been annotated with reference-counting semantic information
>>    - A secondary known use-case is as a vehicle for creating a
>>    COpaquePointer containing a reference’s bits, e.g. for when you need to
>>    pass a reference through C APIs that use “void*” as a universal “give me
>>    some info and I’ll give it back to your callback” mechanism.
>>    - We saw several problems with Unmanaged that we wanted to fix:
>>       - It was poorly-named (the reference is managed by *somebody*, we
>>       just aren't representing that management in the type system).
>>       - Its interface was much broader than it needs to be to cover the
>>       use-cases
>>       - The purpose of many of its APIs was unclear
>>       - Its documentation was vague and hard to understand.
>>       - It didn’t establish a maximally-safe usage pattern for handling
>>       the results of un-annotated CoreFoundation functions.
>> The code for the proposed replacement, called UnsafeReference, is here
>> <https://github.com/dabrahams/swift/blob/6eb86b48d150342709da3f3be9c738df23382866/stdlib/public/core/UnsafeReference.swift>,
>> and a commit that updates Swift to use it is here
>> <https://github.com/dabrahams/swift/commit/6eb86b48d150342709da3f3be9c738df23382866>
>> .
>> Maximally Safe Usage
>> The recommended usage pattern for handling an UnsafeReference<T>
>> returned by a function CF*Something* is to always use the T instance
>> produced by one of the forms:
>>     CF*Something*(*arguments…*).release() // when the result is returned
>> at +1
>> or
>>     CF*Something*(*arguments…*).object    // when the result is returned
>> at +0
>> In other words, turn the UnsafeReference<T> into a safe T as quickly as
>> possible, and never store the UnsafeReference<T> in a variable so that
>> it can’t be (mis)used thereafter.
>> Points of Discussion
>> We’re interested in any feedback you might have, but there are a few
>> points we’d especially like to address:
>>    - The name of the release() method has been contentious.
>>       - 👍: Documentation—or naming conventions such as the “create rule
>>       <https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html>”—normally
>>       says something like “you are responsible for releasing the result” in those
>>       cases where release() must be called, so there’s a very direct way
>>       to know which variant of the recommended usage pattern to employ.
>>       - 👎: Some people who are very familiar with existing manual
>>       retain/release programming find the recommended usage pattern really
>>       counter-intuitive because they're “using something after calling release on
>>       it,” which one never does in Objective-C.
>>       - The alternative names we’ve been able to think of so far are
>>       verbose, clumsy, and don’t match up with anything in the documentation of
>>       the called function, so this seems like a really hard naming problem.
>>       Better ideas from the community would be most welcome here.
>>    - We’re not sure about the terminology
>>    <https://github.com/dabrahams/swift/blob/6eb86b48d150342709da3f3be9c738df23382866/stdlib/public/core/UnsafeReference.swift#L27> (Unretained/Retained/Released) used
>>    to precisely describe the semantics of UnsafeReference. We’d like to
>>    know if these terms make sense to you or whether you have better ideas.
>>    - We want to know whether the usage pattern recommended above works
>>    for you.
>>    - We want to know if the API is sufficiently broad or if there are
>>    things you currently get—and need—from Unmanaged that we’ve left out.
>> Thanks in advance,
>> -Dave
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> -Dave
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151217/0d6753cd/attachment.html>

More information about the swift-evolution mailing list