@@ -421,72 +421,80 @@ class DependencyRecorder {
421421 usedNames.names.foreach:
422422 case (usedName, scopes) =>
423423 cb.usedName(className, usedName.toString, scopes)
424- classDependencies.foreach(recordClassDependency(cb, _))
424+ val siblingClassfiles = new mutable.HashMap [PlainFile , Path ]
425+ classDependencies.foreach(recordClassDependency(cb, _, siblingClassfiles))
425426 clear()
426427
427- private val _siblingClassfiles = new mutable.HashMap [PlainFile , Path ]
428+ /** Clear all state. */
429+ def clear (): Unit =
430+ _usedNames.clear()
431+ _classDependencies.clear()
432+ lastOwner = NoSymbol
433+ lastDepSource = NoSymbol
434+ _responsibleForImports = NoSymbol
435+
436+ /** Handles dependency on given symbol by trying to figure out if represents a term
437+ * that is coming from either source code (not necessarily compiled in this compilation
438+ * run) or from class file and calls respective callback method.
439+ */
440+ private def recordClassDependency (cb : interfaces.IncrementalCallback , dep : ClassDependency ,
441+ siblingClassfiles : mutable.Map [PlainFile , Path ])(using Context ): Unit = {
442+ val fromClassName = classNameAsString(dep.fromClass)
443+ val sourceFile = ctx.compilationUnit.source
428444
429- extension (pf : PlainFile )
430- /** Constructs a sibling class to the `jpath`.
445+ /** For a `.tasty` file, constructs a sibling class to the `jpath`.
431446 * Does not validate if it exists as a real file.
447+ *
448+ * Because classpath scanning looks for tasty files first, `dep.fromClass` will be
449+ * associated to a `.tasty` file. However Zinc records all dependencies either based on `.jar` or `.class` files,
450+ * where classes are in directories on the filesystem.
451+ *
452+ * So if the dependency comes from an upstream `.tasty` file and it was not packaged in a jar, then
453+ * we need to call this to resolve the classfile that will eventually exist at runtime.
454+ *
432455 * The way this works is that by the end of compilation analysis,
433- * there should be a corresponding NonLocalClass sent to zinc with the same class file name.
456+ * we should have called `cb.generatedNonLocalClass` with the same class file name.
434457 *
435458 * FIXME: we still need a way to resolve the correct classfile when we split tasty and classes between
436459 * different outputs (e.g. stdlib-bootstrapped).
437460 */
438- private def siblingClass : Path =
439- _siblingClassfiles .getOrElseUpdate(pf, {
461+ def cachedSiblingClass ( pf : PlainFile ) : Path =
462+ siblingClassfiles .getOrElseUpdate(pf, {
440463 val jpath = pf.jpath
441464 jpath.getParent.resolve(jpath.getFileName.toString.stripSuffix(" .tasty" ) + " .class" )
442465 })
443466
444- /** Clear all state. */
445- def clear (): Unit =
446- _usedNames.clear()
447- _classDependencies.clear()
448- _siblingClassfiles.clear()
449- lastOwner = NoSymbol
450- lastDepSource = NoSymbol
451- _responsibleForImports = NoSymbol
452-
453- /** Handles dependency on given symbol by trying to figure out if represents a term
454- * that is coming from either source code (not necessarily compiled in this compilation
455- * run) or from class file and calls respective callback method.
456- */
457- private def recordClassDependency (cb : interfaces.IncrementalCallback , dep : ClassDependency )(using Context ): Unit = {
458- val fromClassName = classNameAsString(dep.fromClass)
459- val sourceFile = ctx.compilationUnit.source
460-
461467 def binaryDependency (path : Path , binaryClassName : String ) =
462468 cb.binaryDependency(path, binaryClassName, fromClassName, sourceFile, dep.context)
463469
464- def processExternalDependency (depFile : AbstractFile , binaryClassName : String , convertTasty : Boolean ) = {
465- depFile match {
466- case ze : ZipArchive # Entry => // The dependency comes from a JAR
467- ze.underlyingSource match
468- case Some (zip) if zip.jpath != null =>
469- binaryDependency(zip.jpath, binaryClassName)
470- case _ =>
471- case pf : PlainFile => // The dependency comes from a class file, Zinc handles JRT filesystem
472- binaryDependency(if convertTasty then pf.siblingClass else pf.jpath, binaryClassName)
473- case _ =>
474- internalError(s " Ignoring dependency $depFile of unknown class ${depFile.getClass}} " , dep.fromClass.srcPos)
475- }
476- }
477-
478- val depFile = dep.toClass.associatedFile
470+ val depClass = dep.toClass
471+ val depFile = depClass.associatedFile
479472 if depFile != null then {
480473 // Cannot ignore inheritance relationship coming from the same source (see sbt/zinc#417)
481474 def allowLocal = dep.context == DependencyByInheritance || dep.context == LocalDependencyByInheritance
482- if depFile.hasTastyExtension then
483- processExternalDependency(depFile, dep.toClass.binaryClassName, convertTasty = true )
484- else if depFile.hasClassExtension then
485- processExternalDependency(depFile, dep.toClass.binaryClassName, convertTasty = false )
475+ val isTasty = depFile.hasTastyExtension
476+
477+ def processExternalDependency () = {
478+ val binaryClassName = depClass.binaryClassName
479+ depFile match {
480+ case ze : ZipArchive # Entry => // The dependency comes from a JAR
481+ ze.underlyingSource match
482+ case Some (zip) if zip.jpath != null =>
483+ binaryDependency(zip.jpath, binaryClassName)
484+ case _ =>
485+ case pf : PlainFile => // The dependency comes from a class file, Zinc handles JRT filesystem
486+ binaryDependency(if isTasty then cachedSiblingClass(pf) else pf.jpath, binaryClassName)
487+ case _ =>
488+ internalError(s " Ignoring dependency $depFile of unknown class ${depFile.getClass}} " , dep.fromClass.srcPos)
489+ }
490+ }
491+
492+ if isTasty || depFile.hasClassExtension then
493+ processExternalDependency()
486494 else if allowLocal || depFile != sourceFile.file then
487495 // We cannot ignore dependencies coming from the same source file because
488496 // the dependency info needs to propagate. See source-dependencies/trait-trait-211.
489- val toClassName = classNameAsString(dep.toClass )
497+ val toClassName = classNameAsString(depClass )
490498 cb.classDependency(toClassName, fromClassName, dep.context)
491499 }
492500 }
0 commit comments