Skip to content

Commit eeb00d4

Browse files
Disallow local term references in staged types (scala#16362)
Fixes scala#15917 Fixes scala#16355
2 parents ea93524 + 4e4bf20 commit eeb00d4

File tree

4 files changed

+51
-2
lines changed

4 files changed

+51
-2
lines changed

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

+6-2
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,10 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
176176
/** If the type refers to a locally defined symbol (either directly, or in a pickled type),
177177
* check that its staging level matches the current level.
178178
* - Static types and term are allowed at any level.
179-
* - If a type reference is used a higher level, then it is inconsistent. Will attempt to heal before failing.
180-
* - If a term reference is used a different level, then it is inconsistent.
179+
* - If a type reference is used a higher level, then it is inconsistent.
180+
* Will attempt to heal before failing.
181+
* - If a term reference is used a higher level, then it is inconsistent.
182+
* It cannot be healed because the term will not exist in any future stage.
181183
*
182184
* If `T` is a reference to a type at the wrong level, try to heal it by replacing it with
183185
* a type tag of type `quoted.Type[T]`.
@@ -206,6 +208,8 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
206208
tryHeal(prefix.symbol, tp, pos)
207209
case _ =>
208210
mapOver(tp)
211+
case tp @ TermRef(NoPrefix, _) if !tp.symbol.isStatic && level > levelOf(tp.symbol) =>
212+
levelError(tp.symbol, tp, pos)
209213
case tp: ThisType if level != -1 && level != levelOf(tp.cls) =>
210214
levelError(tp.cls, tp, pos)
211215
case tp: AnnotatedType =>

tests/neg-macros/i15917.scala

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import scala.quoted.*
2+
3+
def m(using Quotes): Expr[Option[_]] =
4+
val s = 3
5+
type st = s.type
6+
'{ Some(${ Expr(s) }: st) } // error

tests/neg-macros/i16355a.scala

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//> using scala "3.2.1"
2+
import scala.quoted.Expr
3+
import scala.quoted.Type
4+
import scala.quoted.quotes
5+
import scala.quoted.Quotes
6+
7+
object macros {
8+
9+
inline transparent def mkNames[A]: List[Any] = ${ mkNamesImpl[A] }
10+
11+
def mkNamesImpl[A: Type](using Quotes): Expr[List[Any]] = {
12+
import quotes.reflect._
13+
14+
val fieldNames = TypeRepr.of[A].typeSymbol.declaredFields.map(_.name)
15+
16+
val types = fieldNames
17+
.map { f =>
18+
val t1 = ConstantType(StringConstant(f))
19+
t1.asType match {
20+
case '[t1Type] => TypeRepr.of[(t1Type, "aa")]
21+
}
22+
}
23+
.reduceLeft[TypeRepr](OrType(_, _))
24+
25+
types.asType match {
26+
case '[ttt] =>
27+
Expr.ofList[ttt](
28+
fieldNames.map { v =>
29+
Expr[(v.type, "aa")](v -> "aa").asExprOf[ttt] // error
30+
}
31+
)
32+
}
33+
}
34+
35+
}

tests/neg-macros/i16355b.scala

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import scala.quoted._
2+
def test(v: String)(using Quotes): Any =
3+
Type.of : Type[v.type] // error
4+
Type.of[v.type] // error

0 commit comments

Comments
 (0)