> On Nov 12, 2017, at 11:11 PM, Brent Royal-Gordon via swift-evolution > <swift-evolution@swift.org> wrote: > >> On Nov 12, 2017, at 12:55 AM, David Hart via swift-evolution >> <swift-evolution@swift.org> wrote: >> >> Hello evolution folks, >> >> After the positive feedback on the idea of improving capturing semantics of >> local functions, Alex Lynch and I worked on a proposal. Please let us know >> if you have any feedback: >> >> https://github.com/hartbit/swift-evolution/blob/improving-capturing-semantics-of-local-functions/proposals/XXXX-improve-capture-semantics-of-local-functions.md > > So, quoting the proposal: > >> First of all, this proposal suggests extending the requirement of the self. >> prefix to local functions, but only if the local function is used as or used >> inside an escaping closure. > > I don't love that the use of a function many lines away can cause errors in > that closure. There's a "spooky action-at-a-distance" quality to this > behavior that I don't like. > > The best idea I have is to require local functions to be annotated with > `@escaping` if they're to be used in an escaping closure: > > func foo() { > // `local1` is nonescaping since it isn't marked with the @escaping > attribute. > func local1() { > bar() > } > local1() // OK, direct call > { local1() }() // OK, closure is nonescaping > DispatchQueue.main.async(execute: local1) // error: passing > non-escaping function 'local2' to function expecting an @escaping closure > DispatchQueue.main.async { local1() } // error: closure use > of non-escaping function 'local2' may allow it to escape > > @escaping func local2() { > bar() // error: call to method 'bar' in escaping > local function requires explicit 'self.' to make capture semantics explicit > } > > @escaping func local3() { > self. bar() // OK, explicit `self` > } > DispatchQueue.main.async(execute: local3) // OK, escaping function > DispatchQueue.main.async { local3() } // OK, escaping closure > } > > func bar() { > print("bar") > } > > But this would be quite source-breaking. (Maybe it could be introduced as a > warning first?)
I like the idea of requiring @escaping to be explicit on local funcs, but I'm worried that it might be too onerous; after all, we infer @escapingness on closures quite successfully. At the same time, I agree that applying semantic rules based on how the func is used, potentially much later in the function, is really spooky. I don't have a great alternative right now. Random note: we currently infer non-escapingness for local funcs that capture ``inout``s, since those cannot be allowed to escape. In fact, this is the only way to make a local function non-escaping at all. John. > >> Secondly, this proposal suggests allowing the same capture list syntax from >> closures in local functions. Capture lists would still be invalid in >> top-level and member functions. > > > I think this is a good idea, but I don't like bringing the already weird use > of `in` to actual functions. > > By analogy with the current closure syntax, the capture list ought to go > somewhere before the parameter list, in one of these slots: > > 1. func fn<T>[foo, bar](param: T) throws -> T where T: Equatable { … } > 2. func fn[foo, bar]<T>(param: T) throws -> T where T: Equatable { … } > 3. func [foo, bar] fn<T>(param: T) throws -> T where T: Equatable { … } > 4. [foo, bar] func fn<T>(param: T) throws -> T where T: Equatable { … } > > Of these options, I actually think #4 reads best; 1 and 2 are very cluttered, > and 3 just seems weird. But it seems like the one that would be easiest to > misparse. > > -- > Brent Royal-Gordon > Architechies > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution