[swift-evolution] /*Let it be*/ func() -> @discardable Bool {} /*Rather Than*/ @discardableResult func() -> Bool {}

Xiaodi Wu xiaodi.wu at gmail.com
Wed Oct 18 22:04:19 CDT 2017

On Wed, Oct 18, 2017 at 9:29 PM, Brent Royal-Gordon <brent at architechies.com>

> On Oct 9, 2017, at 11:02 PM, Xiaodi Wu via swift-evolution <
> swift-evolution at swift.org> wrote:
> This idea was discussed long ago and the present design was selected.
> But this design was discussed in the proposal as a "future direction",
> because @discardableResult was chosen partially because it was easier to
> implement. It says so [in the proposal][1]. This is why we write formal
> proposals, Xiaodi—so we remember why we made the decisions we made.

You're right that it was chosen in part because it was easier to implement.

But this does not at all mean that "@discardable" is the blessed future
direction; whether it is wise ever to adopt the "@discardable" design was
not thoroughly evaluated--it was simply decided that, for Swift 3,
@discardableResult was preferable to @discardable in the totality of things.

In my view, this means the "@discardable" idea needs to meet a higher bar
than a never-before presented idea, not a lower one.

* * *
> Now, the proposal specifically suggests we delay `@discardable` "until
> such time as there's a strong motivation to use such an approach". Do we
> have such a motivation?
> I actually think we do (although it may not be strong enough). Currently,
> we have two types—`Void` (as well as optionals, of any depth, wrapping
> `Void`) and `Never`—which are "implicitly discardable". That is, you don't
> need to mark a function which returns those types with
> `@discardableResult`; it inherently is. This is currently handled with [an
> ad-hoc test][2], but I think we should consider strengthening and opening
> up this mechanism.
> Why? Because there are other types we would like to be implicitly
> discardable. You can already make an argument for types like `Array<Void>`,
> but concurrency will bring types like `Future<Void>` which could get pretty
> strong benefits from it. Since we're planning to leave a lot of async stuff
> to userspace, there ought to be a userspace way to mark types as implicitly
> discardable. And if discardability stems from the type system, it's pretty
> natural to make ad-hoc discardibility a property attached to the type, too.
> (We could then mark `Never` with @discardable, make tuples discardable
> unless one of their elements is not discardable, make optionals discardable
> if the type they wrap is discardable, and—et voilà!—we have a nice, general
> language feature with as little magic as we can manage.)
> [1]: https://github.com/apple/swift-evolution/blob/master/
> proposals/0047-nonvoid-warn.md#future-directions
> [2]: https://github.com/apple/swift/blob/e907031d3d4555e917ca3ad7fffeac
> 7f580331a0/lib/Sema/TypeCheckStmt.cpp#L991

I am not sure this is entirely wise, for a few reasons.

a) I sure don't know why you'd want to return `Void?`, but if you do, it
doesn't follow that it should be discardable simply because `Void` is
discardable. It may well be so, or it may be (for some odd reason) that
it's the return type of a pure function that certainly shouldn't be

b) Based on (a), I don't think that types composed of discardable types are
therefore discardable. I need to think this through further.

c) If you reject (b), then this brings up a larger issue.
`@discardableResult` is an attribute of the function; here, you're saying
that not only should the _spelling_ be moved to the other side of the
function arrow, but that the attribute should apply to the type. Would we
then have to invent a new overriding attribute for functions that return
`@discardable` types which don't want their return value to be discardable?
Like, a `@nondiscardableResult func foo() -> Void? /* implicitly
discardable type */`? I think this further demonstrates how it's not really
the type but the function that we want to annotate.

d) Does a class that override a `@discardable` type inherit that
annotation? If not, they it's kind of a weird exception to the inheritance
thing, no? If so, then we'd need a @nondiscardable annotation to do
type-level overrides of @discardable.

e) `Never` was explicitly designed to have no magic that any other
uninhabited enum would not get. To stick with this design, every enum
without any cases would have to be implicitly `@discardable`. This might be

f) Speaking of enums: if types are discardable, then some errors are
discardable. By contrast, we do not currently have a `@discardableError`
annotation. What does it mean if a function throws a "discardable error"?
Can we choose not to catch it?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171018/3ab4e0d0/attachment.html>

More information about the swift-evolution mailing list