[swift-evolution] Best way to handle escaping function that might throw
Howard Lovatt
howard.lovatt at gmail.com
Thu Jan 12 18:28:01 CST 2017
@Slava,
I'm imagining that the compiler does much the same as Anton suggested, e.g.
Anton's:
struct FStore<E: Error> {
let f: () throws<E> -> Void
init(_ f: @escaping () throws<E> -> Void) { self.f = f }
func call() throws<E> { try f() }
}
Is much the same as my:
struct FStore {
let f: () throws -> Void
init(_ f: @escaping () throws -> Void) { self.f = f }
func call() throws { try f() }
}
>From a compiler point of view.
The idea is that the compiler reuses some of its existing generic's
infrastructure. The main differences between my proposal and Anton's is
that because mine doesn't use a typed throw, E can only be 'AnyError' (any
type that implements Error) or Never, and E is not explicit. The
throws/rethrows distinction just becomes a compiler optimization in both
cases.
-- Howard.
On 13 January 2017 at 10:42, Slava Pestov <spestov at apple.com> wrote:
>
> On Jan 11, 2017, at 2:02 PM, Howard Lovatt via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Another possibility, other than generics, would be to drop rethrows all
> together and have the compiler infer if a throw is possible or not,
> including:
>
> struct FStore {
> let f: () throws -> Void
> func call() throws { try f() }
> }
>
> The compiler can make two versions, one if f can throw and one if it
> definitely doesn't.
>
>
> It seems that this approach is impractical, because you either have to
> compile two versions of every function, or make all function bodies
> available for inlining, which is a non-starter for a stable ABI.
>
> Slava
>
>
> Just a thought.
>
> On Tue, 10 Jan 2017 at 4:29 pm, Jacob Bandes-Storch <jtbandes at gmail.com>
> wrote:
>
>> Moving to swift-users list.
>>
>> No, there's no way to do this today. The point of rethrows is that within
>> one call site, "f(block)" can be treated as throwing if the block throws,
>> or not throwing if the block doesn't throw. In your example, once the
>> FStore object is constructed, the information about the original passed-in
>> function is lost, so the caller has no way to know whether call() can throw
>> or not.
>>
>> If this *were* possible, the information would somehow need to be encoded
>> in the type system when creating FStore(f: block). That would require
>> something like dependent typing, or generic-param-based-rethrows, e.g.
>>
>> struct FStore<T: () throws -> Void> { // made-up syntax
>> let f: T
>> func call() rethrows(T) { try f() } // throws-ness of this function
>> depends on throws-ness of T
>> }
>>
>>
>>
>> On Mon, Jan 9, 2017 at 9:21 PM, Howard Lovatt via swift-evolution <swift-
>> evolution at swift.org> wrote:
>>
>> Hi,
>>
>> If I have an escaping function that I store and then call, I need to
>> declare the calling function as throwing, not rethrowing. EG:
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> struct FStore {
>> let f: () throws -> Void
>> init(f: @escaping () throws -> Void) { self.f = f }
>> func call() throws { try f() } // Can't put rethrows here - have
>> to use throws
>> }
>> Is there a better solution?
>>
>> Thanks for any suggestions,
>>
>> -- Howard.
>>
>>
>>
>>
>>
>> _______________________________________________
>>
>>
>> swift-evolution mailing list
>>
>>
>> swift-evolution at swift.org
>>
>>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>>
>>
>>
>>
>> --
> -- Howard.
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170113/5335b374/attachment.html>
More information about the swift-evolution
mailing list