From e6f38966d13dcef90e7b640e7c09daa29aff77a8 Mon Sep 17 00:00:00 2001
From: Richard Wei <rxwei@apple.com>
Date: Mon, 20 Jun 2022 00:13:31 -0700
Subject: [PATCH] Make unary builder return `Regex` type consistently.

Currently, unary regex component builder simply forwards the component's base type. However, this is inconsistent with non-unary builder results. The current behavior may lead to surprising results when the user marks a property with `@RegexComponentBuilder`.

This patch makes `RegexComponentBuilder.buildPartialBlock<R>(first: R)` return a `Regex<R.RegexOutput>` rather than `R` itself.

---

Before:

```swift
// error: cannot convert value of type 'OneOrMore<Substring>' to specified type 'Regex<Substring>'
@RegexComponentBuilder
var r: Regex<Substring> {
  OneOrMore("a")
  // Adding other components below will make the error go away.
}

struct MyCustomRegex: RegexComponent {
  // error: cannot convert value of type 'OneOrMore<Substring>' to specified type 'Regex<Substring>'
  var regex: Regex<Substring> {
    OneOrMore("a")
  }
}
```

After: No errors.
---
 Sources/RegexBuilder/Builder.swift          |  6 ++++--
 Tests/RegexBuilderTests/RegexDSLTests.swift | 22 ++++++++++++++++++++-
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/Sources/RegexBuilder/Builder.swift b/Sources/RegexBuilder/Builder.swift
index a50f069ec..dfafd3803 100644
--- a/Sources/RegexBuilder/Builder.swift
+++ b/Sources/RegexBuilder/Builder.swift
@@ -18,8 +18,10 @@ public enum RegexComponentBuilder {
     .init(node: .empty)
   }
 
-  public static func buildPartialBlock<R: RegexComponent>(first: R ) -> R {
-    first
+  public static func buildPartialBlock<R: RegexComponent>(
+    first component: R
+  ) -> Regex<R.RegexOutput> {
+    component.regex
   }
 
   public static func buildExpression<R: RegexComponent>(_ regex: R) -> R {
diff --git a/Tests/RegexBuilderTests/RegexDSLTests.swift b/Tests/RegexBuilderTests/RegexDSLTests.swift
index 5b3914e3b..fc31e575f 100644
--- a/Tests/RegexBuilderTests/RegexDSLTests.swift
+++ b/Tests/RegexBuilderTests/RegexDSLTests.swift
@@ -1015,7 +1015,7 @@ class RegexDSLTests: XCTestCase {
       XCTAssertEqual(str.wholeMatch(of: parser)?.1, version)
     }
   }
-  
+
   func testZeroWidthConsumer() throws {
     struct Trace: CustomConsumingRegexComponent {
       typealias RegexOutput = Void
@@ -1051,6 +1051,26 @@ class RegexDSLTests: XCTestCase {
       
       """)
   }
+
+  func testRegexComponentBuilderResultType() {
+    // Test that the user can declare a closure or computed property marked with
+    // `@RegexComponentBuilder` with `Regex` as the result type.
+    @RegexComponentBuilder
+    var unaryWithSingleNonRegex: Regex<Substring> {
+      OneOrMore("a")
+    }
+    @RegexComponentBuilder
+    var multiComponent: Regex<Substring> {
+      OneOrMore("a")
+      "b"
+    }
+    struct MyCustomRegex: RegexComponent {
+      @RegexComponentBuilder
+      var regex: Regex<Substring> {
+        OneOrMore("a")
+      }
+    }
+  }
 }
 
 extension Unicode.Scalar {