-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Introduce Best Effort compilation options #17582
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
Changes from all commits
2813fd1
0cd8452
df0feaa
603a23e
bdd6d72
c08db68
14601e8
3c19ebc
cdf4f98
2eb73c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -720,12 +720,16 @@ object SymDenotations { | |
| * TODO: Find a more robust way to characterize self symbols, maybe by | ||
| * spending a Flag on them? | ||
|
Comment on lines
720
to
721
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe a flag has been spent on that since this was written, namely final def isSelfSym(using Context): Boolean = is(SelfName)?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| */ | ||
| final def isSelfSym(using Context): Boolean = owner.infoOrCompleter match { | ||
| case ClassInfo(_, _, _, _, selfInfo) => | ||
| selfInfo == symbol || | ||
| selfInfo.isInstanceOf[Type] && name == nme.WILDCARD | ||
| case _ => false | ||
| } | ||
| final def isSelfSym(using Context): Boolean = | ||
| if !ctx.isBestEffort || exists then | ||
| owner.infoOrCompleter match { | ||
| case ClassInfo(_, _, _, _, selfInfo) => | ||
| selfInfo == symbol || | ||
| selfInfo.isInstanceOf[Type] && name == nme.WILDCARD | ||
| case _ => false | ||
| } | ||
| else false | ||
|
|
||
|
|
||
| /** Is this definition contained in `boundary`? | ||
| * Same as `ownersIterator contains boundary` but more efficient. | ||
|
|
@@ -2003,7 +2007,7 @@ object SymDenotations { | |
| case p :: parents1 => | ||
| p.classSymbol match { | ||
| case pcls: ClassSymbol => builder.addAll(pcls.baseClasses) | ||
| case _ => assert(isRefinementClass || p.isError || ctx.mode.is(Mode.Interactive), s"$this has non-class parent: $p") | ||
| case _ => assert(isRefinementClass || p.isError || ctx.mode.is(Mode.Interactive) || ctx.tolerateErrorsForBestEffort, s"$this has non-class parent: $p") | ||
| } | ||
| traverse(parents1) | ||
| case nil => | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,7 @@ import java.nio.channels.ClosedByInterruptException | |
|
|
||
| import scala.util.control.NonFatal | ||
|
|
||
| import dotty.tools.dotc.classpath.FileUtils.hasTastyExtension | ||
| import dotty.tools.dotc.classpath.FileUtils.{hasTastyExtension, hasBetastyExtension} | ||
| import dotty.tools.io.{ ClassPath, ClassRepresentation, AbstractFile } | ||
| import dotty.tools.backend.jvm.DottyBackendInterface.symExtensions | ||
|
|
||
|
|
@@ -26,6 +26,7 @@ import parsing.JavaParsers.OutlineJavaParser | |
| import parsing.Parsers.OutlineParser | ||
| import dotty.tools.tasty.{TastyHeaderUnpickler, UnpickleException, UnpicklerConfig, TastyVersion} | ||
| import dotty.tools.dotc.core.tasty.TastyUnpickler | ||
| import dotty.tools.tasty.besteffort.BestEffortTastyHeaderUnpickler | ||
|
|
||
| object SymbolLoaders { | ||
| import ast.untpd.* | ||
|
|
@@ -198,7 +199,7 @@ object SymbolLoaders { | |
| enterToplevelsFromSource(owner, nameOf(classRep), src) | ||
| case (Some(bin), _) => | ||
| val completer = | ||
| if bin.hasTastyExtension then ctx.platform.newTastyLoader(bin) | ||
| if bin.hasTastyExtension || bin.hasBetastyExtension then ctx.platform.newTastyLoader(bin) | ||
| else ctx.platform.newClassLoader(bin) | ||
| enterClassAndModule(owner, nameOf(classRep), completer) | ||
| } | ||
|
|
@@ -261,7 +262,8 @@ object SymbolLoaders { | |
| (idx + str.TOPLEVEL_SUFFIX.length + 1 != name.length || !name.endsWith(str.TOPLEVEL_SUFFIX)) | ||
| } | ||
|
|
||
| def maybeModuleClass(classRep: ClassRepresentation): Boolean = classRep.name.last == '$' | ||
| def maybeModuleClass(classRep: ClassRepresentation): Boolean = | ||
| classRep.name.nonEmpty && classRep.name.last == '$' | ||
|
|
||
| private def enterClasses(root: SymDenotation, packageName: String, flat: Boolean)(using Context) = { | ||
| def isAbsent(classRep: ClassRepresentation) = | ||
|
|
@@ -416,34 +418,45 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader { | |
| } | ||
|
|
||
| class TastyLoader(val tastyFile: AbstractFile) extends SymbolLoader { | ||
|
|
||
| val isBestEffortTasty = tastyFile.hasBetastyExtension | ||
| private val unpickler: tasty.DottyUnpickler = | ||
| handleUnpicklingExceptions: | ||
| val tastyBytes = tastyFile.toByteArray | ||
| new tasty.DottyUnpickler(tastyFile, tastyBytes) // reads header and name table | ||
| new tasty.DottyUnpickler(tastyFile, tastyBytes, isBestEffortTasty) // reads header and name table | ||
|
|
||
| val compilationUnitInfo: CompilationUnitInfo | Null = unpickler.compilationUnitInfo | ||
|
|
||
| def description(using Context): String = "TASTy file " + tastyFile.toString | ||
| def description(using Context): String = | ||
| if isBestEffortTasty then "Best Effort TASTy file " + tastyFile.toString | ||
| else "TASTy file " + tastyFile.toString | ||
|
|
||
| override def doComplete(root: SymDenotation)(using Context): Unit = | ||
| handleUnpicklingExceptions: | ||
| checkTastyUUID() | ||
| val (classRoot, moduleRoot) = rootDenots(root.asClass) | ||
| unpickler.enter(roots = Set(classRoot, moduleRoot, moduleRoot.sourceModule))(using ctx.withSource(util.NoSource)) | ||
| if mayLoadTreesFromTasty then | ||
| classRoot.classSymbol.rootTreeOrProvider = unpickler | ||
| moduleRoot.classSymbol.rootTreeOrProvider = unpickler | ||
| if (!isBestEffortTasty || ctx.withBestEffortTasty) then | ||
| val tastyBytes = tastyFile.toByteArray | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With that change, we started unzipping TASTy files twice. Fixed in #24604. |
||
| unpickler.enter(roots = Set(classRoot, moduleRoot, moduleRoot.sourceModule))(using ctx.withSource(util.NoSource)) | ||
| if mayLoadTreesFromTasty || isBestEffortTasty then | ||
| classRoot.classSymbol.rootTreeOrProvider = unpickler | ||
| moduleRoot.classSymbol.rootTreeOrProvider = unpickler | ||
| if isBestEffortTasty then | ||
| checkBeTastyUUID(tastyFile, tastyBytes) | ||
| ctx.setUsedBestEffortTasty() | ||
| else | ||
| checkTastyUUID() | ||
| else | ||
| report.error(em"Cannot read Best Effort TASTy $tastyFile without the ${ctx.settings.YwithBestEffortTasty.name} option") | ||
|
|
||
| private def handleUnpicklingExceptions[T](thunk: =>T): T = | ||
| try thunk | ||
| catch case e: RuntimeException => | ||
| val tastyType = if (isBestEffortTasty) "Best Effort TASTy" else "TASTy" | ||
| val message = e match | ||
| case e: UnpickleException => | ||
| s"""TASTy file ${tastyFile.canonicalPath} could not be read, failing with: | ||
| s"""$tastyType file ${tastyFile.canonicalPath} could not be read, failing with: | ||
| | ${Option(e.getMessage).getOrElse("")}""".stripMargin | ||
| case _ => | ||
| s"""TASTy file ${tastyFile.canonicalPath} is broken, reading aborted with ${e.getClass} | ||
| s"""$tastyFile file ${tastyFile.canonicalPath} is broken, reading aborted with ${e.getClass} | ||
| | ${Option(e.getMessage).getOrElse("")}""".stripMargin | ||
| throw IOException(message, e) | ||
|
|
||
|
|
@@ -460,6 +473,9 @@ class TastyLoader(val tastyFile: AbstractFile) extends SymbolLoader { | |
| // tasty file compiled by `-Yearly-tasty-output-write` comes from an early output jar. | ||
| report.inform(s"No classfiles found for $tastyFile when checking TASTy UUID") | ||
|
|
||
| private def checkBeTastyUUID(tastyFile: AbstractFile, tastyBytes: Array[Byte])(using Context): Unit = | ||
| new BestEffortTastyHeaderUnpickler(tastyBytes).readHeader() | ||
|
|
||
| private def mayLoadTreesFromTasty(using Context): Boolean = | ||
| ctx.settings.YretainTrees.value || ctx.settings.fromTasty.value | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.