Scala: never throw from parseInputs and self-heal compiler core libraries#7980
Open
knutwannheden wants to merge 1 commit into
Open
Scala: never throw from parseInputs and self-heal compiler core libraries#7980knutwannheden wants to merge 1 commit into
parseInputs and self-heal compiler core libraries#7980knutwannheden wants to merge 1 commit into
Conversation
…ries ScalaParser.parseInputs() could throw instead of producing per-file ParseError source files, killing entire builds in downstream tools: - Batch compilation ran outside the per-input try/catch, so any exception from compileAll propagated to the caller. Now a batch failure degrades to per-file parsing, and a per-file parse failure inside the bridge's parse loop no longer aborts the whole batch. - With a classpath lacking the Scala stdlib (e.g. an empty classpath inside a fat-jar application), dotty's Run construction failed and parsing `A with B` types threw MissingCoreLibraryException. The bridge now retries Run construction with the compiler's own core library jars (located via ProtectionDomain) appended, using the result for parsing only so narrow-classpath callers like ScalaTemplate still get no type attribution.
parseInputs and self-heal compiler core libraries
greg-at-moderne
approved these changes
Jun 11, 2026
greg-at-moderne
left a comment
Contributor
There was a problem hiding this comment.
Great improvement.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
ScalaParser.parseInputs()could throw instead of producing per-fileParseErrorsource files, which kills entire builds in downstream tools (observed on apache/flink, where a resource build step died mid-build). Two related problems:parseInputs()could throw. Batch compilation (compilerContext.compileAll(...)) ran outside the per-input try/catch, so any exception from it propagated to the caller and failed the whole parse stream. Inside the bridge, the phase-1 parse loop also had no per-entry handling, so one file that failed to parse aborted the entire batch. Other parsers (e.g.JavaParser,KotlinParser) yield aParseErrorfor the failing file and keep going.Parsing
A with Btypes threwMissingCoreLibraryExceptionwithout the Scala stdlib on the classpath. Parsing a self-type likeclass Service { self: Logging with Config => }with an empty classpath inside a fat-jar application threwdotty.tools.dotc.MissingCoreLibraryException: Could not find package scala from compiler core libraries(withTypeRest→untpd.makeAndType→Definitions.andType→Denotations.staticRef). Dotty'sRunconstruction needs the Scala stdlib to initializeDefinitions; when the caller's classpath lacks it — or overrides dotty's default lookup, as a fat jar does — the bridge fell back to a bare context wherewithtypes "fail loudly". This didn't reproduce in the test JVM because dotty finds the stdlib via the JVM classpath there.Summary
ScalaParser.parseInputs()wraps batch compilation in a catch-all; on failure it reports viactx.getOnError()and degrades to the existing per-file fallback, where each input independently yields a real tree or aParseError.ScalaCompilerBridge.compileAllcatches per-entry parse failures in its phase-1 loop and omits the entry, so the caller's single-file fallback surfaces aParseErrorfor that file only.Runconstruction fails, the bridge retries it with the compiler's own core library jars appended (located viaProtectionDomain, which works inside a fat jar). The retry needs an entirely new compiler context: the failed attempt has already cached theContextBase's platform classpath, so updating the setting on afreshof the same base has no effect.Runis used for parsing only — no type attribution. Narrow-classpath callers likeScalaTemplateintentionally avoid type resolution of user types; they only need the initializedContextBasesowithtypes parse.configuredContext(...)in the bridge to share compiler context setup betweencompileAllandparse.Test plan
ParseError(previously the error killed the whole stream)parseInputswithself-type parses to a realS.CompilationUnitwith a classpath containing only a non-Scala jar, which overrides dotty's default stdlib lookup to simulate the fat-jar environment (previouslyMissingCoreLibraryException)./gradlew :rewrite-scala:checkpasses (full module test suite, license check)