Skip to content

6.0.3: Unrelated structs end up sharing a closure when they shouldn't #78922

Open
@GarthSnyder

Description

@GarthSnyder

Description

The code below defines a struct, ClosureStorer, that accepts a closure as an initialization argument. The class UsesStorers creates two of these structs, one with < as an argument and the other with >. The problem is that both structs end up sharing a reference to the same closure.

I suspect that the underlying issue lies somewhere in the domain of class initialization. If the line

let greater = ClosureStorer(>), lessThan = ClosureStorer(<)

is rewritten to

let greater = ClosureStorer(>)
let lessThan = ClosureStorer(<)

then the problem does not occur.

Other cases where the problem doesn't occur:

  • If the ClosureStorers are initialized at the top level rather than inside a class definition.
  • If the arguments to ClosureStorer() are the names of freestanding functions rather than operators.

Reproduction

Run the following code:

struct ClosureStorer {
    let op: (Int, Int) -> Bool
    init(_ op: @escaping (Int, Int) -> Bool) {
        self.op = op
    }
    func compare(_ a: Int, _ b: Int) -> Bool {
        return op(a, b)
    }
}

class UsesStorers {
    let greater = ClosureStorer(>), lessThan = ClosureStorer(<)
    func test() {
        print(greater.compare(1, 2), lessThan.compare(1, 2))   // false false
        print(greater.compare(2, 1), lessThan.compare(2, 1))   // true true
    }
}

let user = UsesStorers()
user.test()

As indicated in the comments, the two ClosureStorer structs return (or should return, if the issue is being demonstrated correctly) the same comparison results.

Xcode shows ClosureStorer.op as having the same address for both copies of the struct. The debug output labels this "implicit closure #1".

Expected behavior

The two ClosureStorer structs are independent and should each return results that conform to the comparison operator they're initialized with. The correct output is "false true / true false", demonstrating that the closures return different results.

Environment

I'm seeing this problem on Xcode 16.2 (16C5032a), which I believe is Swift 6.0.3.

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.triage neededThis issue needs more specific labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions