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

Match.subscript fails to properly cast non-matched Capture #624

Open
jasonbobier opened this issue Jan 21, 2023 · 7 comments
Open

Match.subscript fails to properly cast non-matched Capture #624

jasonbobier opened this issue Jan 21, 2023 · 7 comments
Labels
bug Something isn't working

Comments

@jasonbobier
Copy link

jasonbobier commented Jan 21, 2023

This code should produce an Optional<Int>. Instead it produces an Optional<Substring> and crashes.

import RegexBuilder

let ref = Reference(Int.self)

let regex = Regex {
	"test"
	Optionally {
		TryCapture(as: ref) {
			OneOrMore(.digit)
		} transform: {
			Int($0)
		}
	}
	"a"
}

let match = "testa".wholeMatch(of: regex)

print("Int \(match![ref])")

This aborts with:

Could not cast value of type 'Swift.Optional<Swift.Substring>' (0x1f2db92c0) to 'Swift.Int' (0x1f3da0bf0).

@jasonbobier jasonbobier added the bug Something isn't working label Jan 21, 2023
@LucianoPAlmeida
Copy link

There a few things to notice here:

  • By capture of Int being Optionally that means that an Int for the capture may not happen at all, rendering the result nil so I think what you want is a reference for an optional Int?e.g. let ref = Reference(Int?.self) which makes total sense meaning for "testa" for example no digit(which is optional) was captured meaning nil.
  • Perhaps what you want instead of Optionally with TryCapture/OneOrMore is simply TryCapture/ZeroOrMore

With that said, I don't think there is a bug here(perhaps a better runtime error message), but I'm don't know much about regex feature so I'll let @hamishknight, @natecook1000, @Azoy take a look.

@jasonbobier
Copy link
Author

Nevermind... it works... I had tried:

let ref = Reference(Optional(Int).self)

and it didn't work.

Notice the typo... Sorry for the false bug. Grrrr...

@jasonbobier
Copy link
Author

jasonbobier commented Jan 22, 2023

@LucianoPAlmeida but it won't compile for Substring. For example this fails to compile:

import RegexBuilder

let ref = Reference(Substring?.self)

let regex = Regex {
	"test"
	Optionally {
		Capture(as: ref) {
			OneOrMore(.digit)
		}
	}
	"a"
}

let match = "testa".wholeMatch(of: regex)

print("Substring \(match![ref])")

with an error of:

error: initializer 'init(as:_:)' requires the types 'Substring?' and 'Regex<OneOrMore<Substring>.RegexOutput>.RegexOutput' (aka 'Substring') be equivalent

and if I change the ref to:

let ref = Reference(Substring.self)

I get a runtime casting error:

Could not cast value of type 'Swift.Optional<Swift.Substring>' (0x1f2db10e0) to 'Swift.Substring' (0x1f3d9f530).

@jasonbobier jasonbobier reopened this Jan 22, 2023
@jasonbobier jasonbobier changed the title Match.subscript fails to properly cast non-matched TryCapture Match.subscript fails to properly cast non-matched Capture Jan 22, 2023
@LucianoPAlmeida
Copy link

@LucianoPAlmeida but it won't compile for Substring. For example this fails to compile:

import RegexBuilder

let ref = Reference(Substring?.self)

let regex = Regex {
	"test"
	Optionally {
		Capture(as: ref) {
			OneOrMore(.digit)
		}
	}
	"a"
}

let match = "testa".wholeMatch(of: regex)

print("Substring \(match![ref])")

with an error of:

error: initializer 'init(as:_:)' requires the types 'Substring?' and 'Regex<OneOrMore<Substring>.RegexOutput>.RegexOutput' (aka 'Substring') be equivalent

and if I change the ref to:

let ref = Reference(Substring.self)

I get a runtime casting error:

Could not cast value of type 'Swift.Optional<Swift.Substring>' (0x1f2db10e0) to 'Swift.Substring' (0x1f3d9f530).

Have to look in more depth into it but initially applying a transform hack makes it compile.

import RegexBuilder

let ref = Reference(Substring?.self)

let regex = Regex {
  "test"
  Optionally {
    Capture(as: ref) {
      OneOrMore(.digit)
    } transform: { $0 }
  }
  "a"
}

let match = "testa".wholeMatch(of: regex)

print("Substring \(match![ref])")

Looks like a type checker problem on matching Substring and Substring?.

@hamishknight hamishknight transferred this issue from swiftlang/swift Jan 25, 2023
@hamishknight
Copy link
Contributor

Looks like a similar issue to #623, cc @milseman

@jasonbobier
Copy link
Author

This still fails on Xcode Version 15.0 beta (15A5160n).

@jasonbobier
Copy link
Author

This still fails with Xcode 15 final.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants