> On May 16, 2017, at 17:37, John McCall <[email protected]> wrote:
>
>>
>> On May 16, 2017, at 5:20 PM, Jordan Rose <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>>
>>> On May 15, 2017, at 20:29, John McCall <[email protected]
>>> <mailto:[email protected]>> wrote:
>>>
>>>>
>>>> On May 15, 2017, at 9:00 PM, Jordan Rose <[email protected]
>>>> <mailto:[email protected]>> wrote:
>>>>
>>>> [Proposal:
>>>> https://github.com/apple/swift-evolution/blob/master/proposals/0176-enforce-exclusive-access-to-memory.md
>>>>
>>>> <https://github.com/apple/swift-evolution/blob/master/proposals/0176-enforce-exclusive-access-to-memory.md>]
>>>>
>>>> I have severe concerns about these revisions because they make
>>>> withoutActuallyEscaping harder to reason about.
>>>>
>>>> + - Programmers using ``withoutActuallyEscaping`` should take
>>>> + care not to allow the result to be recursively invoked.
>>>>
>>>> +[…] if they are certain that their code will
>>>> +not violate the NRR, use ``withoutActuallyEscaping`` to disable
>>>> +the NPCR check.
>>>>
>>>> I think this constitutes a violation of the user model for
>>>> withoutActuallyEscaping, because withoutActuallyEscaping hasn't
>>>> historically meant withoutBeingReentrant. The proposal "should take care"
>>>> is a very mild way of saying we're introducing a new rule under which the
>>>> compiler can silently do something different than what you wrote (with no
>>>> "unsafe" in sight). Similarly, using withoutActuallyEscaping to mean
>>>> withoutActuallyViolatingExclusivity seems like it'll come back to haunt
>>>> us, the kind of thing where people ask on Stack Overflow why the Swift
>>>> people didn't design something that said what it did.
>>>
>>> You're right that it's a silent change in the semantics of
>>> withoutActuallyEscaping. I'm comfortable with that because of the ways in
>>> which I expect withoutActuallyEscaping to be used, but I can see why
>>> someone wouldn't be.
>>>
>>>> When I first brought this up on an Apple-internal list, John let me know
>>>> that we could introduce checking for it. This helps assuage my concerns
>>>> quite a bit, but I'm not sure how we would do so without modifying the
>>>> original closure, and if we can modify the original closure I'm not sure
>>>> we've saved anything over proper dynamic checking.
>>>
>>> withoutActuallyEscaping does not actually promise to return exactly the
>>> original closure (which is not a user-detectable property of the closure
>>> value), just something semantically equivalent. In particular, we can wrap
>>> it in a thunk that (say) dynamically asserts that the closure is not called
>>> re-entrantly.
>>>
>>> We may need withoutActuallyEscaping to add a thunk anyway, because I don't
>>> know that we actually want to guarantee that the context pointer of a
>>> non-escaping closure is retainable; it costs us unnecessary set-up code in
>>> the caller.
>>
>> I thought of this too, but it doesn't handle the case where you use
>> withoutActuallyEscaping and use the original closure directly from within
>> the block. Maybe we can forbid that, though—it seems extra-rare. Does it
>> make sense to add that as an extra rule in this proposal?
>
> Well, you'd have to integrate the check with some sort of record-keeping done
> by the original closures. I'm not entirely sure what that record-keeping
> would look like off-hand.
>
> I'm not sure what you're proposing to disallow here. I don't think we should
> add any extra restrictions in order to avoid problems with unfortunate uses
> of withoutActuallyEscaping, though.
Here's a small, currently-legal, re-entrant case that only calls the wrapped
function once.
var global: (() -> Void)?
func problem(_ fn: () -> Void) {
withoutActuallyEscaping(fn) { wrappedFn in
global = wrappedFn
fn() // note: not wrappedFn
}
}
func test() {
var local = 0
problem() {
local += 1
if let callback = global {
global = nil
callback()
}
print(local)
}
}
test()
We could prevent this by saying it's not legal to refer to 'fn' inside the
callback for withoutActuallyEscaping, and you have to use 'wrappedFn' instead.
Jordan_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution