Skip to content

Commit 4924c9c

Browse files
committed
Replace symbol travelsal with tree traversal when finding top level experimentals
1 parent 6e32627 commit 4924c9c

File tree

3 files changed

+46
-15
lines changed

3 files changed

+46
-15
lines changed

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -804,20 +804,23 @@ object Checking {
804804
*
805805
*/
806806
def checkAndAdaptExperimentalImports(trees: List[Tree])(using Context): Unit =
807-
def nonExperimentalTopLevelDefs(pack: Symbol): Iterator[Symbol] =
808-
def isNonExperimentalTopLevelDefinition(sym: Symbol) =
809-
sym.isDefinedInCurrentRun
810-
&& sym.source == ctx.compilationUnit.source
811-
&& !sym.isConstructor // not constructor of package object
812-
&& !sym.is(Package) && !sym.name.isPackageObjectName
813-
&& !sym.isExperimental
814-
815-
pack.info.decls.toList.iterator.flatMap: sym =>
816-
if sym.isClass && (sym.is(Package) || sym.isPackageObject) then
817-
nonExperimentalTopLevelDefs(sym)
818-
else if isNonExperimentalTopLevelDefinition(sym) then
819-
sym :: Nil
820-
else Nil
807+
def nonExperimentalTopLevelDefs(): Iterator[Symbol] =
808+
new TreeAccumulator[List[Symbol]] {
809+
override def apply(x: List[Symbol], tree: tpd.Tree)(using Context): List[Symbol] =
810+
def addIfExperimental(sym: Symbol) =
811+
if !sym.isExperimental then sym :: x
812+
else x
813+
tree match {
814+
case tpd.PackageDef(_, contents) =>
815+
super.apply(x, contents)
816+
case defdef: tpd.DefDef => addIfExperimental(defdef.symbol)
817+
case valdef: tpd.ValDef => addIfExperimental(valdef.symbol)
818+
case typeDef @ tpd.TypeDef(_, temp: Template) if typeDef.symbol.isPackageObject =>
819+
super.apply(x, temp.body)
820+
case typeDef @ tpd.TypeDef(_, Template(_, _, _, _)) => addIfExperimental(typeDef.symbol)
821+
case _ => x
822+
}
823+
}.apply(Nil, ctx.compilationUnit.tpdTree).iterator
821824

822825
def unitExperimentalLanguageImports =
823826
def isAllowedImport(sel: untpd.ImportSelector) =
@@ -835,7 +838,7 @@ object Checking {
835838

836839
if ctx.owner.is(Package) || ctx.owner.name.startsWith(str.REPL_SESSION_LINE) then
837840
def markTopLevelDefsAsExperimental(why: String): Unit =
838-
for sym <- nonExperimentalTopLevelDefs(ctx.owner) do
841+
for sym <- nonExperimentalTopLevelDefs() do
839842
sym.addAnnotation(ExperimentalAnnotation(s"Added by $why", sym.span))
840843

841844
unitExperimentalLanguageImports match

tests/pos-macros/i21802/Macro.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class MetricsGroup[A]
2+
object MetricsGroup:
3+
import scala.quoted.*
4+
5+
transparent inline final def refine[A]: MetricsGroup[A] =
6+
${ refineImpl[A] }
7+
8+
private def refineImpl[A](using qctx: Quotes, tpe: Type[A]): Expr[MetricsGroup[A]] =
9+
import qctx.reflect.*
10+
11+
val mt = MethodType(Nil)(_ => Nil, _ => TypeRepr.of[A])
12+
val tpe = Refinement(TypeRepr.of[MetricsGroup[A]], "apply", mt).asType
13+
tpe match
14+
case '[tpe] =>
15+
'{ MetricsGroup[A]().asInstanceOf[MetricsGroup[A] & tpe] }

tests/pos-macros/i21802/Test.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//> using options -experimental -Ydebug
2+
3+
class ProbeFailedException(cause: Exception) extends Exception(cause)
4+
trait Probing:
5+
self: Metrics =>
6+
val probeFailureCounter: MetricsGroup[Counter] =
7+
counters("ustats_probe_failures_count").labelled
8+
9+
10+
trait Counter
11+
class Metrics:
12+
class counters(name: String):
13+
transparent inline final def labelled: MetricsGroup[Counter] = MetricsGroup.refine[Counter]

0 commit comments

Comments
 (0)