Skip to content

Commit

Permalink
Avoid forcing whole package when using -experimental
Browse files Browse the repository at this point in the history
In #19807, the behavior of `-experimental`
was changed to mark all top-level definitions as experimental. To do so, the
implementation traverses the whole package and checks every symbol to see if it
should be transformed or not. The problem was that the first check we do is
`sym.isExperimental` which ends up forcing the symbol.

Besides being a performance issue, this could also lead to a crash if the
current package is the empty package, because we could end up forcing the magic
`module-info.class` that Java modules place there. For some reason, this appear
to only happen when building with sbt, hence the additional scripted test.

This PR fixes this issue by reordering the checks (and adding a preliminary
`isDefinedInCurrentRun` check for good measure). We should also investigate
whether we can avoid creating a symbol for `module-info.class`, but this PR is
intentionally minimal so we can backport it to 3.5.0-RC2 without risks.
  • Loading branch information
smarter committed May 14, 2024
1 parent 7c9aae3 commit c8764ba
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 1 deletion.
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -806,10 +806,11 @@ object Checking {
def checkAndAdaptExperimentalImports(trees: List[Tree])(using Context): Unit =
def nonExperimentalTopLevelDefs(pack: Symbol): Iterator[Symbol] =
def isNonExperimentalTopLevelDefinition(sym: Symbol) =
!sym.isExperimental
sym.isDefinedInCurrentRun
&& sym.source == ctx.compilationUnit.source
&& !sym.isConstructor // not constructor of package object
&& !sym.is(Package) && !sym.name.isPackageObjectName
&& !sym.isExperimental

pack.info.decls.toList.iterator.flatMap: sym =>
if sym.isClass && (sym.is(Package) || sym.isPackageObject) then
Expand Down
2 changes: 2 additions & 0 deletions sbt-test/java-compat/moduleInfo/A.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Previously, we crashed trying to parse module-info.class in the empty package.
class A
5 changes: 5 additions & 0 deletions sbt-test/java-compat/moduleInfo/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
scalaVersion := sys.props("plugin.scalaVersion")

scalacOptions ++= Seq(
"-experimental"
)
1 change: 1 addition & 0 deletions sbt-test/java-compat/moduleInfo/test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
> compile

0 comments on commit c8764ba

Please sign in to comment.