Skip to content

Commit a24ff12

Browse files
committed
Address review
1 parent 41bcb6a commit a24ff12

File tree

2 files changed

+55
-62
lines changed

2 files changed

+55
-62
lines changed

compiler/src/dotty/tools/dotc/transform/init/Checker.scala

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import scala.collection.mutable
1919

2020
import Semantic._
2121

22-
class Checker extends Phase {
22+
class Checker extends Phase:
2323

2424
override def phaseName: String = Checker.name
2525

@@ -34,19 +34,20 @@ class Checker extends Phase {
3434
val checkCtx = ctx.fresh.setPhase(this.start)
3535
val traverser = new InitTreeTraverser()
3636
units.foreach { unit => traverser.traverse(unit.tpdTree) }
37-
val classes = traverser.getConcreteClasses()
37+
val classes = traverser.getClasses()
3838

3939
Semantic.checkClasses(classes)(using checkCtx)
40+
4041
units
4142

4243
def run(using Context): Unit =
4344
// ignore, we already called `Semantic.check()` in `runOn`
4445
()
4546

46-
class InitTreeTraverser extends TreeTraverser {
47-
private val concreteClasses: mutable.ArrayBuffer[ClassSymbol] = new mutable.ArrayBuffer
47+
class InitTreeTraverser extends TreeTraverser:
48+
private val classes: mutable.ArrayBuffer[ClassSymbol] = new mutable.ArrayBuffer
4849

49-
def getConcreteClasses(): List[ClassSymbol] = concreteClasses.toList
50+
def getClasses(): List[ClassSymbol] = classes.toList
5051

5152
override def traverse(tree: Tree)(using Context): Unit =
5253
traverseChildren(tree)
@@ -59,28 +60,12 @@ class Checker extends Phase {
5960
mdef match
6061
case tdef: TypeDef if tdef.isClassDef =>
6162
val cls = tdef.symbol.asClass
62-
if isConcreteClass(cls) then concreteClasses.append(cls)
63+
classes.append(cls)
6364
case _ =>
6465

6566
case _ =>
6667
}
67-
}
68-
69-
private def isConcreteClass(cls: ClassSymbol)(using Context) = {
70-
val instantiable: Boolean =
71-
cls.is(Flags.Module) ||
72-
!cls.isOneOf(Flags.AbstractOrTrait) && {
73-
// see `Checking.checkInstantiable` in typer
74-
val tp = cls.appliedRef
75-
val stp = SkolemType(tp)
76-
val selfType = cls.givenSelfType.asSeenFrom(stp, cls)
77-
!selfType.exists || stp <:< selfType
78-
}
79-
80-
// A concrete class may not be instantiated if the self type is not satisfied
81-
instantiable && cls.enclosingPackageClass != defn.StdLibPatchesPackage.moduleClass
82-
}
83-
}
68+
end InitTreeTraverser
8469

8570
object Checker:
8671
val name: String = "initChecker"

compiler/src/dotty/tools/dotc/transform/init/Semantic.scala

Lines changed: 47 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,56 +1206,49 @@ object Semantic:
12061206
cls == defn.AnyValClass ||
12071207
cls == defn.ObjectClass
12081208

1209-
// ----- Work list ---------------------------------------------------
1210-
class WorkList private[Semantic](tasks: List[ClassSymbol]):
1211-
/** Process the worklist until done */
1212-
final def work()(using Cache, Context): Unit =
1213-
for task <- tasks do doTask(task)
1214-
1215-
/** Check an individual class
1216-
*
1217-
* This method should only be called from the work list scheduler.
1218-
*/
1219-
private def doTask(classSym: ClassSymbol)(using Cache, Context): Unit =
1220-
val thisRef = ThisRef(classSym)
1221-
val tpl = classSym.defTree.asInstanceOf[TypeDef].rhs.asInstanceOf[Template]
1209+
// ----- API --------------------------------
12221210

1223-
@tailrec
1224-
def iterate(): Unit = {
1225-
given Promoted = Promoted.empty(classSym)
1226-
given Trace = Trace.empty.add(classSym.defTree)
1227-
given reporter: Reporter.BufferedReporter = new Reporter.BufferedReporter
1211+
/** Check an individual class
1212+
*
1213+
* The class to be checked must be an instantiable concrete class.
1214+
*/
1215+
private def checkClass(classSym: ClassSymbol)(using Cache, Context): Unit =
1216+
val thisRef = ThisRef(classSym)
1217+
val tpl = classSym.defTree.asInstanceOf[TypeDef].rhs.asInstanceOf[Template]
12281218

1229-
thisRef.ensureFresh()
1219+
@tailrec
1220+
def iterate(): Unit = {
1221+
given Promoted = Promoted.empty(classSym)
1222+
given Trace = Trace.empty.add(classSym.defTree)
1223+
given reporter: Reporter.BufferedReporter = new Reporter.BufferedReporter
12301224

1231-
// set up constructor parameters
1232-
for param <- tpl.constr.termParamss.flatten do
1233-
thisRef.updateField(param.symbol, Hot)
1225+
thisRef.ensureFresh()
12341226

1235-
log("checking " + classSym) { eval(tpl, thisRef, classSym) }
1236-
reporter.errors.foreach(_.issue)
1227+
// set up constructor parameters
1228+
for param <- tpl.constr.termParamss.flatten do
1229+
thisRef.updateField(param.symbol, Hot)
12371230

1238-
if cache.hasChanged && reporter.errors.isEmpty then
1239-
// code to prepare cache and heap for next iteration
1240-
cache.prepareForNextIteration()
1241-
iterate()
1242-
else
1243-
cache.prepareForNextClass()
1244-
}
1231+
log("checking " + classSym) { eval(tpl, thisRef, classSym) }
1232+
reporter.errors.foreach(_.issue)
12451233

1246-
iterate()
1247-
end doTask
1248-
end WorkList
1234+
if cache.hasChanged && reporter.errors.isEmpty then
1235+
// code to prepare cache and heap for next iteration
1236+
cache.prepareForNextIteration()
1237+
iterate()
1238+
else
1239+
cache.prepareForNextClass()
1240+
}
12491241

1250-
// ----- API --------------------------------
1242+
iterate()
1243+
end checkClass
12511244

12521245
/**
12531246
* Check the specified concrete classes
12541247
*/
1255-
def checkClasses(concreteClasses: List[ClassSymbol])(using Context): Unit =
1256-
val workList = new WorkList(concreteClasses)
1257-
val cache = new Cache
1258-
workList.work()(using cache, ctx)
1248+
def checkClasses(classes: List[ClassSymbol])(using Context): Unit =
1249+
given Cache()
1250+
for classSym <- classes if isConcreteClass(classSym) do
1251+
checkClass(classSym)
12591252

12601253
// ----- Semantic definition --------------------------------
12611254

@@ -1766,3 +1759,18 @@ object Semantic:
17661759
if (sym.isEffectivelyFinal || sym.isConstructor) sym
17671760
else sym.matchingMember(cls.appliedRef)
17681761
}
1762+
1763+
private def isConcreteClass(cls: ClassSymbol)(using Context) = {
1764+
val instantiable: Boolean =
1765+
cls.is(Flags.Module) ||
1766+
!cls.isOneOf(Flags.AbstractOrTrait) && {
1767+
// see `Checking.checkInstantiable` in typer
1768+
val tp = cls.appliedRef
1769+
val stp = SkolemType(tp)
1770+
val selfType = cls.givenSelfType.asSeenFrom(stp, cls)
1771+
!selfType.exists || stp <:< selfType
1772+
}
1773+
1774+
// A concrete class may not be instantiated if the self type is not satisfied
1775+
instantiable && cls.enclosingPackageClass != defn.StdLibPatchesPackage.moduleClass
1776+
}

0 commit comments

Comments
 (0)