Skip to content

Commit c3ec5d3

Browse files
committed
Fix scala#7048: Check for splice stability
1 parent c8371e4 commit c3ec5d3

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import dotty.tools.dotc.util.SourcePosition
1818
import dotty.tools.dotc.util.Spans._
1919
import dotty.tools.dotc.transform.SymUtils._
2020
import dotty.tools.dotc.transform.TreeMapWithStages._
21+
import dotty.tools.dotc.typer.Checking
2122
import dotty.tools.dotc.typer.Implicits.SearchFailureType
2223
import dotty.tools.dotc.typer.Inliner
2324

@@ -31,7 +32,7 @@ import scala.annotation.constructorOnly
3132
*
3233
* Type healing consists in transforming a phase inconsistent type `T` into a splice of `implicitly[Type[T]]`.
3334
*/
34-
class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(ictx) {
35+
class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(ictx) with Checking {
3536
import tpd._
3637

3738
private val InAnnotation = Property.Key[Unit]()
@@ -212,7 +213,8 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
212213
val reqType = defn.QuotedTypeClass.typeRef.appliedTo(tp)
213214
val tag = ctx.typer.inferImplicitArg(reqType, pos.span)
214215
tag.tpe match
215-
case _: TermRef =>
216+
case tp: TermRef =>
217+
checkStable(tp, pos)
216218
Some(tag.select(tpnme.splice))
217219
case _: SearchFailureType =>
218220
levelError(sym, tp, pos,

tests/neg/i7048e.scala

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import scala.quoted.{given, _}
2+
3+
abstract class Test {
4+
type T
5+
6+
val T: Type[T]
7+
val getT: Type[T] = T // need this to avoid getting `null`
8+
given Type[T] = getT
9+
10+
def foo with QuoteContext: Expr[Any] = {
11+
12+
val r = '{Option.empty[T]} // error
13+
14+
{
15+
val t: Test = this
16+
import t.{given}
17+
println(summon[Type[t.T]].show)
18+
val r = '{Option.empty[t.T]} // access to value t from wrong staging level
19+
val r2 = '{Option.empty[${t.T}]} // works
20+
}
21+
22+
{
23+
val r1 = '{Option.empty[${T}]} // works
24+
val r2 = '{Option.empty[List[${T}]]} // works
25+
val r3 = '{sumstmon[Type[${T}]]} // access to Test.this from wrong staging level
26+
val r4 = '{summon[${T} <:< Any]} // error
27+
}
28+
29+
{
30+
val s = '{Option.empty[${T}]}
31+
val r = '{identity($s)} // works
32+
val r2 = '{identity(${s: Expr[Option[T]]})} // error
33+
}
34+
35+
r
36+
}
37+
}
38+
39+
@main def main = ()

0 commit comments

Comments
 (0)