> On Jun 9, 2016, at 4:15 PM, Jordan Rose <[email protected]> wrote:
>> On Jun 9, 2016, at 16:10, John McCall <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>>> On Jun 9, 2016, at 3:43 PM, Jordan Rose via swift-evolution 
>>> <[email protected] <mailto:[email protected]>> wrote:
>>> 
>>> I'm against this for library evolution reasons: if someone releases a 
>>> version of their library that has a non-escaping closure and later 
>>> discovers it needs to be escaping, they can't change it.
>>> 
>>> IIRC the counterpoint to this is that people were probably implicitly 
>>> relying on it being non-escaping already, and that there aren't many cases 
>>> where you'd want to do this anyway.
>> 
>> Right.  APIs are already semantically constrained in how they're allowed to 
>> use their closure arguments.  Closure arguments inject arbitrary code, with 
>> arbitrary data access, into the callee; as a rule, the caller must know how 
>> the callee intends to use the closure, or its semantics will be grossly 
>> violated.  You can't re-implement an existing API that always synchronously 
>> sub-invokes a closure to instead call the closure asynchronously or 
>> concurrently because it is completely reasonable for the caller to pass a 
>> closure that relies on being called synchronously or from at most one thread 
>> at once and/or within a fixed range of time.  For example, the closure may 
>> modify a captured local variable, or it may it use a network connection that 
>> will be closed after the API returns.  APIs that want to do this sort of 
>> thing have to reserve the right to do that (and even then, they may have 
>> binary compatibility limitations), in which case it is totally reasonable to 
>> expect them to express that in the type.
> 
> I don't buy this. If someone publishes an API that executes something on the 
> current thread today and on a background queue tomorrow, that's totally fine 
> if they never promised it would execute on a particular thread. If a client 
> accidentally assumes an implementation detail is part of the interface, 
> that's their fault, and always has been…though the library author might 
> decide to continue supporting their use in the future in the interest of not 
> making waves.

Synchronous-but-off-thread is kind of a special case because it's only 
observable in very special ways, e.g. thread-local storage and the current 
thread ID.  Concurrent (e.g. calling an enumeration callback on multiple 
threads simultaneously) and asynchronous (even if it comes back to the current 
queue) are absolutely something you have to know about as a caller.  It is 
deeply unreasonable for an API to suddenly start invoking a closure 
asynchronously when it hasn't documented that it might do that (perhaps 
implicitly by obviously following some well-known pattern, e.g. calling the 
closure a completion handler); that would be a huge semantic and 
binary-compatibility problem.

Another line of argument: flipping the default is a huge boon to static 
analysis because (1) closure execution becomes ordered by default and (2) an 
escaping closure becomes a much more meaningful hint.  For example, consider a 
use-after-free static analysis that sees this code:

  func foo(ptr: UnsafeMutablePointer<Int>) {
    bar { ptr[5] = 0 }
    ptr.dealloc()
  }

This analysis is currently blocked by this abstraction unless it knows 
something specific about 'bar'.  If 'bar' marks its argument @noescape, then 
the analysis knows that this is safe; but if not, the analysis is unlikely to 
be willing to warn because it's quite likely that 'bar' is just missing an 
annotation and does not actually execute its closure asynchronously.  However, 
if the polarity is flipped, the analysis wins on both ends: it can prove 
correctness in many more cases by default, and the cases where the closure 
actually escapes become much more suspicious, probably enough to warn by 
default.

John.
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to