-
Couldn't load subscription status.
- Fork 1.1k
Pattern matching on opaque type unions #16449
-
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?
Beta Was this translation helpful? Give feedback.
All reactions
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
-
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
Beta Was this translation helpful? Give feedback.
All reactions
-
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
Beta Was this translation helpful? Give feedback.