Skip to content

Commit 2e4e72d

Browse files
Merge pull request #7531 from dotty-staging/fix-#7519
Fix #7519: Check PCP of constructor calls on the type
2 parents bc87529 + 02536cd commit 2e4e72d

File tree

11 files changed

+66
-11
lines changed

11 files changed

+66
-11
lines changed

compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ class TreeTypeMap(
121121
val bind1 = tmap.transformSub(bind)
122122
val expr1 = tmap.transform(expr)
123123
cpy.Labeled(labeled)(bind1, expr1)
124-
case Hole(n, args) =>
125-
Hole(n, args.mapConserve(transform)).withSpan(tree.span).withType(mapType(tree.tpe))
124+
case Hole(isTermHole, n, args) =>
125+
Hole(isTermHole, n, args.mapConserve(transform)).withSpan(tree.span).withType(mapType(tree.tpe))
126126
case tree1 =>
127127
super.transform(tree1)
128128
}

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1458,7 +1458,7 @@ object Trees {
14581458
this(this(x, arg), annot)
14591459
case Thicket(ts) =>
14601460
this(x, ts)
1461-
case Hole(_, args) =>
1461+
case Hole(_, _, args) =>
14621462
this(x, args)
14631463
case _ =>
14641464
foldMoreCases(x, tree)

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ object TreePickler {
2121

2222
val sectionName = "ASTs"
2323

24-
case class Hole(idx: Int, args: List[tpd.Tree])(implicit @constructorOnly src: SourceFile) extends tpd.Tree {
24+
case class Hole(isTermHole: Boolean, idx: Int, args: List[tpd.Tree])(implicit @constructorOnly src: SourceFile) extends tpd.Tree {
25+
override def isTerm: Boolean = isTermHole
26+
override def isType: Boolean = !isTermHole
2527
override def fallbackToText(printer: Printer): Text =
2628
s"[[$idx|" ~~ printer.toTextGlobal(args, ", ") ~~ "]]"
2729
}
@@ -579,7 +581,7 @@ class TreePickler(pickler: TastyPickler) {
579581
pickleTree(lo);
580582
if (hi ne lo) pickleTree(hi)
581583
}
582-
case Hole(idx, args) =>
584+
case Hole(_, idx, args) =>
583585
writeByte(HOLE)
584586
withLength {
585587
writeNat(idx)

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import dotty.tools.dotc.core.NameKinds._
1313
import dotty.tools.dotc.core.StagingContext._
1414
import dotty.tools.dotc.core.StdNames._
1515
import dotty.tools.dotc.core.Symbols._
16-
import dotty.tools.dotc.core.tasty.TreePickler.Hole
1716
import dotty.tools.dotc.core.Types._
1817
import dotty.tools.dotc.util.SourcePosition
1918
import dotty.tools.dotc.util.Spans._
@@ -137,6 +136,8 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
137136
case tp: ThisType =>
138137
assert(checkSymLevel(tp.cls, tp, pos).isEmpty)
139138
mapOver(tp)
139+
case tp: AnnotatedType =>
140+
derivedAnnotatedType(tp, apply(tp.parent), tp.annot)
140141
case _ =>
141142
mapOver(tp)
142143
}
@@ -167,7 +168,12 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
167168
case tp1: SkolemType => isStaticPathOK(tp1.info)
168169
case _ => false
169170

170-
if (!sym.exists || levelOK(sym) || isStaticPathOK(tp))
171+
/* Is a reference to an `<init>` method on a class with a static path */
172+
def isStaticNew(tp1: Type): Boolean = tp1 match
173+
case tp1: TermRef => tp1.symbol.isConstructor && isStaticPathOK(tp1.prefix)
174+
case _ => false
175+
176+
if (!sym.exists || levelOK(sym) || isStaticPathOK(tp) || isStaticNew(tp))
171177
None
172178
else if (!sym.isStaticOwner && !isClassRef)
173179
tryHeal(sym, tp, pos)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class Pickler extends Phase {
7878
pickled.iterator.grouped(10).toList.zipWithIndex.map {
7979
case (row, i) => s"${i}0: ${row.mkString(" ")}"
8080
}
81-
81+
8282
// println(i"rawBytes = \n$rawBytes%\n%") // DEBUG
8383
if (pickling ne noPrinter) {
8484
println(i"**** pickled info of $cls")

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ class ReifyQuotes extends MacroTransform {
157157
val tagDef = tagDefCache.getOrElseUpdate(prefix.symbol, mkTagSymbolAndAssignType(prefix))
158158
tagDef.symbol.typeRef
159159
}
160+
case AnnotatedType(parent, _) =>
161+
apply(parent) // Only keep the Annotated tree
160162
case _ =>
161163
mapOver(tp)
162164
}
@@ -263,7 +265,7 @@ class ReifyQuotes extends MacroTransform {
263265
assert(level == 1, "unexpected top splice outside quote")
264266
val (body1, quotes) = nested(isQuote = false).splitSplice(body)(spliceContext)
265267
val tpe = outer.embedded.getHoleType(body, splice)
266-
val hole = makeHole(body1, quotes, tpe).withSpan(splice.span)
268+
val hole = makeHole(splice.isTerm, body1, quotes, tpe).withSpan(splice.span)
267269
// We do not place add the inline marker for trees that where lifted as they come from the same file as their
268270
// enclosing quote. Any intemediate splice will add it's own Inlined node and cancel it before splicig the lifted tree.
269271
// Note that lifted trees are not necessarily expressions and that Inlined nodes are expected to be expressions.
@@ -378,9 +380,9 @@ class ReifyQuotes extends MacroTransform {
378380
/** Register `body` as an `embedded` quote or splice
379381
* and return a hole with `splices` as arguments and the given type `tpe`.
380382
*/
381-
private def makeHole(body: Tree, splices: List[Tree], tpe: Type)(implicit ctx: Context): Hole = {
383+
private def makeHole(isTermHole: Boolean, body: Tree, splices: List[Tree], tpe: Type)(implicit ctx: Context): Hole = {
382384
val idx = embedded.addTree(body, NoSymbol)
383-
Hole(idx, splices).withType(tpe).asInstanceOf[Hole]
385+
Hole(isTermHole, idx, splices).withType(tpe).asInstanceOf[Hole]
384386
}
385387

386388
override def transform(tree: Tree)(implicit ctx: Context): Tree =

tests/pos/i7519.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.quoted._
2+
import scala.annotation.StaticAnnotation
3+
4+
object Test {
5+
class Annot extends StaticAnnotation
6+
7+
class Quoted[T]
8+
9+
inline def quote[T]: Quoted[T] = ${ quoteImpl[T] }
10+
def quoteImpl[T: Type](given qctx: QuoteContext): Expr[Quoted[T]] = '{
11+
new Quoted[T @Annot]
12+
}
13+
}

tests/pos/i7519b.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.quoted._
2+
import scala.annotation.StaticAnnotation
3+
4+
class Annot(in: Int) extends StaticAnnotation
5+
6+
class Quoted[T]
7+
8+
inline def quote[T]: Quoted[T] = ${ quoteImpl[T] }
9+
10+
def quoteImpl[T: Type](given qctx: QuoteContext): Expr[Quoted[T]] = {
11+
val value: Expr[Int] = '{ 42 }
12+
'{ new Quoted[T @Annot($value)] }
13+
}

tests/run-macros/i7519c.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
new Quoted[scala.Int @Annot(42)]()

tests/run-macros/i7519c/Macro_1.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.quoted._
2+
import scala.annotation.StaticAnnotation
3+
4+
class Annot(in: Int) extends StaticAnnotation
5+
6+
class Quoted[T]
7+
8+
inline def quote[T]: String = ${ quoteImpl[T] }
9+
10+
def quoteImpl[T: Type](given qctx: QuoteContext): Expr[String] = {
11+
val value: Expr[Int] = '{ 42 }
12+
Expr(('{ new Quoted[T @Annot($value)] }).show)
13+
}

tests/run-macros/i7519c/Test_2.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
println(quote[Int])
4+
}
5+
}

0 commit comments

Comments
 (0)