swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
66.86k stars 10.3k forks source link

callAsFunction mistaken for a trailing closure when using a static initializer on same line #74853

Open davepaul0 opened 1 week ago

davepaul0 commented 1 week ago

Description

callAsFunction can be used in the same statement as an object's initializer call - this is put to good use with SwiftUI's Layout protocol.

However, if an object that implements callAsFunction is initialized with a free function or a static initializer, then trying to invoke the callAsFunction implementation without binding to a variable first will fail to compile.

Reproduction

struct MyStruct {
    static func foo() -> MyStruct { MyStruct(label: "foo") }

    let label: String

    func callAsFunction(_ work: () -> Void) -> MyStruct {
        self
    }
}

// initializer and callAsFunction argument on same line - no error
let ex1 = MyStruct(label: "foo") { _ = 1 + 1 }

// static init and callAsFunction on separate lines - no error
let ex2 = MyStruct.foo()
_ = ex2 { _ = 1 + 1 }

// static init and callAsFunction on same line - "Extra trailing closure passed in call"
let ex3 = MyStruct.foo() { _ = 1 + 1 }

Expected behavior

I would expect the third example in the code block above to compile without errors.

Environment

swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4) Target: arm64-apple-macosx14.0

(also tested with Xcode 16 Beta 2)

Additional information

No response

davepaul0 commented 1 week ago

for what it's worth, example 1 seems to work due to this addition from 2022: https://github.com/swiftlang/swift/pull/59432

If trailing closure is extraneous in a call to .init on callable type, let's not attempt to to fix it and allow solver to inject .callAsFunction first.