Skip to content

Commit c8764ba

Browse files
committed
Avoid forcing whole package when using -experimental
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.
1 parent 7c9aae3 commit c8764ba

File tree

4 files changed

+10
-1
lines changed

4 files changed

+10
-1
lines changed

Diff for: compiler/src/dotty/tools/dotc/typer/Checking.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -806,10 +806,11 @@ object Checking {
806806
def checkAndAdaptExperimentalImports(trees: List[Tree])(using Context): Unit =
807807
def nonExperimentalTopLevelDefs(pack: Symbol): Iterator[Symbol] =
808808
def isNonExperimentalTopLevelDefinition(sym: Symbol) =
809-
!sym.isExperimental
809+
sym.isDefinedInCurrentRun
810810
&& sym.source == ctx.compilationUnit.source
811811
&& !sym.isConstructor // not constructor of package object
812812
&& !sym.is(Package) && !sym.name.isPackageObjectName
813+
&& !sym.isExperimental
813814

814815
pack.info.decls.toList.iterator.flatMap: sym =>
815816
if sym.isClass && (sym.is(Package) || sym.isPackageObject) then

Diff for: sbt-test/java-compat/moduleInfo/A.scala

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Previously, we crashed trying to parse module-info.class in the empty package.
2+
class A

Diff for: sbt-test/java-compat/moduleInfo/build.sbt

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
scalaVersion := sys.props("plugin.scalaVersion")
2+
3+
scalacOptions ++= Seq(
4+
"-experimental"
5+
)

Diff for: sbt-test/java-compat/moduleInfo/test

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
> compile

0 commit comments

Comments
 (0)