This is an automated email from the ASF dual-hosted git repository.
He-Pin pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko.git
The following commit(s) were added to refs/heads/main by this push:
new b8625a6143 fix: resolve LogSource for getClass results on Scala 3
(#3609)
b8625a6143 is described below
commit b8625a6143cd778af992497852e0c2fb55b7505e
Author: PJ Fanning <[email protected]>
AuthorDate: Sat Oct 10 06:26:26 2026 +0100
fix: resolve LogSource for getClass results on Scala 3 (#3609)
Motivation:
On Scala 3, `Logging(system, getClass)` fails to compile with
"Cannot find LogSource for Class[? <: Foo]". `getClass` returns a
wildcard class type, which Scala 3 does not match against
`LogSource.fromAnyClass[T]: LogSource[Class[T]]`. Scala 2.13 accepts it.
Modification:
- Make `object LogSource` extend a new `LogSourceCompat` trait.
- The Scala 3 `LogSourceCompat` adds a lower priority
`fromAnySubClass[T]: LogSource[Class[? <: T]]` implicit; the Scala 2.13
version is empty because Scala 2 reports that implicit as ambiguous
with `fromAnyClass`.
- `fromAnyClass` is unchanged; changing its signature instead fails MiMa
with an IncompatibleSignatureProblem.
- Add `LogSourceSpec`.
Result:
`Logging(system, getClass)` and `LogSource(getClass, system)` compile
on Scala 3.
Tests:
- `actor-tests/Test/testOnly org.apache.pekko.event.LogSourceSpec` on
Scala 3.3.8 without the fix: compile error "Cannot find LogSource for
Class[? <: ...LogsWithGetClass]"
- `actor-tests/Test/testOnly org.apache.pekko.event.LogSourceSpec
org.apache.pekko.event.LoggerSpec` with the fix: passed on 2.13.18
and 3.3.8
- `actor/mimaReportBinaryIssues`: passed on 2.13.18 and 3.3.8
- scalafmt run on changed files
References:
Fixes #1538
---
.../org/apache/pekko/event/LogSourceSpec.scala | 56 ++++++++++++++++++++++
.../org/apache/pekko/event/LogSourceCompat.scala | 28 +++++++++++
.../org/apache/pekko/event/LogSourceCompat.scala | 33 +++++++++++++
.../scala/org/apache/pekko/event/Logging.scala | 2 +-
4 files changed, 118 insertions(+), 1 deletion(-)
diff --git
a/actor-tests/src/test/scala/org/apache/pekko/event/LogSourceSpec.scala
b/actor-tests/src/test/scala/org/apache/pekko/event/LogSourceSpec.scala
new file mode 100644
index 0000000000..39aff56ff1
--- /dev/null
+++ b/actor-tests/src/test/scala/org/apache/pekko/event/LogSourceSpec.scala
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.pekko.event
+
+import org.apache.pekko
+import pekko.testkit.PekkoSpec
+
+object LogSourceSpec {
+ class LogsWithGetClass(system: pekko.actor.ActorSystem) {
+ // `getClass` returns `Class[? <: LogsWithGetClass]`, which did not
compile on Scala 3
+ val log: LoggingAdapter = Logging(system, getClass)
+ val logSource: (String, Class[?]) = LogSource(getClass, system)
+ }
+}
+
+class LogSourceSpec extends PekkoSpec {
+ import LogSourceSpec._
+
+ "LogSource" must {
+
+ "resolve an implicit LogSource for the result of getClass" in {
+ val subject = new LogsWithGetClass(system)
+ subject.logSource._1 should
===(s"LogSourceSpec$$LogsWithGetClass($system)")
+ subject.logSource._2 should ===(classOf[LogsWithGetClass])
+ subject.log.isInstanceOf[BusLogging] should ===(true)
+ }
+
+ "resolve an implicit LogSource for a class literal" in {
+ val logSource: (String, Class[?]) = LogSource(classOf[LogsWithGetClass])
+ logSource._1 should ===("LogSourceSpec$LogsWithGetClass")
+ logSource._2 should ===(classOf[LogsWithGetClass])
+ }
+
+ "resolve an implicit LogSource for a wildcard class" in {
+ val c: Class[?] = classOf[LogsWithGetClass]
+ val logSource: (String, Class[?]) = LogSource(c)
+ logSource._1 should ===("LogSourceSpec$LogsWithGetClass")
+ logSource._2 should ===(classOf[LogsWithGetClass])
+ }
+ }
+}
diff --git
a/actor/src/main/scala-2.13/org/apache/pekko/event/LogSourceCompat.scala
b/actor/src/main/scala-2.13/org/apache/pekko/event/LogSourceCompat.scala
new file mode 100644
index 0000000000..0d58b06dd7
--- /dev/null
+++ b/actor/src/main/scala-2.13/org/apache/pekko/event/LogSourceCompat.scala
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.pekko.event
+
+import org.apache.pekko.annotation.InternalApi
+
+/**
+ * INTERNAL API
+ *
+ * Scala 2 resolves [[LogSource.fromAnyClass]] for `getClass` results, so no
extra implicits are needed.
+ */
+@InternalApi
+private[event] trait LogSourceCompat
diff --git
a/actor/src/main/scala-3/org/apache/pekko/event/LogSourceCompat.scala
b/actor/src/main/scala-3/org/apache/pekko/event/LogSourceCompat.scala
new file mode 100644
index 0000000000..0fdd6d91a0
--- /dev/null
+++ b/actor/src/main/scala-3/org/apache/pekko/event/LogSourceCompat.scala
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.pekko.event
+
+import org.apache.pekko.annotation.InternalApi
+
+/**
+ * INTERNAL API
+ *
+ * Lower priority implicits for [[LogSource]]. Scala 3 does not match
`getClass`, which returns
+ * `Class[? <: T]`, against [[LogSource.fromAnyClass]]. This is not in the
shared sources because
+ * Scala 2 reports it as ambiguous with `fromAnyClass`.
+ */
+@InternalApi
+private[event] trait LogSourceCompat {
+ implicit def fromAnySubClass[T]: LogSource[Class[? <: T]] =
+ LogSource.fromClass.asInstanceOf[LogSource[Class[? <: T]]]
+}
diff --git a/actor/src/main/scala/org/apache/pekko/event/Logging.scala
b/actor/src/main/scala/org/apache/pekko/event/Logging.scala
index 1c4b0f86d5..5d14018dc3 100644
--- a/actor/src/main/scala/org/apache/pekko/event/Logging.scala
+++ b/actor/src/main/scala/org/apache/pekko/event/Logging.scala
@@ -324,7 +324,7 @@ class DummyClassForStringSources
* <li>anything else gives compile error unless implicit
[[pekko.event.LogSource]] is in scope for it</li>
* </ul>
*/
-object LogSource {
+object LogSource extends LogSourceCompat {
implicit val fromString: LogSource[String] = new LogSource[String] {
def genString(s: String) = s
override def genString(s: String, system: ActorSystem) = s + "(" + system
+ ")"
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]