Hi!
I find incredible your work on mapping rust concepts to jvm concepts, however, I have a proposal. In Rust it's a common practice to have different subsets of a larger sum types, expressed as different enums. Let's say, a Rust programmer wants to write types A | B | C and A | B, both equally meaningful in their program. There are two common ways to do it:
enum AorBorC { VarA(A), VarB(B), VarC(C) }
enum AorB { VarA(A), VarB(B) }
or
enum AorBorC { VarAB(AorB), VarC(C) }
enum AorB { VarA(A), VarB(B) }
, both provide certain benefits:
- The former can be easily extended with another type like
A | C if needed, and (since names are usually aren't as transparent as AorB) it gives more clarity as to what the options of AorBorC are,
- The latter doesn't require writing additional From and Into impls, and enables more concise matching patterns at times.
However, what it currently compiles to is nothing like what it would be reasonably represented with in JVM languages. The typical solution there would be
sealed interface AorBorC permits AorB, VarC {}
sealed interface AorB extends AorBorC permits VarA, VarB {}
record VarA(A a) implements AorB {}
record VarB(B b) implements AorB {}
record VarC(C c) implements AorBorC {}
or better yet, have A, B and C directly implementing AorBorC and AorB where needed.
I understand the latter might be a stretch, especially considering the fact that A might as well be i32 and there's no putting custom interfaces on Integer. Unless you do some AspectJ-style weaving on stdlib jar, of course, which is considered to be a dangerous spell even by the most fearless siths.
In my head, here's how this might look in code. An attribute macro signifying that this particular enum should be a sealed interface, not a class. Still, having sealed class might be preferable for indirection reasons: INVOKEINTERFACE is slower than INVOKEVIRTUAL, although I'm not sure that applies to sealed hierarchies; that's why I'm saying an interface should be an option and not default. Consequently, one-argument variants of said "interface" enum might just be done as implementing an interface rather than creating a new wrapper class. That is, if the enum and the variant parameter are in the same... module? whatever compiles into one package.
I think that's it, although I'm all for brainstorming more ideas if you feel like discussing this. There a lot of crazy ideas that I have thought of for this project...
P.S. I am absolutely stunned by your project, seriously. Just this morning I thought about what dark magic I could pull off to make cross-FFI async between Kotlin's suspend and Rust's async. I couldn't express enough how impressed I am that someone has not only thought about it, but already done it. I hope this project brings you joy
Hi!
I find incredible your work on mapping rust concepts to jvm concepts, however, I have a proposal. In Rust it's a common practice to have different subsets of a larger sum types, expressed as different enums. Let's say, a Rust programmer wants to write types
A | B | CandA | B, both equally meaningful in their program. There are two common ways to do it:or
, both provide certain benefits:
A | Cif needed, and (since names are usually aren't as transparent as AorB) it gives more clarity as to what the options of AorBorC are,However, what it currently compiles to is nothing like what it would be reasonably represented with in JVM languages. The typical solution there would be
or better yet, have A, B and C directly implementing AorBorC and AorB where needed.
I understand the latter might be a stretch, especially considering the fact that
Amight as well bei32and there's no putting custom interfaces on Integer. Unless you do some AspectJ-style weaving on stdlib jar, of course, which is considered to be a dangerous spell even by the most fearless siths.In my head, here's how this might look in code. An attribute macro signifying that this particular enum should be a sealed interface, not a class. Still, having sealed class might be preferable for indirection reasons: INVOKEINTERFACE is slower than INVOKEVIRTUAL, although I'm not sure that applies to sealed hierarchies; that's why I'm saying an interface should be an option and not default. Consequently, one-argument variants of said "interface" enum might just be done as implementing an interface rather than creating a new wrapper class. That is, if the enum and the variant parameter are in the same... module? whatever compiles into one package.
I think that's it, although I'm all for brainstorming more ideas if you feel like discussing this. There a lot of crazy ideas that I have thought of for this project...
P.S. I am absolutely stunned by your project, seriously. Just this morning I thought about what dark magic I could pull off to make cross-FFI async between Kotlin's
suspendand Rust'sasync. I couldn't express enough how impressed I am that someone has not only thought about it, but already done it. I hope this project brings you joy