Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Pattern matching on opaque type unions #16449

Discussion options

Hi there 👋 I've placed this question under "Metaprogramming" but feel free to change it if my question is not really suitable for this.

My understanding is that the outer type for opaque types is erased during compiling, which means we can't check the outer type during runtime. This means that if we have a union of 2 opaque types which have the same underlying type, using pattern matching to differentiate them during runtime is not possible. As an example:

object opaques:
 opaque type Foo = String
 opaque type Bar = String
 type FooBar = Foo | Bar
 val foo: Foo = "foo"
 val bar: Bar = "foo"
end opaques
object program:
 import opaques.*
 def handleFooBar(fooBar: FooBar): Unit = fooBar match
 case _: Foo => throw new Throwable("foo")
 case _: Bar => println("bar")
 @main def main =
 handleFooBar(bar)
end program

In this case handleFooBar will always raise an error since we're essentially pattern matching on _: String during runtime. One way we could work around this is via inlining, e.g.,

 inline def handleFooBar(inline fooBar: FooBar): Unit = inline fooBar match
 case _: Foo => throw new Throwable("foo")
 case _: Bar => println("bar")

However, this might not always be possible to do, particularly in cases where we have other non-inlined methods in the middle. I was wondering, is there any other way that this can be achieved or is inlining the only solution?

You must be logged in to vote

if you have some kind of runtime inspectable property that distinguishes Foo and Bar then you can define a given scala.reflect.TypeTest instance for them - see API Docs and Scala 3 Reference. However it appears in your example that foo: Foo and bar: Bar both == "foo", so there is no way to distinguish them in this case

Replies: 1 comment 1 reply

Comment options

if you have some kind of runtime inspectable property that distinguishes Foo and Bar then you can define a given scala.reflect.TypeTest instance for them - see API Docs and Scala 3 Reference. However it appears in your example that foo: Foo and bar: Bar both == "foo", so there is no way to distinguish them in this case

You must be logged in to vote
1 reply
Comment options

Thank you very much for sharing that info, I've learned quite a bit reading through this!

In this particular usecase though it's not possible to differentiate the opaques based on a runtime property so it's not possible to use TypeTag

Answer selected by kyri-petrou
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /