How should we fix SR-5719 for Swift 5?

Greetings community, last year I filed a bug report about an issue with @autoclosure which allows closure forwarding as long as it’s another autoclosure. This creates an inconsistent behavior and can also lead to several bugs which are really hard to track. This issue persisted in the language since at least Swift 2.

func autoclosureFoo(_ c: @autoclosure () -> Int) {
	print(c())
}

func autoclosureBar(_ c: @autoclosure () -> Int) {
	autoclosureFoo(c) // <-- This one here
	autoclosureFoo(c())
}

func baz(_ c: () -> Int) {
	autoclosureFoo(c) // does not work as expected
}

autoclosureBar(42)

Apparently if we’re going to fix this issue by banning it as it already should have been this will become a breaking change.

There is also another solution that I pitched on JIRA, where we could align this behavior a little and allow forwarding methods/functions/closures to an autoclosre as long the signature matches.

func foo() -> Int { return 42 }
func bar(_ c: @autoclosure () -> Int) { ... }
bar(foo) 

This would allow us to specify autoclosures with default reference to another function/closure:

func foo() -> Int { return 42 }
func bar(_ c: @autoclosure () -> Int = foo) { ... }
bar() 

This fix requires an evolution process, that’s why I’m bringing this up now. ;)

Be warned that there is yet another unresolved issue caused by autoclosure forwarding in combination with @escaping.

This piece of code produces Segmentation fault: 11

SR-5718

func foo(_ c: @autoclosure () -> Void) {}
func bar(_ c: @autoclosure @escaping () -> Void) {
  foo(c)
}

Oof, that’s a confusing one. I’m also torn on whether we should outright remove this or consider the alternative you proposed.

Do we have an idea how wide-spread this “feature” is being used? If it’s not being pervasively used, I think it should just be removed outright.

Aside: This reminds me a bit of the tuple-splatting that was removed in SE-0029.

I’d like closure forwarding to be a general feature. It should rarely be ambiguous, and it seems a nice convenience, just like…

…nevermind.

We should ban this “forwarding” in -swift-version 5 and later. I think it’s an anti-feature, and certainly wouldn’t want to see it extended.

Mark

3 Likes