Skip to content

Commit 24b75d7

Browse files
Merge pull request #9512 from dotty-staging/add-missing-liftables
Add full tests suite for quoted.Liftable
2 parents d5bdea8 + 858b53b commit 24b75d7

File tree

7 files changed

+240
-9
lines changed

7 files changed

+240
-9
lines changed

compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,11 @@ class ReifyQuotes extends MacroTransform {
167167
def pickleAsTasty() = {
168168
val meth =
169169
if (isType) ref(defn.Unpickler_unpickleType).appliedToType(originalTp)
170-
else ref(defn.Unpickler_unpickleExpr).appliedToType(originalTp.widen.dealias)
170+
else
171+
val tpe =
172+
if originalTp =:= defn.NilModule.termRef then originalTp // Workaround #4987
173+
else originalTp.widen.dealias
174+
ref(defn.Unpickler_unpickleExpr).appliedToType(tpe)
171175
val pickledQuoteStrings = liftList(PickledQuotes.pickleQuote(body).map(x => Literal(Constant(x))), defn.StringType)
172176
val splicesList = liftList(splices, defn.FunctionType(1).appliedTo(defn.SeqType.appliedTo(defn.AnyType), defn.AnyType))
173177
meth.appliedTo(pickledQuoteStrings, splicesList)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ object Expr {
113113
* `'{ List($e1, $e2, ...) }` typed as an `Expr[List[T]]`
114114
*/
115115
def ofList[T](xs: Seq[Expr[T]])(using Type[T], QuoteContext): Expr[List[T]] =
116-
if (xs.isEmpty) '{ Nil } else '{ List(${Varargs(xs)}: _*) }
116+
if (xs.isEmpty) Expr(Nil) else '{ List(${Varargs(xs)}: _*) }
117117

118118
/** Lifts this sequence of expressions into an expression of a tuple
119119
*

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

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ trait Liftable[T] {
1919
*/
2020
object Liftable {
2121

22+
// IMPORTANT Keep in sync with tests/run-staging/liftables.scala
23+
2224
given BooleanIsLiftable[T <: Boolean] as Liftable[T] = new PrimitiveLiftable
2325
given ByteIsLiftable[T <: Byte] as Liftable[T] = new PrimitiveLiftable
2426
given ShortIsLiftable[T <: Short] as Liftable[T] = new PrimitiveLiftable
@@ -103,7 +105,7 @@ object Liftable {
103105
else '{ Array(${Expr(array(0))}, ${Expr(array.toSeq.tail)}: _*) }
104106
}
105107

106-
given iArrayIsLiftable[T: Type](using ltArray: Liftable[Array[T]]) as Liftable[IArray[T]] {
108+
given IArrayIsLiftable[T: Type](using ltArray: Liftable[Array[T]]) as Liftable[IArray[T]] {
107109
def toExpr(iarray: IArray[T]): QuoteContext ?=> Expr[IArray[T]] =
108110
'{ ${ltArray.toExpr(iarray.asInstanceOf[Array[T]])}.asInstanceOf[IArray[T]] }
109111
}
@@ -118,6 +120,11 @@ object Liftable {
118120
Expr.ofList(xs.map(summon[Liftable[T]].toExpr))
119121
}
120122

123+
given NilIsLiftable as Liftable[Nil.type] = new Liftable[Nil.type] {
124+
def toExpr(xs: Nil.type): QuoteContext ?=> Expr[Nil.type] =
125+
'{ Nil }
126+
}
127+
121128
given [T: Type: Liftable] as Liftable[Set[T]] = new Liftable[Set[T]] {
122129
def toExpr(set: Set[T]): QuoteContext ?=> Expr[Set[T]] =
123130
'{ Set(${Expr(set.toSeq)}: _*) }
@@ -130,16 +137,40 @@ object Liftable {
130137

131138
given [T: Type: Liftable] as Liftable[Option[T]] = new Liftable[Option[T]] {
132139
def toExpr(x: Option[T]): QuoteContext ?=> Expr[Option[T]] = x match {
133-
case Some(x) => '{ Some[T](${Expr(x)}) }
134-
case None => '{ None: Option[T] }
140+
case x: Some[T] => Expr(x)
141+
case None => Expr(None)
135142
}
136143
}
137144

145+
given [T: Type: Liftable] as Liftable[Some[T]] = new Liftable[Some[T]] {
146+
def toExpr(x: Some[T]): QuoteContext ?=> Expr[Some[T]] =
147+
'{ Some[T](${Expr(x.get)}) }
148+
}
149+
150+
given Liftable[None.type] = new Liftable[None.type] {
151+
def toExpr(x: None.type): QuoteContext ?=> Expr[None.type] =
152+
'{ None }
153+
}
154+
138155
given [L: Type: Liftable, R: Type: Liftable] as Liftable[Either[L, R]] = new Liftable[Either[L, R]] {
139-
def toExpr(x: Either[L, R]): QuoteContext ?=> Expr[Either[L, R]] = x match {
140-
case Left(x) => '{ Left[L, R](${Expr(x)}) }
141-
case Right(x) => '{ Right[L, R](${Expr(x)}) }
142-
}
156+
def toExpr(x: Either[L, R]): QuoteContext ?=> Expr[Either[L, R]] = x match
157+
case x: Left[L, R] => Expr(x)
158+
case x: Right[L, R] => Expr(x)
159+
}
160+
161+
given [L: Type: Liftable, R: Type] as Liftable[Left[L, R]] = new Liftable[Left[L, R]] {
162+
def toExpr(x: Left[L, R]): QuoteContext ?=> Expr[Left[L, R]] =
163+
'{ Left[L, R](${Expr(x.value)}) }
164+
}
165+
166+
given [L: Type, R: Type: Liftable] as Liftable[Right[L, R]] = new Liftable[Right[L, R]] {
167+
def toExpr(x: Right[L, R]): QuoteContext ?=> Expr[Right[L, R]] =
168+
'{ Right[L, R](${Expr(x.value)}) }
169+
}
170+
171+
given EmptyTupleIsLiftable as Liftable[EmptyTuple.type] = new {
172+
def toExpr(tup: EmptyTuple.type) =
173+
'{ EmptyTuple }
143174
}
144175

145176
given [T1: Type: Liftable] as Liftable[Tuple1[T1]] = new {
@@ -305,4 +336,11 @@ object Liftable {
305336
'{ BigDecimal(${Expr(x.toString)}) }
306337
}
307338

339+
/** Lift a StringContext */
340+
given Liftable[StringContext] = new Liftable[StringContext] {
341+
def toExpr(stringContext: StringContext): QuoteContext ?=> Expr[StringContext] =
342+
val parts = Varargs(stringContext.parts.map(Expr(_)))
343+
'{ StringContext($parts: _*) }
344+
}
345+
308346
}

tests/pos-macros/nil-liftable.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import scala.quoted._
2+
3+
class Test:
4+
given NilIsLiftable as Liftable[Nil.type] = new Liftable[Nil.type] {
5+
def toExpr(xs: Nil.type): QuoteContext ?=> Expr[Nil.type] =
6+
'{ Nil }
7+
}

tests/pos-macros/quote-liftable.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def test(using QuoteContext) = {
3535
Expr(1.0f)
3636
Expr(1.0)
3737
Expr("abc")
38+
Expr(StringContext("a", "b", "c"))
3839

3940
val xs: Expr[List[Int]] = Expr(1 :: 2 :: 3 :: Nil)
4041
}

0 commit comments

Comments
 (0)