Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add compilation unit info to ClassSymbol #19010

Merged
33 changes: 33 additions & 0 deletions compiler/src/dotty/tools/dotc/core/CompilationUnitInfo.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package dotty.tools.dotc.core

import dotty.tools.io.AbstractFile
import dotty.tools.tasty.TastyVersion

/** Information about the compilation unit of a class symbol.
*
* @param associatedFile The source or class file from which this class or
* the class containing this symbol was generated,
* null if not applicable.
* @param tastyVersion The TASTy version (major, minor, experimental)
*/
class CompilationUnitInfo(
val associatedFile: AbstractFile,
private var tastyVersionOpt: Option[TastyVersion],
bishabosha marked this conversation as resolved.
Show resolved Hide resolved
) {

def tastyVersion: Option[TastyVersion] = tastyVersionOpt

/** Sets the TASTy version. Used to initialize the TASTy version when
* Loading a TASTy file in TastyLoader.
*/
def initTastyVersion(version: TastyVersion): Unit =
tastyVersionOpt = Some(version)

override def toString(): String =
s"CompilationUnitInfo($associatedFile, $tastyVersion)"
}

object CompilationUnitInfo:
def apply(assocFile: AbstractFile | Null): CompilationUnitInfo | Null =
if assocFile == null then null
else new CompilationUnitInfo(assocFile, tastyVersionOpt = None) // TODO use current TASTy version
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1409,7 +1409,7 @@ class Definitions {
),
privateWithin = patch.privateWithin,
coord = denot.symbol.coord,
assocFile = denot.symbol.associatedFile
compUnitInfo = denot.symbol.compilationUnitInfo
)

def makeNonClassSymbol(patch: Symbol) =
Expand Down
3 changes: 1 addition & 2 deletions compiler/src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -298,14 +298,13 @@ object Denotations {
name: Name,
site: Denotation = NoDenotation,
args: List[Type] = Nil,
source: AbstractFile | Null = null,
bishabosha marked this conversation as resolved.
Show resolved Hide resolved
generateStubs: Boolean = true)
(p: Symbol => Boolean)
(using Context): Symbol =
disambiguate(p) match {
case m @ MissingRef(ownerd, name) if generateStubs =>
if ctx.settings.YdebugMissingRefs.value then m.ex.printStackTrace()
newStubSymbol(ownerd.symbol, name, source)
newStubSymbol(ownerd.symbol, name)
case NoDenotation | _: NoQualifyingRef | _: MissingRef =>
def argStr = if (args.isEmpty) "" else i" matching ($args%, %)"
val msg =
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/NamerOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ object NamerOps:
ConstructorCompanionFlags, ConstructorCompanionFlags,
constructorCompanionCompleter(cls),
coord = cls.coord,
assocFile = cls.assocFile)
compUnitInfo = cls.compUnitInfo)
companion.moduleClass.registerCompanion(cls)
cls.registerCompanion(companion.moduleClass)
companion
Expand All @@ -150,7 +150,7 @@ object NamerOps:
newSymbol(tsym.owner, tsym.name.toTermName,
ConstructorCompanionFlags | StableRealizable | Method, ExprType(prefix.select(proxy)), coord = tsym.coord)

/** Add all necesssary constructor proxy symbols for members of class `cls`. This means:
/** Add all necessary constructor proxy symbols for members of class `cls`. This means:
*
* - if a member is a class, or type alias, that needs a constructor companion, add one,
* provided no member with the same name exists.
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2588,7 +2588,7 @@ object SymDenotations {
for (sym <- scope.toList.iterator)
// We need to be careful to not force the denotation of `sym` here,
// otherwise it will be brought forward to the current run.
if (sym.defRunId != ctx.runId && sym.isClass && sym.asClass.assocFile == file)
if (sym.defRunId != ctx.runId && sym.isClass && sym.asClass.compUnitInfo != null && sym.asClass.compUnitInfo.nn.associatedFile == file)
scope.unlink(sym, sym.lastKnownDenotation.name)
}
}
Expand Down
25 changes: 16 additions & 9 deletions compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ object SymbolLoaders {
def enterClass(
owner: Symbol, name: PreName, completer: SymbolLoader,
flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(using Context): Symbol = {
val cls = newClassSymbol(owner, name.toTypeName.unmangleClassName.decode, flags, completer, assocFile = completer.sourceFileOrNull)
val cls = newClassSymbol(owner, name.toTypeName.unmangleClassName.decode, flags, completer, compUnitInfo = completer.compilationUnitInfo)
enterNew(owner, cls, completer, scope)
}

Expand All @@ -64,7 +64,7 @@ object SymbolLoaders {
val module = newModuleSymbol(
owner, name.toTermName.decode, modFlags, clsFlags,
(module, _) => completer.proxy.withDecls(newScope).withSourceModule(module),
assocFile = completer.sourceFileOrNull)
compUnitInfo = completer.compilationUnitInfo)
enterNew(owner, module, completer, scope)
enterNew(owner, module.moduleClass, completer, scope)
}
Expand Down Expand Up @@ -213,7 +213,7 @@ object SymbolLoaders {
/** Load contents of a package
*/
class PackageLoader(_sourceModule: TermSymbol, classPath: ClassPath) extends SymbolLoader {
override def sourceFileOrNull: AbstractFile | Null = null
def compilationUnitInfo: CompilationUnitInfo | Null = null
override def sourceModule(using Context): TermSymbol = _sourceModule
def description(using Context): String = "package loader " + sourceModule.fullName

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

def sourceFileOrNull: AbstractFile | Null
def compilationUnitInfo: CompilationUnitInfo | Null

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

Expand Down Expand Up @@ -405,7 +405,8 @@ abstract class SymbolLoader extends LazyType { self =>

class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {

override def sourceFileOrNull: AbstractFile | Null = classfile
def compilationUnitInfo: CompilationUnitInfo | Null = CompilationUnitInfo(classfile)


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

Expand All @@ -417,7 +418,12 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {

class TastyLoader(val tastyFile: AbstractFile) extends SymbolLoader {

override def sourceFileOrNull: AbstractFile | Null = tastyFile
private val compUnitInfo = new CompilationUnitInfo(
tastyFile,
tastyVersionOpt = None // set on doComplete
)

def compilationUnitInfo: CompilationUnitInfo | Null = compUnitInfo

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

Expand All @@ -426,6 +432,7 @@ class TastyLoader(val tastyFile: AbstractFile) extends SymbolLoader {
val (classRoot, moduleRoot) = rootDenots(root.asClass)
val tastyBytes = tastyFile.toByteArray
val unpickler = new tasty.DottyUnpickler(tastyBytes)
compUnitInfo.initTastyVersion(unpickler.tastyVersion)
unpickler.enter(roots = Set(classRoot, moduleRoot, moduleRoot.sourceModule))(using ctx.withSource(util.NoSource))
if mayLoadTreesFromTasty then
classRoot.classSymbol.rootTreeOrProvider = unpickler
Expand Down Expand Up @@ -460,15 +467,15 @@ class TastyLoader(val tastyFile: AbstractFile) extends SymbolLoader {

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

/** A NoCompleter which is also a SymbolLoader. */
class NoLoader extends SymbolLoader with NoCompleter {
def description(using Context): String = "NoLoader"
override def sourceFileOrNull: AbstractFile | Null = null
def compilationUnitInfo: CompilationUnitInfo | Null = null
override def complete(root: SymDenotation)(using Context): Unit =
super[NoCompleter].complete(root)
def doComplete(root: SymDenotation)(using Context): Unit =
Expand Down
73 changes: 45 additions & 28 deletions compiler/src/dotty/tools/dotc/core/Symbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import config.Printers.typr
import dotty.tools.dotc.classpath.FileUtils.isScalaBinary

import scala.compiletime.uninitialized
import dotty.tools.tasty.TastyVersion

object Symbols {

Expand Down Expand Up @@ -265,12 +266,27 @@ object Symbols {

/** The source or class file from which this class or
* the class containing this symbol was generated, null if not applicable.
* Note that this the returned classfile might be the top-level class
* Note that the returned classfile might be from the top-level class
* containing this symbol instead of the directly enclosing class.
* Overridden in ClassSymbol
*/
def associatedFile(using Context): AbstractFile | Null =
lastDenot.topLevelClass.associatedFile
val compUnitInfo = compilationUnitInfo
if compUnitInfo == null then (null: AbstractFile | Null)
else compUnitInfo.associatedFile

/** The compilation unit info (associated file, tasty versions, ...).
* Note that the returned CompilationUnitInfo might be from the top-level class
* containing this symbol instead of the directly enclosing class.
* Overridden in ClassSymbol
*/
def compilationUnitInfo(using Context): CompilationUnitInfo | Null =
lastDenot.topLevelClass.compilationUnitInfo

/** The version of TASTy from which the symbol was loaded, None if not applicable. */
def tastyVersion(using Context): Option[TastyVersion] =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EugeneFlesselle here is the new version of the TASTy version. I changed a bit your original design, now we only have a TASTy version if the symbol vas loaded from TASTy. For symbols created from source we can assume they have the current TASTy version.

val compUnitInfo = compilationUnitInfo
if compUnitInfo == null then None
else compUnitInfo.tastyVersion

/** The class file from which this class was generated, null if not applicable. */
final def binaryFile(using Context): AbstractFile | Null = {
Expand Down Expand Up @@ -353,7 +369,7 @@ object Symbols {
def paramRef(using Context): TypeRef = denot.typeRef

/** Copy a symbol, overriding selective fields.
* Note that `coord` and `associatedFile` will be set from the fields in `owner`, not
* Note that `coord` and `compilationUnitInfo` will be set from the fields in `owner`, not
* the fields in `sym`. */
def copy(using Context)(
owner: Symbol = this.owner,
Expand All @@ -362,13 +378,14 @@ object Symbols {
info: Type = this.info,
privateWithin: Symbol = this.privateWithin,
coord: Coord = NoCoord, // Can be `= owner.coord` once we bootstrap
associatedFile: AbstractFile | Null = null // Can be `= owner.associatedFile` once we bootstrap
compUnitInfo: CompilationUnitInfo | Null = null // Can be `= owner.associatedFile` once we bootstrap
): Symbol = {
val coord1 = if (coord == NoCoord) owner.coord else coord
val associatedFile1 = if (associatedFile == null) owner.associatedFile else associatedFile
val compilationUnitInfo1 = if (compilationUnitInfo == null) owner.compilationUnitInfo else compilationUnitInfo


if isClass then
newClassSymbol(owner, name.asTypeName, flags, _ => info, privateWithin, coord1, associatedFile1)
newClassSymbol(owner, name.asTypeName, flags, _ => info, privateWithin, coord1, compilationUnitInfo1)
else
newSymbol(owner, name, flags, info, privateWithin, coord1)
}
Expand Down Expand Up @@ -396,7 +413,7 @@ object Symbols {
type TermSymbol = Symbol { type ThisName = TermName }
type TypeSymbol = Symbol { type ThisName = TypeName }

class ClassSymbol private[Symbols] (coord: Coord, val assocFile: AbstractFile | Null, id: Int, nestingLevel: Int)
class ClassSymbol private[Symbols] (coord: Coord, val compUnitInfo: CompilationUnitInfo | Null, id: Int, nestingLevel: Int)
extends Symbol(coord, id, nestingLevel) {

type ThisName = TypeName
Expand Down Expand Up @@ -456,9 +473,9 @@ object Symbols {
}

/** The source or class file from which this class was generated, null if not applicable. */
override def associatedFile(using Context): AbstractFile | Null =
if assocFile != null || this.is(Package) || this.owner.is(Package) then assocFile
else super.associatedFile
override def compilationUnitInfo(using Context): CompilationUnitInfo | Null =
if compUnitInfo != null || this.is(Package) || this.owner.is(Package) then compUnitInfo
else super.compilationUnitInfo

private var mySource: SourceFile = NoSource

Expand Down Expand Up @@ -488,7 +505,7 @@ object Symbols {
}

@sharable object NoSymbol extends Symbol(NoCoord, 0, 0) {
override def associatedFile(using Context): AbstractFile | Null = NoSource.file
override def compilationUnitInfo(using Context): CompilationUnitInfo | Null = CompilationUnitInfo(NoSource.file)
override def recomputeDenot(lastd: SymDenotation)(using Context): SymDenotation = NoDenotation
}

Expand Down Expand Up @@ -537,9 +554,9 @@ object Symbols {
infoFn: ClassSymbol => Type,
privateWithin: Symbol = NoSymbol,
coord: Coord = NoCoord,
assocFile: AbstractFile | Null = null)(using Context): ClassSymbol
compUnitInfo: CompilationUnitInfo | Null = null)(using Context): ClassSymbol
= {
val cls = new ClassSymbol(coord, assocFile, ctx.base.nextSymId, ctx.nestingLevel)
val cls = new ClassSymbol(coord, compUnitInfo, ctx.base.nextSymId, ctx.nestingLevel)
val denot = SymDenotation(cls, owner, name, flags, infoFn(cls), privateWithin)
cls.denot = denot
cls
Expand All @@ -555,11 +572,11 @@ object Symbols {
selfInfo: Type = NoType,
privateWithin: Symbol = NoSymbol,
coord: Coord = NoCoord,
assocFile: AbstractFile | Null = null)(using Context): ClassSymbol =
compUnitInfo: CompilationUnitInfo | Null = null)(using Context): ClassSymbol =
newClassSymbol(
owner, name, flags,
ClassInfo(owner.thisType, _, parents, decls, selfInfo),
privateWithin, coord, assocFile)
privateWithin, coord, compUnitInfo)

/** Same as `newCompleteClassSymbol` except that `parents` can be a list of arbitrary
* types which get normalized into type refs and parameter bindings.
Expand All @@ -572,15 +589,15 @@ object Symbols {
selfInfo: Type = NoType,
privateWithin: Symbol = NoSymbol,
coord: Coord = NoCoord,
assocFile: AbstractFile | Null = null)(using Context): ClassSymbol = {
compUnitInfo: CompilationUnitInfo | Null = null)(using Context): ClassSymbol = {
def completer = new LazyType {
def complete(denot: SymDenotation)(using Context): Unit = {
val cls = denot.asClass.classSymbol
val decls = newScope
denot.info = ClassInfo(owner.thisType, cls, parentTypes.map(_.dealias), decls, selfInfo)
}
}
newClassSymbol(owner, name, flags, completer, privateWithin, coord, assocFile)
newClassSymbol(owner, name, flags, completer, privateWithin, coord, compUnitInfo)
}

def newRefinedClassSymbol(coord: Coord = NoCoord)(using Context): ClassSymbol =
Expand All @@ -598,15 +615,15 @@ object Symbols {
infoFn: (TermSymbol, ClassSymbol) => Type, // typically a ModuleClassCompleterWithDecls
privateWithin: Symbol = NoSymbol,
coord: Coord = NoCoord,
assocFile: AbstractFile | Null = null)(using Context): TermSymbol
compUnitInfo: CompilationUnitInfo | Null = null)(using Context): TermSymbol
= {
val base = owner.thisType
val modclsFlags = clsFlags | ModuleClassCreationFlags
val modclsName = name.toTypeName.adjustIfModuleClass(modclsFlags)
val module = newSymbol(
owner, name, modFlags | ModuleValCreationFlags, NoCompleter, privateWithin, coord)
val modcls = newClassSymbol(
owner, modclsName, modclsFlags, infoFn(module, _), privateWithin, coord, assocFile)
owner, modclsName, modclsFlags, infoFn(module, _), privateWithin, coord, compUnitInfo)
module.info =
if (modcls.isCompleted) TypeRef(owner.thisType, modcls)
else new ModuleCompleter(modcls)
Expand All @@ -627,12 +644,12 @@ object Symbols {
decls: Scope,
privateWithin: Symbol = NoSymbol,
coord: Coord = NoCoord,
assocFile: AbstractFile | Null = null)(using Context): TermSymbol =
compUnitInfo: CompilationUnitInfo | Null = null)(using Context): TermSymbol =
newModuleSymbol(
owner, name, modFlags, clsFlags,
(module, modcls) => ClassInfo(
owner.thisType, modcls, parents, decls, TermRef(owner.thisType, module)),
privateWithin, coord, assocFile)
privateWithin, coord, compUnitInfo)

/** Same as `newCompleteModuleSymbol` except that `parents` can be a list of arbitrary
* types which get normalized into type refs and parameter bindings.
Expand All @@ -646,7 +663,7 @@ object Symbols {
decls: Scope,
privateWithin: Symbol = NoSymbol,
coord: Coord = NoCoord,
assocFile: AbstractFile | Null = null)(using Context): TermSymbol = {
compUnitInfo: CompilationUnitInfo | Null = null)(using Context): TermSymbol = {
def completer(module: Symbol) = new LazyType {
def complete(denot: SymDenotation)(using Context): Unit = {
val cls = denot.asClass.classSymbol
Expand All @@ -657,7 +674,7 @@ object Symbols {
newModuleSymbol(
owner, name, modFlags, clsFlags,
(module, modcls) => completer(module),
privateWithin, coord, assocFile)
privateWithin, coord, compUnitInfo)
}

/** Create a package symbol with associated package class
Expand Down Expand Up @@ -697,17 +714,17 @@ object Symbols {
/** Create a stub symbol that will issue a missing reference error
* when attempted to be completed.
*/
def newStubSymbol(owner: Symbol, name: Name, file: AbstractFile | Null = null)(using Context): Symbol = {
def newStubSymbol(owner: Symbol, name: Name, compUnitInfo: CompilationUnitInfo | Null = null)(using Context): Symbol = {
def stubCompleter = new StubInfo()
val normalizedOwner = if (owner.is(ModuleVal)) owner.moduleClass else owner
typr.println(s"creating stub for ${name.show}, owner = ${normalizedOwner.denot.debugString}, file = $file")
typr.println(s"creating stub for ${name.show}, owner = ${normalizedOwner.denot.debugString}, compilation unit = $compUnitInfo")
typr.println(s"decls = ${normalizedOwner.unforcedDecls.toList.map(_.debugString).mkString("\n ")}") // !!! DEBUG
//if (base.settings.debug.value) throw new Error()
val stub = name match {
case name: TermName =>
newModuleSymbol(normalizedOwner, name, EmptyFlags, EmptyFlags, stubCompleter, assocFile = file)
newModuleSymbol(normalizedOwner, name, EmptyFlags, EmptyFlags, stubCompleter, compUnitInfo = compUnitInfo)
case name: TypeName =>
newClassSymbol(normalizedOwner, name, EmptyFlags, stubCompleter, assocFile = file)
newClassSymbol(normalizedOwner, name, EmptyFlags, stubCompleter, compUnitInfo = compUnitInfo)
}
stub
}
Expand Down
Loading