Skip to content

Commit 08ab809

Browse files
authored
Add compilation unit info to ClassSymbol (#19010)
- [x] Add `compilationUnitInfo` to class symbols - [x] Move `assocFile` into `CompilationUnitInfo` - [x] Add tasty version to `CompilationUnitInfo` - [x] Include #18925 to have test for `CompilationUnitInfo` - [x] Add explicit nulls to `CompilationUnitInfo` Fixes #18933
2 parents 637ed88 + 050859e commit 08ab809

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+329
-123
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package dotty.tools.dotc.core
2+
3+
import dotty.tools.io.AbstractFile
4+
import dotty.tools.tasty.TastyVersion
5+
6+
/** Information about the compilation unit of a class symbol.
7+
*
8+
* @param associatedFile The source or class file from which this class or
9+
* the class containing this symbol was generated,
10+
* null if not applicable.
11+
* @param tastyVersion The TASTy version (major, minor, experimental)
12+
* @param explicitNulls This compilation unit has explicit nulls enabled?
13+
*/
14+
class CompilationUnitInfo(
15+
val associatedFile: AbstractFile,
16+
val tastyVersion: Option[TastyVersion],
17+
val explicitNulls: Boolean
18+
) {
19+
20+
override def toString(): String =
21+
s"CompilationUnitInfo($associatedFile, $tastyVersion)"
22+
}
23+
24+
object CompilationUnitInfo:
25+
def apply(assocFile: AbstractFile | Null, explicitNulls: Boolean = false): CompilationUnitInfo | Null =
26+
if assocFile == null then null
27+
else new CompilationUnitInfo(
28+
assocFile,
29+
tastyVersion = None,
30+
explicitNulls = explicitNulls,
31+
)

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1409,7 +1409,7 @@ class Definitions {
14091409
),
14101410
privateWithin = patch.privateWithin,
14111411
coord = denot.symbol.coord,
1412-
assocFile = denot.symbol.associatedFile
1412+
compUnitInfo = denot.symbol.compilationUnitInfo
14131413
)
14141414

14151415
def makeNonClassSymbol(patch: Symbol) =

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,14 +298,13 @@ object Denotations {
298298
name: Name,
299299
site: Denotation = NoDenotation,
300300
args: List[Type] = Nil,
301-
source: AbstractFile | Null = null,
302301
generateStubs: Boolean = true)
303302
(p: Symbol => Boolean)
304303
(using Context): Symbol =
305304
disambiguate(p) match {
306305
case m @ MissingRef(ownerd, name) if generateStubs =>
307306
if ctx.settings.YdebugMissingRefs.value then m.ex.printStackTrace()
308-
newStubSymbol(ownerd.symbol, name, source)
307+
newStubSymbol(ownerd.symbol, name)
309308
case NoDenotation | _: NoQualifyingRef | _: MissingRef =>
310309
def argStr = if (args.isEmpty) "" else i" matching ($args%, %)"
311310
val msg =

compiler/src/dotty/tools/dotc/core/NamerOps.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ object NamerOps:
141141
ConstructorCompanionFlags, ConstructorCompanionFlags,
142142
constructorCompanionCompleter(cls),
143143
coord = cls.coord,
144-
assocFile = cls.assocFile)
144+
compUnitInfo = cls.compUnitInfo)
145145
companion.moduleClass.registerCompanion(cls)
146146
cls.registerCompanion(companion.moduleClass)
147147
companion
@@ -150,7 +150,7 @@ object NamerOps:
150150
newSymbol(tsym.owner, tsym.name.toTermName,
151151
ConstructorCompanionFlags | StableRealizable | Method, ExprType(prefix.select(proxy)), coord = tsym.coord)
152152

153-
/** Add all necesssary constructor proxy symbols for members of class `cls`. This means:
153+
/** Add all necessary constructor proxy symbols for members of class `cls`. This means:
154154
*
155155
* - if a member is a class, or type alias, that needs a constructor companion, add one,
156156
* provided no member with the same name exists.

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2588,7 +2588,7 @@ object SymDenotations {
25882588
for (sym <- scope.toList.iterator)
25892589
// We need to be careful to not force the denotation of `sym` here,
25902590
// otherwise it will be brought forward to the current run.
2591-
if (sym.defRunId != ctx.runId && sym.isClass && sym.asClass.assocFile == file)
2591+
if (sym.defRunId != ctx.runId && sym.isClass && sym.asClass.compUnitInfo != null && sym.asClass.compUnitInfo.nn.associatedFile == file)
25922592
scope.unlink(sym, sym.lastKnownDenotation.name)
25932593
}
25942594
}

compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@ import ast.desugar
2424

2525
import parsing.JavaParsers.OutlineJavaParser
2626
import parsing.Parsers.OutlineParser
27-
import dotty.tools.tasty.{TastyHeaderUnpickler, UnpickleException, UnpicklerConfig}
27+
import dotty.tools.tasty.{TastyHeaderUnpickler, UnpickleException, UnpicklerConfig, TastyVersion}
2828
import dotty.tools.dotc.core.tasty.TastyUnpickler
2929

30-
3130
object SymbolLoaders {
3231
import ast.untpd.*
3332

@@ -52,7 +51,7 @@ object SymbolLoaders {
5251
def enterClass(
5352
owner: Symbol, name: PreName, completer: SymbolLoader,
5453
flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(using Context): Symbol = {
55-
val cls = newClassSymbol(owner, name.toTypeName.unmangleClassName.decode, flags, completer, assocFile = completer.sourceFileOrNull)
54+
val cls = newClassSymbol(owner, name.toTypeName.unmangleClassName.decode, flags, completer, compUnitInfo = completer.compilationUnitInfo)
5655
enterNew(owner, cls, completer, scope)
5756
}
5857

@@ -64,7 +63,7 @@ object SymbolLoaders {
6463
val module = newModuleSymbol(
6564
owner, name.toTermName.decode, modFlags, clsFlags,
6665
(module, _) => completer.proxy.withDecls(newScope).withSourceModule(module),
67-
assocFile = completer.sourceFileOrNull)
66+
compUnitInfo = completer.compilationUnitInfo)
6867
enterNew(owner, module, completer, scope)
6968
enterNew(owner, module.moduleClass, completer, scope)
7069
}
@@ -213,7 +212,7 @@ object SymbolLoaders {
213212
/** Load contents of a package
214213
*/
215214
class PackageLoader(_sourceModule: TermSymbol, classPath: ClassPath) extends SymbolLoader {
216-
override def sourceFileOrNull: AbstractFile | Null = null
215+
def compilationUnitInfo: CompilationUnitInfo | Null = null
217216
override def sourceModule(using Context): TermSymbol = _sourceModule
218217
def description(using Context): String = "package loader " + sourceModule.fullName
219218

@@ -317,7 +316,7 @@ abstract class SymbolLoader extends LazyType { self =>
317316
/** Load source or class file for `root`, return */
318317
def doComplete(root: SymDenotation)(using Context): Unit
319318

320-
def sourceFileOrNull: AbstractFile | Null
319+
def compilationUnitInfo: CompilationUnitInfo | Null
321320

322321
/** Description of the resource (ClassPath, AbstractFile)
323322
* being processed by this loader
@@ -328,7 +327,7 @@ abstract class SymbolLoader extends LazyType { self =>
328327
* but provides fresh slots for scope/sourceModule/moduleClass
329328
*/
330329
def proxy: SymbolLoader = new SymbolLoader {
331-
export self.{doComplete, sourceFileOrNull}
330+
export self.{doComplete, compilationUnitInfo}
332331
def description(using Context): String = s"proxy to ${self.description}"
333332
}
334333

@@ -405,7 +404,8 @@ abstract class SymbolLoader extends LazyType { self =>
405404

406405
class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
407406

408-
override def sourceFileOrNull: AbstractFile | Null = classfile
407+
def compilationUnitInfo: CompilationUnitInfo | Null = CompilationUnitInfo(classfile)
408+
409409

410410
def description(using Context): String = "class file " + classfile.toString
411411

@@ -417,38 +417,55 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
417417

418418
class TastyLoader(val tastyFile: AbstractFile) extends SymbolLoader {
419419

420-
override def sourceFileOrNull: AbstractFile | Null = tastyFile
420+
private val unpickler: tasty.DottyUnpickler =
421+
handleUnpicklingExceptions:
422+
val tastyBytes = tastyFile.toByteArray
423+
new tasty.DottyUnpickler(tastyBytes) // reads header and name table
424+
425+
val compilationUnitInfo: CompilationUnitInfo | Null =
426+
val tastyHeader = unpickler.unpickler.header
427+
val tastyVersion = TastyVersion(
428+
tastyHeader.majorVersion,
429+
tastyHeader.minorVersion,
430+
tastyHeader.experimentalVersion,
431+
)
432+
val attributes = unpickler.tastyAttributes
433+
new CompilationUnitInfo(
434+
tastyFile,
435+
tastyVersion = Some(tastyVersion),
436+
explicitNulls = attributes.explicitNulls,
437+
)
421438

422439
def description(using Context): String = "TASTy file " + tastyFile.toString
423440

424441
override def doComplete(root: SymDenotation)(using Context): Unit =
425-
try
442+
handleUnpicklingExceptions:
443+
checkTastyUUID()
426444
val (classRoot, moduleRoot) = rootDenots(root.asClass)
427-
val tastyBytes = tastyFile.toByteArray
428-
val unpickler = new tasty.DottyUnpickler(tastyBytes)
429445
unpickler.enter(roots = Set(classRoot, moduleRoot, moduleRoot.sourceModule))(using ctx.withSource(util.NoSource))
430446
if mayLoadTreesFromTasty then
431447
classRoot.classSymbol.rootTreeOrProvider = unpickler
432448
moduleRoot.classSymbol.rootTreeOrProvider = unpickler
433-
checkTastyUUID(tastyFile, tastyBytes)
449+
450+
private def handleUnpicklingExceptions[T](thunk: =>T): T =
451+
try thunk
434452
catch case e: RuntimeException =>
435453
val message = e match
436454
case e: UnpickleException =>
437-
i"""TASTy file ${tastyFile.canonicalPath} could not be read, failing with:
438-
| ${Option(e.getMessage).getOrElse("")}"""
455+
s"""TASTy file ${tastyFile.canonicalPath} could not be read, failing with:
456+
| ${Option(e.getMessage).getOrElse("")}""".stripMargin
439457
case _ =>
440-
i"""TASTy file ${tastyFile.canonicalPath} is broken, reading aborted with ${e.getClass}
441-
| ${Option(e.getMessage).getOrElse("")}"""
442-
if (ctx.debug) e.printStackTrace()
443-
throw IOException(message)
458+
s"""TASTy file ${tastyFile.canonicalPath} is broken, reading aborted with ${e.getClass}
459+
| ${Option(e.getMessage).getOrElse("")}""".stripMargin
460+
throw IOException(message, e)
444461

445462

446-
private def checkTastyUUID(tastyFile: AbstractFile, tastyBytes: Array[Byte])(using Context): Unit =
463+
private def checkTastyUUID()(using Context): Unit =
447464
val classfile =
448465
val className = tastyFile.name.stripSuffix(".tasty")
449466
tastyFile.resolveSibling(className + ".class")
450467
if classfile != null then
451-
val tastyUUID = new TastyHeaderUnpickler(TastyUnpickler.scala3CompilerConfig, tastyBytes).readHeader()
468+
val tastyUUID = unpickler.unpickler.header.uuid
452469
new ClassfileTastyUUIDParser(classfile)(ctx).checkTastyUUID(tastyUUID)
453470
else
454471
// This will be the case in any of our tests that compile with `-Youtput-only-tasty`
@@ -460,15 +477,15 @@ class TastyLoader(val tastyFile: AbstractFile) extends SymbolLoader {
460477

461478
class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader {
462479
def description(using Context): String = "source file " + srcfile.toString
463-
override def sourceFileOrNull: AbstractFile | Null = srcfile
480+
def compilationUnitInfo: CompilationUnitInfo | Null = CompilationUnitInfo(srcfile)
464481
def doComplete(root: SymDenotation)(using Context): Unit =
465482
ctx.run.nn.lateCompile(srcfile, typeCheck = ctx.settings.YretainTrees.value)
466483
}
467484

468485
/** A NoCompleter which is also a SymbolLoader. */
469486
class NoLoader extends SymbolLoader with NoCompleter {
470487
def description(using Context): String = "NoLoader"
471-
override def sourceFileOrNull: AbstractFile | Null = null
488+
def compilationUnitInfo: CompilationUnitInfo | Null = null
472489
override def complete(root: SymDenotation)(using Context): Unit =
473490
super[NoCompleter].complete(root)
474491
def doComplete(root: SymDenotation)(using Context): Unit =

0 commit comments

Comments
 (0)