-
Notifications
You must be signed in to change notification settings - Fork 154
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
Macros missing for Scala 3 #932
Comments
I see this work is currently being experimented with in #921 |
I took a look at what it would take to migrate macros to Scala 3. The biggest issue is stumbled upon is lack of equivalent of Anyway, I managed to create a very incomplete draft (#959), it supports only one use case and almost everything is hardcoded there. It shows the basic idea though - since we cannot evaluate the tree we have to manually pattern match against each possible predicate which is very cumbersome. Also, I don't see a way to support user defined custom predicates in this solution. Implementing non-leaf predicates (as e.g. It's definitely a problematic solution, I would love to see something simpler. The above attempt assumed we are constrained by current encoding. #921 suggests that @fthomas was experimenting with new encodings. I played around with Scala 3 features that seems relevant and you can see the outcome here. Predicates for Ints can be written exclusively in terms of A friend of mine hinted me about multi-stage programming. I've had no idea about it but it sounds like something worth looking into as a way of overcoming limitations of Scala 3 macros. |
Hi, Is the issue still there ? |
Still no solution I am aware of. For test code you could circumvent it via Some things can be done via opaque types but that re-involves a lot of boilerplate. |
@Kordyjan following up on the generous offer from your tweet, would greatly appreciate @VirtusLab support in this effort! :) |
So I experimented with the encoding from #921 in armanbilge/lucuma-core#1 and it seems to work for the simple case there. @note, can you expand on your comment in #932 (comment)?
Why is this the case? Since |
Hi @armanbilge,
In #959 I tried to stay the in realm of I am writing of top of my head, probably @fthomas is the best person to ask about it, but from my analysis done months ago it looked like there's quite a few things, like type inference or treatment of Now, what was tried out in #921 and in armanbilge/lucuma-core#1 is putting another layer on top of existing stuff, namely I wondered for a moment how // This is the client code we want to support:
val a = refineMV[Int, Or[Interval.Closed[3, 5], Interval.Closed[103, 105]]](4) I was not able to write a type to make it compile in 3 minutes, if you can come up with this let me know. I will try to get back to this next days. After sacrificing readability of types, I was able to figure it out this: object Approach1 {
inline given [T, A <: Predicate[T, _], B <: Predicate[T, _]]: Predicate[T, Or[A, B]] with
transparent inline def isValid(inline t: T): Boolean = true // Dummy impl, just make it compile
val a = refineMV[Int, Or[Predicate[Int, Interval.Closed[3, 5]], Predicate[Int, Interval.Closed[103, 105]]]](4)
} But, as you see, the type What was nice from refined's POV in Scala 2 and, I believe it's not possible in Scala 3, is this: https://github.com/note/refined-demo/blob/main/refined2Base/src/main/scala/base/ContainsDollar.scala#L8. The ability to write Anyway, it's good to revive this thread. And even if we cannot come up with how to write |
@note is this what you are looking for? //> using scala "3.1.2"
//> using lib "eu.timepit::refined::0.9.29"
import eu.timepit.refined.api.Refined
import eu.timepit.refined.boolean.Or
import eu.timepit.refined.numeric.Interval
import scala.compiletime.constValue
inline def refineMV[T, P](inline t: T)(using inline p: Predicate[T, P]): Refined[T, P] = {
inline if (p.isValid(t)) Refined.unsafeApply(t) else scala.compiletime.error("no")
}
trait Predicate[T, P] {
transparent inline def isValid(inline t: T): Boolean
}
object Predicate {
inline given [M <: Int, N <: Int]: Predicate[Int, Interval.Closed[M, N]] with
transparent inline def isValid(inline t: Int): Boolean = constValue[M] <= t && t <= constValue[N]
inline given [T, A, B, PA <: Predicate[T, A], PB <: Predicate[T, B]](using predA: PA, predB: PB): Predicate[T, Or[A, B]] with
transparent inline def isValid(inline t: T): Boolean = predA.isValid(t) || predB.isValid(t)
}
@main def main =
println(refineMV[Int, Interval.Closed[1, 42]](42))
println(refineMV[Int, Or[Interval.Closed[3, 5], Interval.Closed[103, 105]]](4)) |
Polite bump on this :) if folks are happy with this |
I see some 👍 so FYI I've begun assembling some predicates here on an as-needed basis: The goal is that all of that can eventually be upstreamed. |
I should mention that I used the |
Aha, that's a very helpful pointer. Thanks! At a glance it seems like |
As I am working with Scala 3.2 currently, it would be very nice if the caveats for Scala 3 would make it in the main Readme. E,g, I stumbled upon "refineMV" missing. |
Actually there is kind of eval in Scala 3. There is eval from source code to value. Regarding eval from a tree to value it exists but |
Getting |
xref, I proposed pushing the literals into the types, since this is quite clean in scala3: to wit: instead of |
+1 for @armanbilge inline / |
Any news on this? |
Is there a milestone / expectation when and if this is going to happen? |
Support for `refined` was added to Scanamo with #182 in January 2018, but unfortunately the `refined` library itself has limited support for Scala 3 (see fthomas/refined#932), and as seen in #1804, the tests for Scanamo's `refined` code do not compile under Scala 3. Although, when Scanamo gained Scala 3 support with PR #1596 in November 2022, we initially continued `refined` support by restricting it to release only Scala 2 modules, in order to simplify Scanamo's build and reduce ongoing maintenance burden, I'm now removing Scanamo's `refined` module. If `refined` gains enough Scala 3 support to cross-compile against all versions of Scala supported by Scanamo, I'd definitely be happy for the `refined` module to be reintroduced to Scanamo.
The following code compiles and works as expected on Scala
2.13.x
, but fails on3.0.0-RC1
:It looks like the 2.x macros haven't been ported to Scala 3 yet.
The text was updated successfully, but these errors were encountered: