Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-13234] Overload resolution with autoclosure and tuple labels (Swift 5.3 regression) #55674

Closed
ole opened this issue Jul 16, 2020 · 1 comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 5.3 type checker Area → compiler: Semantic analysis

Comments

@ole
Copy link
Contributor

ole commented Jul 16, 2020

Previous ID SR-13234
Radar None
Original Reporter @ole
Type Bug
Status Resolved
Resolution Done

Attachment: Download

Environment

Xcode 12.0 beta 2 (Apple Swift version 5.3 (swiftlang-1200.0.16.13 clang-1200.0.22.25)).

The code does compile in Xcode 11.6 and previous versions.

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, 5.3Regression, TypeChecker
Assignee None
Priority Medium

md5: 4e8ff947e165718b87a487f24f10b4fd

Issue Description:

The following code doesn't compile in Swift 5.3 (Xcode 12.0 beta 2), but does compile in Swift 5.2:

import XCTest

/// Asserts that two sequences contain equal elements.
public func eqElements<S1, S2>(_ expression1: @autoclosure () -> S1, _ expression2: @autoclosure () -> S2)
  where S1: Sequence, S2: Sequence, S1.Element == S2.Element, S1.Element: Equatable
{
  print("eqElements-overload1")
  XCTAssertEqual(Array(expression1()), Array(expression2()))
}

/// Asserts that two sequences *of pairs* contain equal elements.
public func eqElements<S1, S2, A, B>(_ expression1: @autoclosure () -> S1, _ expression2: @autoclosure () -> S2)
  where S1: Sequence, S2: Sequence, S1.Element == (A,B), S1.Element == S2.Element, A: Equatable, B: Equatable
{
  print("eqElements-overload2")
  XCTAssertTrue(expression1().elementsEqual(expression2(), by: { $0 == $1 }))
}

func test1() {
  let actual = [(label: 1, true)] // real test code omitted
  let expected = [(label: 1, true)]
  eqElements(actual, expected) // error here
}

test1()

The compile error in the eqElements(actual, expected) line is:

Type '(label: Int, Bool)' cannot conform to 'Equatable'; only struct/enum/class types can conform to protocols

I suspect this is what happens:

  • The presence of the element label inside the tuples [(label: 1, true)] somehow causes the compiler to choose the first overload of eqElements, which requires the array elements to be Equatable. I'd expect the second overload to be chosen, which doesn't have this requirement.
  • If I remove the element label in the tuples, i.e. replace [(label: 1, true)] with [(1, true)] in both lines, the code compiles and correctly chooses the second overload.
  • If I change all @autoclosure parameters to normal parameters (e.g. replace @autoclosure () -> S1 with S1 etc.), I can keep the tuple element label and the code still compiles and chooses the second overload.

The combination of @autoclosure and the tuple element label seems to trigger the change in behavior.

@ole
Copy link
Contributor Author

ole commented Aug 5, 2020

Closing this as resolved because it's fixed in Xcode 12.0 beta 4. Thank you to whoever fixed it! (I briefly looked for a corresponding PR/commit that included the fix, but couldn't find any.)

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 5.3 type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

2 participants