@@ -1206,72 +1206,49 @@ object Semantic:
1206
1206
cls == defn.AnyValClass ||
1207
1207
cls == defn.ObjectClass
1208
1208
1209
- // ----- Work list ---------------------------------------------------
1210
- case class Task (value : ThisRef )
1211
-
1212
- class WorkList private [Semantic ]():
1213
- private val pendingTasks : mutable.ArrayBuffer [Task ] = new mutable.ArrayBuffer
1214
-
1215
- def addTask (task : Task ): Unit =
1216
- if ! pendingTasks.contains(task) then pendingTasks.append(task)
1217
-
1218
- /** Process the worklist until done */
1219
- final def work ()(using Cache , Context ): Unit =
1220
- for task <- pendingTasks
1221
- do doTask(task)
1222
-
1223
- /** Check an individual class
1224
- *
1225
- * This method should only be called from the work list scheduler.
1226
- */
1227
- private def doTask (task : Task )(using Cache , Context ): Unit =
1228
- val thisRef = task.value
1229
- val tpl = thisRef.klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
1230
-
1231
- @ tailrec
1232
- def iterate (): Unit = {
1233
- given Promoted = Promoted .empty(thisRef.klass)
1234
- given Trace = Trace .empty.add(thisRef.klass.defTree)
1235
- given reporter : Reporter .BufferedReporter = new Reporter .BufferedReporter
1209
+ // ----- API --------------------------------
1236
1210
1237
- thisRef.ensureFresh()
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 ]
1238
1218
1239
- // set up constructor parameters
1240
- for param <- tpl.constr.termParamss.flatten do
1241
- thisRef.updateField(param.symbol, Hot )
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
1242
1224
1243
- log(" checking " + task) { eval(tpl, thisRef, thisRef.klass) }
1244
- reporter.errors.foreach(_.issue)
1225
+ thisRef.ensureFresh()
1245
1226
1246
- if cache.hasChanged && reporter.errors.isEmpty then
1247
- // code to prepare cache and heap for next iteration
1248
- cache.prepareForNextIteration()
1249
- iterate()
1250
- else
1251
- cache.prepareForNextClass()
1252
- }
1227
+ // set up constructor parameters
1228
+ for param <- tpl.constr.termParamss.flatten do
1229
+ thisRef.updateField(param.symbol, Hot )
1253
1230
1254
- iterate()
1255
- end doTask
1256
- end WorkList
1257
- inline def workList (using wl : WorkList ): WorkList = wl
1231
+ log(" checking " + classSym) { eval(tpl, thisRef, classSym) }
1232
+ reporter.errors.foreach(_.issue)
1258
1233
1259
- // ----- API --------------------------------
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
+ }
1260
1241
1261
- /** Add a checking task to the work list */
1262
- def addTask ( thisRef : ThisRef )( using WorkList ) = workList.addTask( Task (thisRef))
1242
+ iterate()
1243
+ end checkClass
1263
1244
1264
- /** Check the specified tasks
1265
- *
1266
- * Semantic.checkTasks {
1267
- * Semantic.addTask(...)
1268
- * }
1245
+ /**
1246
+ * Check the specified concrete classes
1269
1247
*/
1270
- def checkTasks (using Context )(taskBuilder : WorkList ?=> Unit ): Unit =
1271
- val workList = new WorkList
1272
- val cache = new Cache
1273
- taskBuilder(using workList)
1274
- 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)
1275
1252
1276
1253
// ----- Semantic definition --------------------------------
1277
1254
@@ -1296,7 +1273,10 @@ object Semantic:
1296
1273
*
1297
1274
* This method only handles cache logic and delegates the work to `cases`.
1298
1275
*
1299
- * The parameter `cacheResult` is used to reduce the size of the cache.
1276
+ * @param expr The expression to be evaluated.
1277
+ * @param thisV The value for `C.this` where `C` is represented by the parameter `klass`.
1278
+ * @param klass The enclosing class where the expression is located.
1279
+ * @param cacheResult It is used to reduce the size of the cache.
1300
1280
*/
1301
1281
def eval (expr : Tree , thisV : Ref , klass : ClassSymbol , cacheResult : Boolean = false ): Contextual [Value ] = log(" evaluating " + expr.show + " , this = " + thisV.show + " in " + klass.show, printer, (_ : Value ).show) {
1302
1282
cache.get(thisV, expr) match
@@ -1326,6 +1306,10 @@ object Semantic:
1326
1306
/** Handles the evaluation of different expressions
1327
1307
*
1328
1308
* Note: Recursive call should go to `eval` instead of `cases`.
1309
+ *
1310
+ * @param expr The expression to be evaluated.
1311
+ * @param thisV The value for `C.this` where `C` is represented by the parameter `klass`.
1312
+ * @param klass The enclosing class where the expression `expr` is located.
1329
1313
*/
1330
1314
def cases (expr : Tree , thisV : Ref , klass : ClassSymbol ): Contextual [Value ] =
1331
1315
val trace2 = trace.add(expr)
@@ -1503,7 +1487,14 @@ object Semantic:
1503
1487
report.error(" [Internal error] unexpected tree" + Trace .show, expr)
1504
1488
Hot
1505
1489
1506
- /** Handle semantics of leaf nodes */
1490
+ /** Handle semantics of leaf nodes
1491
+ *
1492
+ * For leaf nodes, their semantics is determined by their types.
1493
+ *
1494
+ * @param tp The type to be evaluated.
1495
+ * @param thisV The value for `C.this` where `C` is represented by the parameter `klass`.
1496
+ * @param klass The enclosing class where the type `tp` is located.
1497
+ */
1507
1498
def cases (tp : Type , thisV : Ref , klass : ClassSymbol ): Contextual [Value ] = log(" evaluating " + tp.show, printer, (_ : Value ).show) {
1508
1499
tp match
1509
1500
case _ : ConstantType =>
@@ -1541,7 +1532,12 @@ object Semantic:
1541
1532
Hot
1542
1533
}
1543
1534
1544
- /** Resolve C.this that appear in `klass` */
1535
+ /** Resolve C.this that appear in `klass`
1536
+ *
1537
+ * @param target The class symbol for `C` for which `C.this` is to be resolved.
1538
+ * @param thisV The value for `D.this` where `D` is represented by the parameter `klass`.
1539
+ * @param klass The enclosing class where the type `C.this` is located.
1540
+ */
1545
1541
def resolveThis (target : ClassSymbol , thisV : Value , klass : ClassSymbol ): Contextual [Value ] = log(" resolving " + target.show + " , this = " + thisV.show + " in " + klass.show, printer, (_ : Value ).show) {
1546
1542
if target == klass then thisV
1547
1543
else if target.is(Flags .Package ) then Hot
@@ -1566,7 +1562,12 @@ object Semantic:
1566
1562
1567
1563
}
1568
1564
1569
- /** Compute the outer value that correspond to `tref.prefix` */
1565
+ /** Compute the outer value that correspond to `tref.prefix`
1566
+ *
1567
+ * @param tref The type whose prefix is to be evaluated.
1568
+ * @param thisV The value for `C.this` where `C` is represented by the parameter `klass`.
1569
+ * @param klass The enclosing class where the type `tref` is located.
1570
+ */
1570
1571
def outerValue (tref : TypeRef , thisV : Ref , klass : ClassSymbol ): Contextual [Value ] =
1571
1572
val cls = tref.classSymbol.asClass
1572
1573
if tref.prefix == NoPrefix then
@@ -1577,7 +1578,12 @@ object Semantic:
1577
1578
if cls.isAllOf(Flags .JavaInterface ) then Hot
1578
1579
else cases(tref.prefix, thisV, klass)
1579
1580
1580
- /** Initialize part of an abstract object in `klass` of the inheritance chain */
1581
+ /** Initialize part of an abstract object in `klass` of the inheritance chain
1582
+ *
1583
+ * @param tpl The class body to be evaluated.
1584
+ * @param thisV The value of the current object to be initialized.
1585
+ * @param klass The class to which the template belongs.
1586
+ */
1581
1587
def init (tpl : Template , thisV : Ref , klass : ClassSymbol ): Contextual [Value ] = log(" init " + klass.show, printer, (_ : Value ).show) {
1582
1588
val paramsMap = tpl.constr.termParamss.flatten.map { vdef =>
1583
1589
vdef.name -> thisV.objekt.field(vdef.symbol)
@@ -1782,3 +1788,18 @@ object Semantic:
1782
1788
if (sym.isEffectivelyFinal || sym.isConstructor) sym
1783
1789
else sym.matchingMember(cls.appliedRef)
1784
1790
}
1791
+
1792
+ private def isConcreteClass (cls : ClassSymbol )(using Context ) = {
1793
+ val instantiable : Boolean =
1794
+ cls.is(Flags .Module ) ||
1795
+ ! cls.isOneOf(Flags .AbstractOrTrait ) && {
1796
+ // see `Checking.checkInstantiable` in typer
1797
+ val tp = cls.appliedRef
1798
+ val stp = SkolemType (tp)
1799
+ val selfType = cls.givenSelfType.asSeenFrom(stp, cls)
1800
+ ! selfType.exists || stp <:< selfType
1801
+ }
1802
+
1803
+ // A concrete class may not be instantiated if the self type is not satisfied
1804
+ instantiable && cls.enclosingPackageClass != defn.StdLibPatchesPackage .moduleClass
1805
+ }
0 commit comments