Skip to content

Commit f57055c

Browse files
Merge pull request #10588 from dotty-staging/support-primitive-unliftable-with-precise-types
Allow unlifting precise types for primitives
2 parents f1872e5 + f9ff628 commit f57055c

File tree

6 files changed

+55
-10
lines changed

6 files changed

+55
-10
lines changed

library/src-bootstrapped/scala/quoted/Unliftable.scala

+10-10
Original file line numberDiff line numberDiff line change
@@ -28,58 +28,58 @@ object Unliftable {
2828
* - Unlifts `'{false}` into `Some(false)`
2929
* - Otherwise unlifts to `None`
3030
*/
31-
given BooleanUnliftable as Unliftable[Boolean] = new PrimitiveUnliftable
31+
given BooleanUnliftable[T <: Boolean] as Unliftable[T] = new PrimitiveUnliftable
3232

3333
/** Default unliftable for Byte
3434
* - Unlifts `'{n}` into `Some(n)` for a literal `n` of type `Byte`
3535
* - Otherwise unlifts to `None`
3636
*/
37-
given ByteUnliftable as Unliftable[Byte] = new PrimitiveUnliftable
37+
given ByteUnliftable[T <: Byte] as Unliftable[T] = new PrimitiveUnliftable
3838

3939
/** Default unliftable for Short
4040
* - Unlifts `'{n}` into `Some(n)` for a literal `n` of type `Short`
4141
* - Otherwise unlifts to `None`
4242
*/
43-
given ShortUnliftable as Unliftable[Short] = new PrimitiveUnliftable
43+
given ShortUnliftable[T <: Short] as Unliftable[T] = new PrimitiveUnliftable
4444

4545
/** Default unliftable for Int
4646
* - Unlifts `'{n}` into `Some(n)` for a literal `n` of type `Int`
4747
* - Otherwise unlifts to `None`
4848
*/
49-
given IntUnliftable as Unliftable[Int] = new PrimitiveUnliftable
49+
given IntUnliftable[T <: Int] as Unliftable[T] = new PrimitiveUnliftable
5050

5151
/** Default unliftable for Long
5252
* - Unlifts `'{n}` into `Some(n)` for a literal `n` of type `Long`
5353
* - Otherwise unlifts to `None`
5454
*/
55-
given LongUnliftable as Unliftable[Long] = new PrimitiveUnliftable
55+
given LongUnliftable[T <: Long] as Unliftable[T] = new PrimitiveUnliftable
5656

5757
/** Default unliftable for Float
5858
* - Unlifts `'{n}` into `Some(n)` for a literal `n` of type `Float`
5959
* - Otherwise unlifts to `None`
6060
*/
61-
given FloatUnliftable as Unliftable[Float] = new PrimitiveUnliftable
61+
given FloatUnliftable[T <: Float] as Unliftable[T] = new PrimitiveUnliftable
6262

6363
/** Default unliftable for Double
6464
* - Unlifts `'{n}` into `Some(n)` for a literal `n` of type `Double`
6565
* - Otherwise unlifts to `None`
6666
*/
67-
given DoubleUnliftable as Unliftable[Double] = new PrimitiveUnliftable
67+
given DoubleUnliftable[T <: Double] as Unliftable[T] = new PrimitiveUnliftable
6868

6969
/** Default unliftable for Char
7070
* - Unlifts `'{c}` into `Some(c)` for a literal `c` of type `Char`
7171
* - Otherwise unlifts to `None`
7272
*/
73-
given CharUnliftable as Unliftable[Char] = new PrimitiveUnliftable
73+
given CharUnliftable[T <: Char] as Unliftable[T] = new PrimitiveUnliftable
7474

7575
/** Default unliftable for String
7676
* - Unlifts `'{str}` into `Some(str)` for a literal `str` of type `String`
7777
* - Otherwise unlifts to `None`
7878
*/
79-
given StringUnliftable as Unliftable[String] = new PrimitiveUnliftable
79+
given StringUnliftable[T <: String] as Unliftable[T] = new PrimitiveUnliftable
8080

8181
/** Lift a quoted primitive value `'{ x }` into `x` */
82-
private class PrimitiveUnliftable[T <: Int | Boolean | Byte | Short | Int | Long | Float | Double | Char | String] extends Unliftable[T] {
82+
private class PrimitiveUnliftable[T <: Boolean | Byte | Short | Int | Long | Float | Double | Char | String] extends Unliftable[T] {
8383
def fromExpr(expr: Expr[T]) =
8484
import quotes.reflect._
8585
def rec(tree: Term): Option[T] = tree match {

tests/run-macros/expr-map-3.check

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
foo
2+
foofoo
3+
apply
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import scala.quoted._
2+
3+
4+
inline def rewrite[T](inline x: Any): Any = ${ stringRewriter('x) }
5+
6+
private def stringRewriter(e: Expr[Any])(using Quotes): Expr[Any] =
7+
StringRewriter.transform(e)
8+
9+
private object StringRewriter extends ExprMap {
10+
11+
def transform[T](e: Expr[T])(using Type[T])(using Quotes): Expr[T] = e match
12+
case '{ ${Unlifted(s)}: String } =>
13+
// checkIfValid(s)
14+
val s2: String & T = s
15+
Expr(s2)
16+
case _ => transformChildren(e)
17+
18+
}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
object Test {
2+
3+
def main(args: Array[String]): Unit = {
4+
println(rewrite("foo"))
5+
println(rewrite("foo" + "foo"))
6+
7+
rewrite {
8+
println("apply")
9+
}
10+
}
11+
12+
}

tests/run-staging/unliftables.check

+6
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@ Some(6)
88
Some(7.1)
99
Some(8.1)
1010

11+
Some(4)
12+
Some(5)
13+
Some(8.2)
14+
1115
Some(a)
16+
Some(b)
1217
Some(abc)
18+
Some(def)
1319

1420
Some(List(1, 2, 3))
1521
Some(List(1, 2, 3))

tests/run-staging/unliftables.scala

+6
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,14 @@ object Test {
1313
println('{ 7.1: Float }.unlift)
1414
println('{ 8.1: Double }.unlift)
1515
println()
16+
println(('{ 4 }: Expr[4]).unlift)
17+
println(('{ 5L }: Expr[5L]).unlift)
18+
println(('{ 8.2 }: Expr[8.2]).unlift)
19+
println()
1620
println('{ 'a' }.unlift)
21+
println(('{ 'b' }: Expr['b']).unlift)
1722
println('{ "abc" }.unlift)
23+
println(('{ "def" }: Expr["def"]).unlift)
1824
println()
1925
// TODO?
2026
// println('{ classOf[String] }.unlift)

0 commit comments

Comments
 (0)