Runtime crash when accessing DSL-composed Regex Match with named capture groups
sstadelman opened this issue · comments
Description
Composing a Regex
with the DSL using RegexLiteral
s with named capture groups works, and matching works, but accessing the matches crashes at runtime.
Using the same patterns in RegexLiteral
& DSL without the names works fine.
forum.swift.org: runtime-crash-regexbuilding-with-regex-literals-containing-named-capture-groups/62539
Steps to reproduce
Define one or more patterns with named capture groups, and use the DSL to compose a Regex
. Match (whole
, prefix
, etc.) to a string. The the pattern matches correctly, but accessing the Output
causes a runtime crash.
enum FrameComponentRegex {
static let number = /frame \#(?<frame_number>\d+):/
static let address = /(?<frame_address>\dx\w{16})/
static let module = /(?<frame_module>\w+\.{0,1}\w+)/
static let function = /(?<frame_function>.+)/
}
let frame = Regex {
FrameComponentRegex.number
One(.whitespace)
FrameComponentRegex.address
One(.whitespace)
FrameComponentRegex.module
One("`")
FrameComponentRegex.function
}
let frameString = """
frame apple/swift#10: 0x00007fff2011383a libdispatch.dylib`_dispatch_client_callout + 8
"""
if let match = frameString.wholeMatch(of: frame) {
print(match)
/**
Match(anyRegexOutput: _StringProcessing.AnyRegexOutput(
input: "frame apple/swift#10: 0x00007fff2011383a libdispatch.dylib`_dispatch_client_callout + 8",
_elements: [
_StringProcessing.AnyRegexOutput.ElementRepresentation(optionalDepth: 0, content: Optional((range: Range(Swift.String.Index(_rawBits: 15)..<Swift.String.Index(_rawBits: 4980743)), value: nil)), name: nil, referenceID: nil),
_StringProcessing.AnyRegexOutput.ElementRepresentation(optionalDepth: 0, content: Optional((range: Range(Swift.String.Index(_rawBits: 458757)..<Swift.String.Index(_rawBits: 590087)), value: nil)), name: Optional("frame_number"), referenceID: nil),
_StringProcessing.AnyRegexOutput.ElementRepresentation(optionalDepth: 0, content: Optional((range: Range(Swift.String.Index(_rawBits: 721159)..<Swift.String.Index(_rawBits: 1900807)), value: nil)), name: Optional("frame_address"), referenceID: nil),
_StringProcessing.AnyRegexOutput.ElementRepresentation(optionalDepth: 0, content: Optional((range: Range(Swift.String.Index(_rawBits: 1966343)..<Swift.String.Index(_rawBits: 3080455)), value: nil)), name: Optional("frame_module"), referenceID: nil),
_StringProcessing.AnyRegexOutput.ElementRepresentation(optionalDepth: 0, content: Optional((range: Range(Swift.String.Index(_rawBits: 3145733)..<Swift.String.Index(_rawBits: 4980743)), value: nil)), name: Optional("frame_function"), referenceID: nil)
]),
range: Range(Swift.String.Index(_rawBits: 15)..<Swift.String.Index(_rawBits: 4980743)))
**/
let _ = match.output /** Runtime crash
Could not cast value of type
'(Swift.Substring, Swift.Substring, Swift.Substring, Swift.Substring, Swift.Substring)' (0x7ff848f83d00)
to 'Swift.Substring' (0x7ff848af00c8).
**/
let (_, number, address, module, function) = match.output /** Compiler exception
Type of expression is ambiguous without more context
**/
Expected behavior
It should be possible to access the captures via tuple. It would be nice to also have subscript-based access, but that's a separate issue.
enum FrameComponentRegex_Unnamed {
static let number = /frame \#(\d+):/
static let address = /(\dx\w{16})/
static let module = /(\w+\.{0,1}\w+)/
static let function = /(.+)/
}
if let match = frameString.wholeMatch(of: frame) {
let (_, number, address, module, function) = match.output
print("""
number: \(number)
address: \(address)
module: \(module)
function: \(function)
""")
}
/**
number: 10
address: 0x00007fff2011383a
module: libdispatch.dylib
function: _dispatch_client_callout + 8
**/
Environment
- Swift compiler version info
swift-driver version: 1.62.15 Apple Swift version 5.7.1 (swiftlang-5.7.1.135.3 clang-1400.0.29.51)
- Xcode version info
Version 14.1 (14B47b)
- Deployment target:
macOS 13.0