Hi Gwendal,

Nice writeup. So I see that you recognise how this extra specification will 
complicate (while also facilitate) things. And I also see that you're a 
co-author of the proposal. So I'm more than happy if you can squeeze this extra 
into it.

However reading your example code, I had to squint to see—without the 
compiler's squiggly red aid—what all the problematic cases are.

1) Is it obvious to everybody why you can't always use `x` in the end of Cases 
2 and 4? For example, with `if—else` you MUST initialise the variable or escape 
its scope in all branches; you can't just write the following to complete the 
initialisation later:

    let x: Int
    if cond { x = 1 }
    // ...
    if !cond { x = 2 } // too late!

2) Should Cases 2 and 4 be made illegal? The requirement could then be that all 
`catch` blocks either:
2.a) initialise another value for `x`, or
2.b) escape the scope using `throw`, `return`, `fatalError`, whatnot…

3) If you consider including this addition to the proposal, it might also help 
other reviewers if you explained how the compiler will be able to help the 
programmer write a valid program. E.g. what would the error messages about 
partially initialised variables look like? And where and when would they 
appear? Could the compiler suggest certain fixits? Etc.

So, I'm all +1 and very glad if you can make it! (But also somewhat sceptical 
whether it could get accepted.)

— Pyry

> On 04 May 2016, at 12:24, Gwendal Roué <[email protected]> wrote:
> 
> I quite expect being able to throw out of a @noescape(once) block. Maybe the 
> sentence "it must not be executed on any path that throws" should be removed 
> from the proposal, should it have the implications you describe.
> 
> Here is below what I expect this proposal to allow. So you see one 
> problematic case?
> 
>       // Function which rethrows closure errors:
>       func f1(closure: @noescape(once) () throws -> ()) rethrows {
>               try closure()
>       }
> 
>       // Function which may throw before, inside, or after the closure:
>       func f2(closure: @noescape(once) () throws -> ()) throws {
>               try mayFailBefore()
>               try closure()
>               try mayFailAfter()
>       }
>       
>       // Support function
>       func getX() throws -> Int { return 1 }
>       
> Case 1:
> 
>       let x: Int
>       f1 {
>               x = 1
>               // use x
>       }
>       // use x
>       
> Case 2:
> 
>       let x: Int
>       do {
>               try f1 {
>                       x = try getX()
>                       // use x
>               }
>               // use x
>       } catch {
>               // can't use x
>       }
>       // can't use x
>       
> Case 3:
> 
>       let x: Int
>       do {
>               try f1 {
>                       x = try getX()
>                       // use x
>               }
>               // use x
>       } catch {
>               x = 1
>       }
>       // use x
>       
> Case 4:
> 
>       let x: Int
>       do {
>               try f2 {
>                       x = try getX()
>                       // use x
>               }
>               // use x
>       } catch {
>               // can't use x
>       }
>       // can't use x
> 
> Case 5:
> 
>       let x: Int
>       do {
>               try f2 {
>                       x = try getX()
>                       // use x
>               }
>               // use x
>       } catch {
>               x = 1
>       }
>       // use x
> 
> Gwendal Roué
> 


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

Reply via email to