Skip to content

Commit 89db0f8

Browse files
authored
Merge pull request #9814 from dotty-staging/fix-#9812
Fix #9812: Do not widen types during quote reification
2 parents 94e7abe + c335a36 commit 89db0f8

File tree

4 files changed

+63
-8
lines changed

4 files changed

+63
-8
lines changed

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

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -163,16 +163,10 @@ class ReifyQuotes extends MacroTransform {
163163
}
164164

165165
def pickleAsTasty() = {
166-
val meth =
167-
if (isType) ref(defn.Unpickler_unpickleType).appliedToType(originalTp)
168-
else
169-
val tpe =
170-
if originalTp =:= defn.NilModule.termRef then originalTp // Workaround #4987
171-
else originalTp.widen.dealias
172-
ref(defn.Unpickler_unpickleExpr).appliedToType(tpe)
166+
val meth = if isType then defn.Unpickler_unpickleType else defn.Unpickler_unpickleExpr
173167
val pickledQuoteStrings = liftList(PickledQuotes.pickleQuote(body).map(x => Literal(Constant(x))), defn.StringType)
174168
val splicesList = liftList(splices, defn.FunctionType(1).appliedTo(defn.SeqType.appliedTo(defn.AnyType), defn.AnyType))
175-
meth.appliedTo(pickledQuoteStrings, splicesList)
169+
ref(meth).appliedToType(originalTp).appliedTo(pickledQuoteStrings, splicesList)
176170
}
177171

178172
def taggedType(sym: Symbol) = ref(defn.InternalQuotedTypeModule).select(sym.name.toTermName)

tests/pos-macros/i9812.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// compile with -Ycheck:reifyQuotes -Ystop-after:reifyQuotes
2+
import quoted._
3+
4+
sealed abstract class SomeEnum
5+
object SomeEnum:
6+
final val Foo = new SomeEnum {}
7+
8+
def quoteFoo: QuoteContext ?=> Expr[SomeEnum.Foo.type] = '{SomeEnum.Foo}

tests/run-macros/i9812b/Macro_1.scala

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import quoted._
2+
import SomeEnum._
3+
4+
trait Liftable[T] {
5+
/** Lift a value into an expression containing the construction of that value */
6+
def toExpr(x: T): QuoteContext ?=> Expr[T]
7+
}
8+
9+
object Lift:
10+
def apply[T: Liftable](t: T)(using qctx: QuoteContext, ev: Liftable[T]): Expr[T] = ev.toExpr(t)
11+
12+
sealed abstract class SomeEnum
13+
object SomeEnum:
14+
final val Foo = new SomeEnum {}
15+
final case class Bar[S <: SomeEnum](s: S) extends SomeEnum
16+
object Bar:
17+
def apply[S <: SomeEnum](s: S): SomeEnum = new Bar(s)
18+
19+
given LiftFoo as Liftable[Foo.type]:
20+
def toExpr(x: Foo.type): QuoteContext ?=> Expr[Foo.type] = '{Foo}
21+
22+
given LiftBar[S <: SomeEnum: Type: Liftable] as Liftable[Bar[S]]:
23+
def toExpr(x: Bar[S]): QuoteContext ?=> Expr[Bar[S]] = '{new Bar(${Lift(x.s)})}
24+
25+
sealed abstract class Lst[+T]
26+
final case class CONS[+T](head: T, tail: Lst[T]) extends Lst[T]
27+
case object NIL extends Lst[Nothing]
28+
29+
given IntLiftable[T <: Int] as Liftable[T]:
30+
def toExpr(x: T): QuoteContext ?=> Expr[T] = qctx ?=> {
31+
import qctx.tasty._
32+
Literal(Constant(x)).seal.asInstanceOf[Expr[T]]
33+
}
34+
35+
given LiftLst[T: Type: Liftable](using ev1: => Liftable[CONS[T]], ev2: => Liftable[NIL.type]) as Liftable[Lst[T]]:
36+
def toExpr(xs: Lst[T]): QuoteContext ?=> Expr[Lst[T]] = xs match
37+
case NIL => ev2.toExpr(NIL)
38+
case cons @ CONS(_, _) => ev1.toExpr(cons)
39+
40+
given LiftCONS[T: Type: Liftable](using Liftable[Lst[T]]) as Liftable[CONS[T]]:
41+
def toExpr(x: CONS[T]): QuoteContext ?=> Expr[CONS[T]] = '{CONS(${Lift(x.head)}, ${Lift(x.tail)})}
42+
43+
given LiftNIL as Liftable[NIL.type]:
44+
def toExpr(x: NIL.type): QuoteContext ?=> Expr[NIL.type] = '{NIL}
45+
46+
def mkLst[T](ts: T*) = ts.foldRight(NIL: Lst[T])(CONS(_,_))
47+
48+
def quote123: QuoteContext ?=> Expr[Lst[Int]] = Lift(mkLst(1,2,3))
49+
50+
inline def get123: Lst[Int] = ${ quote123 }
51+

tests/run-macros/i9812b/Test_2.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@main def Test: Unit = println(get123)
2+

0 commit comments

Comments
 (0)