try? shouldn't work on non-method-call

This is a warning right now — do you think it should be an error?

Slavas-MacBook-Pro:~ slava$ cat ttt.swift
func f() {}

func g() {
try f()
try? f()
}

Slavas-MacBook-Pro:~ slava$ swiftc ttt.swift
ttt.swift:4:3: warning: no calls to throwing functions occur within 'try' expression
try f()
^
ttt.swift:5:8: warning: no calls to throwing functions occur within 'try' expression
try? f()
      ^

IMHO at least, this should be an error. As a side note I do think that try should have greater precedence than as, even though this does potentially limit calls that would use only one try on a series of throwing statement that can be handled using parentheses. The benefit is that try is probably called in the vast majority of situations (that’s my experience at least) on a single throw statement and having it have higher precedance would avoid some surprises as most developers probably already assume that try wil be executed before as.

— Davor

The design of ordinary 'try' and 'try!' are that they includes the entire expression to the right, spanning casts and other binary operators, and I think that's clearly the right rule for them. It's not as clearly right for 'try?', but making 'try' and 'try?' be parsed differently would be horribly confusing.

John.

···

On Aug 18, 2016, at 10:15 AM, Davor Jankolija via swift-evolution <swift-evolution@swift.org> wrote:

This is a warning right now — do you think it should be an error?

Slavas-MacBook-Pro:~ slava$ cat ttt.swift
func f() {}

func g() {
try f()
try? f()
}

Slavas-MacBook-Pro:~ slava$ swiftc ttt.swift
ttt.swift:4:3: warning: no calls to throwing functions occur within 'try' expression
try f()
^
ttt.swift:5:8: warning: no calls to throwing functions occur within 'try' expression
try? f()
     ^

IMHO at least, this should be an error. As a side note I do think that try should have greater precedence than as, even though this does potentially limit calls that would use only one try on a series of throwing statement that can be handled using parentheses. The benefit is that try is probably called in the vast majority of situations (that’s my experience at least) on a single throw statement and having it have higher precedance would avoid some surprises as most developers probably already assume that try wil be executed before as.

I see what you’re saying and I have to agree for the most part, it’s just that now you basically get a ‘try’ executed on the result of the ‘as?’ expression, which although is correct now that I look at your explanation is somewhat unintuitive, again this is just my opinion.

P.S.
It would seem then, that the best way and probably simplest is to remember and place parentheses around the ‘try call()’ and then attempt a cast?

— Davor

···

On 18 Aug 2016, at 19:46, John McCall <rjmccall@apple.com> wrote:

On Aug 18, 2016, at 10:15 AM, Davor Jankolija via swift-evolution <swift-evolution@swift.org> wrote:

This is a warning right now — do you think it should be an error?

Slavas-MacBook-Pro:~ slava$ cat ttt.swift
func f() {}

func g() {
try f()
try? f()
}

Slavas-MacBook-Pro:~ slava$ swiftc ttt.swift
ttt.swift:4:3: warning: no calls to throwing functions occur within 'try' expression
try f()
^
ttt.swift:5:8: warning: no calls to throwing functions occur within 'try' expression
try? f()
    ^

IMHO at least, this should be an error. As a side note I do think that try should have greater precedence than as, even though this does potentially limit calls that would use only one try on a series of throwing statement that can be handled using parentheses. The benefit is that try is probably called in the vast majority of situations (that’s my experience at least) on a single throw statement and having it have higher precedance would avoid some surprises as most developers probably already assume that try wil be executed before as.

The design of ordinary 'try' and 'try!' are that they includes the entire expression to the right, spanning casts and other binary operators, and I think that's clearly the right rule for them. It's not as clearly right for 'try?', but making 'try' and 'try?' be parsed differently would be horribly confusing.

John.

In your case, yes, I think the right solution is probably to parenthesize the try?.

John.

···

On Aug 18, 2016, at 10:56 AM, Davor Jankolija <djankolija@gmail.com> wrote:

On 18 Aug 2016, at 19:46, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Aug 18, 2016, at 10:15 AM, Davor Jankolija via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This is a warning right now — do you think it should be an error?

Slavas-MacBook-Pro:~ slava$ cat ttt.swift
func f() {}

func g() {
try f()
try? f()
}

Slavas-MacBook-Pro:~ slava$ swiftc ttt.swift
ttt.swift:4:3: warning: no calls to throwing functions occur within 'try' expression
try f()
^
ttt.swift:5:8: warning: no calls to throwing functions occur within 'try' expression
try? f()
    ^

IMHO at least, this should be an error. As a side note I do think that try should have greater precedence than as, even though this does potentially limit calls that would use only one try on a series of throwing statement that can be handled using parentheses. The benefit is that try is probably called in the vast majority of situations (that’s my experience at least) on a single throw statement and having it have higher precedance would avoid some surprises as most developers probably already assume that try wil be executed before as.

The design of ordinary 'try' and 'try!' are that they includes the entire expression to the right, spanning casts and other binary operators, and I think that's clearly the right rule for them. It's not as clearly right for 'try?', but making 'try' and 'try?' be parsed differently would be horribly confusing.

John.

I see what you’re saying and I have to agree for the most part, it’s just that now you basically get a ‘try’ executed on the result of the ‘as?’ expression, which although is correct now that I look at your explanation is somewhat unintuitive, again this is just my opinion.

P.S.
It would seem then, that the best way and probably simplest is to remember and place parentheses around the ‘try call()’ and then attempt a cast?