Skip to content

Fix #13221: Set JavaStatic on Module fields of module classes in JSCodeGen. #13381

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

Merged
merged 1 commit into from
Aug 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
// See `tests/run/given-var.scala`
//

// !!! Part of this logic is duplicated in JSCodeGen.genCompilationUnit
claszSymbol.info.decls.foreach { f =>
if f.isField && !f.name.is(LazyBitMapName) then
f.setFlag(JavaStatic)
Expand Down
24 changes: 18 additions & 6 deletions compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,23 @@ class JSCodeGen()(using genCtx: Context) {
}
val allTypeDefs = collectTypeDefs(cunit.tpdTree)

/* #13221 Set JavaStatic on all the Module fields of static module classes.
* This is necessary for `desugarIdent` not to crash in some obscure
* scenarios.
*
* !!! Part of this logic is duplicated in BCodeSkelBuilder.genPlainClass
*
* However, here we only do this for Module fields, not all fields.
*/
for (typeDef <- allTypeDefs) {
if (typeDef.symbol.is(ModuleClass)) {
typeDef.symbol.info.decls.foreach { f =>
if (f.isField && f.is(Module))
f.setFlag(JavaStatic)
}
}
}

val (anonJSClassTypeDefs, otherTypeDefs) =
allTypeDefs.partition(td => td.symbol.isAnonymousClass && td.symbol.isJSType)

Expand Down Expand Up @@ -1957,12 +1974,7 @@ class JSCodeGen()(using genCtx: Context) {
val args = tree.args
val sym = tree.fun.symbol

val fun = tree.fun match {
case fun: Ident => desugarIdent(fun)
case fun => fun
}

fun match {
tree.fun match {
case _ if sym.isJSDefaultParam =>
js.Transient(UndefinedParam)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ class RegressionTestScala3 {
@Test def defaultAccessorBridgesIssue12572(): Unit = {
new MyPromiseIssue12572[Int](5)
}

@Test def desugarIdentCrashIssue13221(): Unit = {
assertEquals(1, X_Issue13221.I.i)
assertEquals(1, X_Issue13221.blah)
}
}

object RegressionTestScala3 {
Expand Down Expand Up @@ -76,6 +81,17 @@ object RegressionTestScala3 {
???
}
}

object X_Issue13221 extends Y_Issue13221 {
object I {
def i = 1
}
}

abstract class Y_Issue13221 { self: X_Issue13221.type =>
import I._
def blah = i
}
}

// This class needs to be at the top-level, not in an object, to reproduce the issue
Expand Down