Intended behavior with @discardableResult?

In the following snippet, I expect to be able to discard the return value after invoking bar, but the compiler even allows me to discard a reference to the function, which makes no sense to me.

@discardableResult func baz() -> Int {
    return 0
}

class Foo {
    @discardableResult func bar() -> Int {
        return 0
    }

    func test() {
        self.bar()
        self.bar // I'd expect an error here

        baz()
        baz // I do get an error here as expected
    }
}

This is also inconsistent with non-method functions: for the free function baz, the compiler generates an error:

Expression resolves to an unused function

2 Likes

I don't think this is intended, probably a bug.

Yes, please do file this at https://bugs.swift.org!

I am able to reproduce this without the @discardableResult attribute as well (Swift 4.2/Xcode 10.1 playgrounds)

I am able to reproduce this without the @discardableResult attribute as well (Swift 4.2/Xcode 10.1 playgrounds)

That's because in a playground nothing is ever really discarded but always printed to the sidebar.

2 Likes

Ah ok. Seems like the DeclRefExpr we want (i.e. bar) is being wrapped in a DotSyntaxCallExpr node (makes sense as we're doing self.foo), hence why the error is missing. Here's a PR: [Typechecker] Fix an issue with @discardableResult error not being emitted by theblixguy · Pull Request #22518 · apple/swift · GitHub

Thanks for the quick fix. The error is not being emitted if I leave out the self. too though. Does your PR address this as well?

I would test it myself, but I never built the Swift compiler locally — I might look into that tomorrow.

Yes it does. In the other case, it gets wrapped in an implicit DotSyntaxCallExpr.

3 Likes