swiftlang / swift

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

(Transferred from swift-testing) `#expect` doesn't correctly expand an expression with a custom operator. #76873

Open YOCKOW opened 2 weeks ago

YOCKOW commented 2 weeks ago

Description

Given the following code:

import Testing

infix operator ~~~~: RangeFormationPrecedence
struct MyFancyStruct: Equatable {}
extension Int {
  static func ~~~~(lhs: Int, rhs: Int) -> MyFancyStruct { .init() }
}

@Test func myFancyTest() {
  #expect(Range<Int>(uncheckedBounds: (lower: 0, upper: 1)) == 0..<1) // ✅ OK (Even not parenthesized).
  #expect(MyFancyStruct() == (1 ~~~~ 2)) // ✅ Needs to be parenthesized because...
  #expect(MyFancyStruct() == 1 ~~~~ 2) // ❌ Expanded as below:
  /*
   Testing.__checkBinaryOperation(MyFancyStruct() == 1, {
           $0 ~~~~ $1()
       }, 2, expression: .__fromBinaryOperation(.__fromSyntaxNode("MyFancyStruct() == 1"), "~~~~", .__fromSyntaxNode("2")), comments: [], isRequired: false, sourceLocation: Testing.SourceLocation.__here()).__expected()
   */
}

As the comments in the code says, the expression with a custom operator on the right side is not correctly expanded as expected.

Expected behavior

#expect(MyFancyStruct() == 1 ~~~~ 2) is supposed to be the same with #expect(MyFancyStruct() == (1 ~~~~ 2)).

Actual behavior

Fails to compile because the expanded statement is invalid.

Steps to reproduce

Described above.

swift-testing version/commit hash

Testing Library Version: 94 (arm64e-apple-macos13.0)

Swift & OS version (output of swift --version ; uname -a)

swift-driver version: 1.115 Apple Swift version 6.0 (swiftlang-6.0.0.9.10 clang-1600.0.26.2)
Target: arm64-apple-macosx15.0
grynspan commented 2 weeks ago

Looks like swift-syntax isn't correctly constructing the AST for this operator. I'll send this over to them shortly.

ahoppen commented 2 weeks ago

Synced to Apple’s issue tracker as rdar://137278375

ahoppen commented 2 weeks ago

We currently only fold standard operators during macro expansion. Sending to the compiler repo because it would need to communicate the operator precedence groups.