diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 7e53b38b5f98..2eb92de2c908 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -22,6 +22,7 @@ import config.Printers.refcheck import reporting.* import Constants.Constant import cc.stripCapturing +import dotty.tools.dotc.printing.Formatting.hl object RefChecks { import tpd.* @@ -1274,6 +1275,18 @@ object RefChecks { case tp: NamedType if tp.prefix.typeSymbol != ctx.owner.enclosingClass => report.warning(UnqualifiedCallToAnyRefMethod(tree, tree.symbol), tree) case _ => () + + def checkJavaStaticProtected(tree: tpd.Apply | tpd.Select | tpd.Assign)(using Context): Unit = + val sym = tree.symbol + if sym.isAllOf(StaticProtected) then + val definedPackage = sym.enclosingPackageClass + val definedClass = sym.owner.companionClass //it's _not_ sym.enclosingClass because it's static, therefore enclosed in a companion object, not a class + val enclosingPackage = ctx.owner.enclosingPackageClass + + if definedPackage != enclosingPackage && !ctx.owner.ownersIterator.exists(_.derivesFrom(definedClass)) then + report.error(em"${StaticProtected} $sym which is defined in $definedPackage is inaccessible at runtime from $enclosingPackage", tree.srcPos) + end checkJavaStaticProtected + } import RefChecks.* @@ -1363,6 +1376,15 @@ class RefChecks extends MiniPhase { thisPhase => override def transformSelect(tree: tpd.Select)(using Context): tpd.Tree = if defn.ScalaBoxedClasses().contains(tree.qualifier.tpe.typeSymbol) && tree.name == nme.synchronized_ then report.warning(SynchronizedCallOnBoxedClass(tree), tree.srcPos) + checkJavaStaticProtected(tree) + tree + + override def transformApply(tree: tpd.Apply)(using Context): tpd.Apply = + checkJavaStaticProtected(tree) + tree + + override def transformAssign(tree: tpd.Assign)(using Context): tpd.Assign = + checkJavaStaticProtected(tree) tree } diff --git a/tests/neg/i18446.check b/tests/neg/i18446.check new file mode 100644 index 000000000000..748818136c11 --- /dev/null +++ b/tests/neg/i18446.check @@ -0,0 +1,4 @@ +-- Error: tests/neg/i18446/Test.scala:1:17 ----------------------------------------------------------------------------- +1 |val _ = foo.Task.poll() // error + | ^^^^^^^^^^^^^ + |protected method poll which is defined in package foo is inaccessible at runtime from package diff --git a/tests/neg/i18446/Task.java b/tests/neg/i18446/Task.java new file mode 100644 index 000000000000..c3ada81c143c --- /dev/null +++ b/tests/neg/i18446/Task.java @@ -0,0 +1,5 @@ +package foo; + +public abstract class Task{ + protected static void poll(){ System.out.println("Task"); } +} diff --git a/tests/neg/i18446/Test.scala b/tests/neg/i18446/Test.scala new file mode 100644 index 000000000000..b0932061cf54 --- /dev/null +++ b/tests/neg/i18446/Test.scala @@ -0,0 +1 @@ +val _ = foo.Task.poll() // error diff --git a/tests/run/i18446.check b/tests/run/i18446.check new file mode 100644 index 000000000000..fb172e33cde4 --- /dev/null +++ b/tests/run/i18446.check @@ -0,0 +1,2 @@ +Task +Task diff --git a/tests/run/i18446/Client.scala b/tests/run/i18446/Client.scala new file mode 100644 index 000000000000..1bad08006011 --- /dev/null +++ b/tests/run/i18446/Client.scala @@ -0,0 +1,7 @@ +// scalajs: --skip + +package bar; + +object Client extends foo.Task { + def run = foo.Task.poll() +} diff --git a/tests/run/i18446/Task.java b/tests/run/i18446/Task.java new file mode 100644 index 000000000000..c3ada81c143c --- /dev/null +++ b/tests/run/i18446/Task.java @@ -0,0 +1,5 @@ +package foo; + +public abstract class Task{ + protected static void poll(){ System.out.println("Task"); } +} diff --git a/tests/run/i18446/Test.scala b/tests/run/i18446/Test.scala new file mode 100644 index 000000000000..f6c85e39784c --- /dev/null +++ b/tests/run/i18446/Test.scala @@ -0,0 +1,5 @@ +// scalajs: --skip + +@main def Test = + foo.run + bar.Client.run diff --git a/tests/run/i18446/i18446.scala b/tests/run/i18446/i18446.scala new file mode 100644 index 000000000000..e67c680990cb --- /dev/null +++ b/tests/run/i18446/i18446.scala @@ -0,0 +1,7 @@ +// scalajs: --skip + +package foo + +def run = { + foo.Task.poll() +}