Suppress unused result warnings on try? if attempted statement does not return


(James Froggatt) #1

More generally, this is the issue of whether the automatic discardability of Void should be extended to Optional<Void>. This could also apply to the result of optional chaining.

EG:
observer?.update() //returns ()?

compared to:
if let unwrapped = observer {
    unwrapped.update() //returns ()
}

Since ()? (or Void?) is almost certainly a side-effect of optional chaining of some form, I'd be in favour of this extension to the rule.

As an interesting side note, the counter-point to this change I can think of is one of symmetry, potentially relevant in some high-level generic code. Failable functions often follow the pattern of returning an Optional, which is nil on failure. Extending this rule to, for example, an in-place load() function, one may consider returning ()? to indicate whether the function was successful. This would be deliberate use of Optional<()>, and so it would make sense not to make this particular result discardable, which would be impossible with this change.

The precedent of languages without optionals and a real Void/Unit type has been established, which is to return a Bool value to indicate success, and if this weren't such a fundamental expectation, it's arguable ()? may actually be clearer in these cases: load() -> Bool could be read as a function which loads a Bool value, whereas load() -> ()? is unambiguous.

While this is unlikely to become an established convention, I love that Swift is able to make such ideas possible. :slight_smile:
Just the simple things which do away with implementation-driven corner cases in favour of a reliable, clear set of rules, really make the language more powerful.

------------ Begin Message ------------
Group: gmane.comp.lang.swift.evolution
MsgID: <B04DCF76-0AA6-4E80-9930-04E1B710E9A0@icloud.com>

I propose that the compiler warnings for unused results are removed from try? if the statement being ‘tried’ does not return itself. This is inline with how try works and although try? does have a possible return value itself (nil) the warning isn’t adding/helping any if the result is either going to be nil or void.

When try? is used in this way, it is essentially the caller saying they don’t care if the operation fails and any consequences of that failure will be handled later on.

I have a slightly contrived example here on gist of where this could be useful https://gist.github.com/joncottonskyuk/abc6caad8be137193d4e1e58cc8d2e06

basically, in the person model, I don’t always care if the emailAddress is set, but in some cases I do, to differentiate between the two use cases, the caller can choose to use either try when they do care and want to handle the specific error, or try? if they don’t care about the failure and just want to carry on with the usual execution path.

The alternative is to just leave this as it is and the caller must then use _ = try? … to suppress the warnings. However, whilst _ = is very useful for suppressing this warning in most cases, as it shows intent for future maintainers of the code, in this case I don’t think it really adds any value. If the statement being attempted does not return itself then you are left with no choice but to assign to nothing to suppress the warning as opposed to assigning to some local reference and then just throwing that away.

···

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

------------- End Message -------------

From James F


(Alex Hoppen) #2

I discussed the same issue in a WWDC lab with Doug yesterday and we came to the conclusion that warnings about unused return values of type Optional<Void> were a bug. The basic line of argumentation was that if you have

class Foo {
  func bar() {}
}

then

foo?.bar() returns Optional<Void> but does not warn about an unused result, which is totally expected behaviour.

It feels inconsistent that this behaviour differs if the return value of Optional<Void> is used in a more complicated expression, e.g.

true ? foo?.bar() : foo?.bar()

Hence we decided that Optional<Void> simply shouldn't generate any warnings about unused results. Note that this does not prevent the user of such an API to still check the result, if he wants to do so.

Implementation of this change is pending in this PR: https://github.com/apple/swift/pull/3057.

– Alex

···

On 17 Jun 2016, at 18:26, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

More generally, this is the issue of whether the automatic discardability of Void should be extended to Optional<Void>. This could also apply to the result of optional chaining.

EG:
observer?.update() //returns ()?

compared to:
if let unwrapped = observer {
   unwrapped.update() //returns ()
}

Since ()? (or Void?) is almost certainly a side-effect of optional chaining of some form, I'd be in favour of this extension to the rule.

As an interesting side note, the counter-point to this change I can think of is one of symmetry, potentially relevant in some high-level generic code. Failable functions often follow the pattern of returning an Optional, which is nil on failure. Extending this rule to, for example, an in-place load() function, one may consider returning ()? to indicate whether the function was successful. This would be deliberate use of Optional<()>, and so it would make sense not to make this particular result discardable, which would be impossible with this change.

The precedent of languages without optionals and a real Void/Unit type has been established, which is to return a Bool value to indicate success, and if this weren't such a fundamental expectation, it's arguable ()? may actually be clearer in these cases: load() -> Bool could be read as a function which loads a Bool value, whereas load() -> ()? is unambiguous.

While this is unlikely to become an established convention, I love that Swift is able to make such ideas possible. :slight_smile:
Just the simple things which do away with implementation-driven corner cases in favour of a reliable, clear set of rules, really make the language more powerful.

------------ Begin Message ------------
Group: gmane.comp.lang.swift.evolution
MsgID: <B04DCF76-0AA6-4E80-9930-04E1B710E9A0@icloud.com>

I propose that the compiler warnings for unused results are removed from try? if the statement being ‘tried’ does not return itself. This is inline with how try works and although try? does have a possible return value itself (nil) the warning isn’t adding/helping any if the result is either going to be nil or void.

When try? is used in this way, it is essentially the caller saying they don’t care if the operation fails and any consequences of that failure will be handled later on.

I have a slightly contrived example here on gist of where this could be useful https://gist.github.com/joncottonskyuk/abc6caad8be137193d4e1e58cc8d2e06

basically, in the person model, I don’t always care if the emailAddress is set, but in some cases I do, to differentiate between the two use cases, the caller can choose to use either try when they do care and want to handle the specific error, or try? if they don’t care about the failure and just want to carry on with the usual execution path.

The alternative is to just leave this as it is and the caller must then use _ = try? … to suppress the warnings. However, whilst _ = is very useful for suppressing this warning in most cases, as it shows intent for future maintainers of the code, in this case I don’t think it really adds any value. If the statement being attempted does not return itself then you are left with no choice but to assign to nothing to suppress the warning as opposed to assigning to some local reference and then just throwing that away.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

------------- End Message -------------

From James F
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution