From e8733764bc13dd556b81905adb04d70f5ec9111f Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 8 Jan 2024 18:16:00 +0000 Subject: [PATCH 1/3] Consider static and non-static methods as non-double def --- .../src/dotty/tools/dotc/typer/Checking.scala | 3 ++- tests/run/19394.scala | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/run/19394.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 3e5d65070a80..9594fe3f5373 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1167,7 +1167,8 @@ trait Checking { def javaFieldMethodPair = decl.is(JavaDefined) && other.is(JavaDefined) && decl.is(Method) != other.is(Method) - if (decl.matches(other) && !javaFieldMethodPair) { + def staticNonStaticPair = decl.isScalaStatic != other.isScalaStatic + if (decl.matches(other) && !javaFieldMethodPair && !staticNonStaticPair) { def doubleDefError(decl: Symbol, other: Symbol): Unit = if (!decl.info.isErroneous && !other.info.isErroneous) report.error(DoubleDefinition(decl, other, cls), decl.srcPos) diff --git a/tests/run/19394.scala b/tests/run/19394.scala new file mode 100644 index 000000000000..c57a9471f345 --- /dev/null +++ b/tests/run/19394.scala @@ -0,0 +1,21 @@ +import scala.annotation.{ static, targetName } + +class Foo +object Foo: + @static def foo: String = "foo" + @targetName("foo") def fooBincompat: String = foo + +class Bar +object Bar: + @static def bar: String = "bar" + def bar: String = bar + +object Test: + def main(args: Array[String]): Unit = + assert(Foo.foo == "foo") + assert(classOf[Foo].getMethod("foo").invoke(null) == "foo") // static + assert(Foo.getClass.getMethod("foo").invoke(Foo) == "foo") // instance, on module class + + assert(Bar.bar == "bar") + assert(classOf[Bar].getMethod("bar").invoke(null) == "bar") + assert(Bar.getClass.getMethod("bar").invoke(Bar) == "bar") From c6e103a30193ee8f55653696da20ffce1b740cf6 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 9 Jan 2024 15:59:30 +0000 Subject: [PATCH 2/3] Fix static method js backend --- compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala | 6 +++++- tests/run/19394.scala | 9 ++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index 54af9f8dd088..d1f5f1b63d26 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -793,6 +793,9 @@ class JSCodeGen()(using genCtx: Context) { name.name }.toSet + val staticNames = moduleClass.companionClass.info.allMembers + .collect { case d if d.name.isTermName && d.symbol.isScalaStatic => d.name }.toSet + val members = { moduleClass.info.membersBasedOnFlags(required = Flags.Method, excluded = Flags.ExcludedForwarder).map(_.symbol) @@ -815,6 +818,7 @@ class JSCodeGen()(using genCtx: Context) { || hasAccessBoundary || isOfJLObject || m.hasAnnotation(jsdefn.JSNativeAnnot) || isDefaultParamOfJSNativeDef // #4557 + || staticNames(m.name) } val forwarders = for { @@ -4769,7 +4773,7 @@ class JSCodeGen()(using genCtx: Context) { } private def isMethodStaticInIR(sym: Symbol): Boolean = - sym.is(JavaStatic) + sym.is(JavaStatic) || sym.isScalaStatic /** Generate a Class[_] value (e.g. coming from classOf[T]) */ private def genClassConstant(tpe: Type)(implicit pos: Position): js.Tree = diff --git a/tests/run/19394.scala b/tests/run/19394.scala index c57a9471f345..7c6938c97503 100644 --- a/tests/run/19394.scala +++ b/tests/run/19394.scala @@ -13,9 +13,8 @@ object Bar: object Test: def main(args: Array[String]): Unit = assert(Foo.foo == "foo") - assert(classOf[Foo].getMethod("foo").invoke(null) == "foo") // static - assert(Foo.getClass.getMethod("foo").invoke(Foo) == "foo") // instance, on module class - assert(Bar.bar == "bar") - assert(classOf[Bar].getMethod("bar").invoke(null) == "bar") - assert(Bar.getClass.getMethod("bar").invoke(Bar) == "bar") + + import scala.reflect.Selectable.reflectiveSelectable + assert(Foo.asInstanceOf[{ def foo: String }].foo == "foo") + assert(Bar.asInstanceOf[{ def bar: String }].bar == "bar") From abffedcf291a9ecf10cbd45cc32ce458635e06e0 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 12 Jan 2024 15:12:10 +0000 Subject: [PATCH 3/3] Add other cases fixed by js backend fix --- tests/run/i17332.scala | 18 ++++++++++++++++++ tests/run/{19394.scala => i19394.scala} | 0 tests/run/i19396.scala | 16 ++++++++++++++++ tests/run/static/i2054.scala | 2 -- 4 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 tests/run/i17332.scala rename tests/run/{19394.scala => i19394.scala} (100%) create mode 100644 tests/run/i19396.scala diff --git a/tests/run/i17332.scala b/tests/run/i17332.scala new file mode 100644 index 000000000000..b609bf215d80 --- /dev/null +++ b/tests/run/i17332.scala @@ -0,0 +1,18 @@ +package foo { + +import annotation.static + +class MirrorHelpers + +object MirrorHelpers: + + @static + def throwStuff(i: Int): Any = throw new NoSuchElementException(String.valueOf(i)) + +} + +@main def Test = + try + foo.MirrorHelpers.throwStuff(23) + ??? // ko + catch case ex: NoSuchElementException if ex.getMessage == "23" => () // ok diff --git a/tests/run/19394.scala b/tests/run/i19394.scala similarity index 100% rename from tests/run/19394.scala rename to tests/run/i19394.scala diff --git a/tests/run/i19396.scala b/tests/run/i19396.scala new file mode 100644 index 000000000000..2fcf23022b0f --- /dev/null +++ b/tests/run/i19396.scala @@ -0,0 +1,16 @@ +import scala.annotation.static + +class Foo + +object Foo { + @static def foo = "foo" +} + +class Bar { + def bar = Foo.foo +} + +object Test: + def main(args: Array[String]): Unit = + Foo.foo + Bar().bar diff --git a/tests/run/static/i2054.scala b/tests/run/static/i2054.scala index dbf88b0efa14..84ebf5d9efeb 100644 --- a/tests/run/static/i2054.scala +++ b/tests/run/static/i2054.scala @@ -1,5 +1,3 @@ -// scalajs: --skip --pending - import scala.annotation.static class Test