Skip to content

Commit

Permalink
ClassValueCompat to support systems without java.lang.ClassValue
Browse files Browse the repository at this point in the history
  • Loading branch information
nwk37011 committed Sep 17, 2021
1 parent 7d7daa6 commit c5a9d09
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 68 deletions.
10 changes: 10 additions & 0 deletions project/MimaFilters.scala
Expand Up @@ -78,6 +78,16 @@ object MimaFilters extends AutoPlugin {

// #9741
ProblemFilters.exclude[MissingClassProblem]("scala.collection.immutable.SeqMap$SeqMapBuilderImpl"), // private[SeqMap]

// #9752
ProblemFilters.exclude[MissingTypesProblem]("scala.reflect.ClassTag$cache$"),
ProblemFilters.exclude[MissingClassProblem]("scala.runtime.ModuleSerializationProxy$"),
ProblemFilters.exclude[MissingTypesProblem]("scala.reflect.runtime.JavaMirrors$JavaMirror$typeTagCache$"),
ProblemFilters.exclude[MissingTypesProblem]("scala.reflect.runtime.JavaMirrors$JavaMirror$typeTagCache$"),
ProblemFilters.exclude[MissingClassProblem]("scala.compat.ClassValueCompat"),
ProblemFilters.exclude[MissingClassProblem]("scala.compat.ClassValueCompat$ClassValueInterface"),
ProblemFilters.exclude[MissingClassProblem]("scala.compat.ClassValueCompat$JavaClassValue"),
ProblemFilters.exclude[MissingClassProblem]("scala.compat.ClassValueCompat$FallbackClassValue"),
)

override val buildSettings = Seq(
Expand Down
47 changes: 47 additions & 0 deletions src/library/scala/compat/ClassValueCompat.scala
@@ -0,0 +1,47 @@
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/

package scala.compat

import scala.util.Try

private[scala] abstract class ClassValueCompat[T] {

private def checkClassValueAvailability(): Boolean = Try {
Class.forName("java.lang.ClassValue", false, getClass.getClassLoader)
true
}.getOrElse(false)

private val instance = if (checkClassValueAvailability()) new JavaClassValue() else new FallbackClassValue()

private class JavaClassValue extends ClassValue[T] with ClassValueInterface {
override def computeValue(`type`: Class[_]): T = ClassValueCompat.this.computeValue(`type`)
}

private class FallbackClassValue extends ClassValueInterface {
override def get(param1Class: Class[_]): T = ClassValueCompat.this.get(param1Class)

override def remove(param1Class: Class[_]): Unit = {}
}

private trait ClassValueInterface {
def get(param1Class: Class[_]): T
def remove(param1Class: Class[_]): Unit
}

def get(`type`: Class[_]): T = instance.get(`type`)

def remove(`type`: Class[_]): Unit = instance.remove(`type`)

protected def computeValue(`type`: Class[_]): T

}
4 changes: 2 additions & 2 deletions src/library/scala/reflect/ClassTag.scala
Expand Up @@ -15,8 +15,8 @@ package reflect

import java.lang.{Class => jClass}
import java.lang.ref.{WeakReference => jWeakReference}

import scala.annotation.{implicitNotFound, nowarn}
import scala.compat.ClassValueCompat

/**
*
Expand Down Expand Up @@ -116,7 +116,7 @@ object ClassTag {
val Null : ClassTag[scala.Null] = Manifest.Null

private val cacheDisabled = java.lang.Boolean.getBoolean("scala.reflect.classtag.cache.disable")
private[this] object cache extends ClassValue[jWeakReference[ClassTag[_]]] {
private[this] object cache extends ClassValueCompat[jWeakReference[ClassTag[_]]] {
override def computeValue(runtimeClass: jClass[_]): jWeakReference[ClassTag[_]] =
new jWeakReference(computeTag(runtimeClass))

Expand Down
51 changes: 0 additions & 51 deletions src/library/scala/runtime/ModuleSerializationProxy.java

This file was deleted.

48 changes: 48 additions & 0 deletions src/library/scala/runtime/ModuleSerializationProxy.scala
@@ -0,0 +1,48 @@
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/

package scala.runtime

import java.io.Serializable
import java.security.PrivilegedActionException
import java.security.PrivilegedExceptionAction
import compat.ClassValueCompat

private[runtime] object ModuleSerializationProxy {
private val instances = new ClassValueCompat[Object] {
override protected def computeValue(`type`: Class[_]): Object = {
try {
java.security.AccessController.doPrivileged(new PrivilegedExceptionAction[Object] {
override def run(): Object = {
`type`.getField("MODULE$").get(null)
}
})
} catch {
case e: PrivilegedActionException =>
rethrowRuntime(e.getCause)
}
}
}

private def rethrowRuntime(e: Throwable): Object = {
val cause = e.getCause
cause match {
case exception: RuntimeException => throw exception
case _ => throw new RuntimeException(cause)
}
}
}

@SerialVersionUID(1L)
final class ModuleSerializationProxy(moduleClass: Class[_]) extends Serializable {
@SuppressWarnings(Array("unused")) private def readResolve = ModuleSerializationProxy.instances.get(moduleClass)
}
3 changes: 2 additions & 1 deletion src/reflect/scala/reflect/macros/Attachments.scala
Expand Up @@ -15,6 +15,7 @@ package reflect
package macros

import reflect.internal.util.Position
import scala.compat.ClassValueCompat

/**
* <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span>
Expand Down Expand Up @@ -109,7 +110,7 @@ abstract class Attachments { self =>
}

private object Attachments {
private val matchesTagCache = new ClassValue[Function1[Any, Boolean]] {
private val matchesTagCache = new ClassValueCompat[Function1[Any, Boolean]] {
override def computeValue(cls: Class[_]): Function[Any, Boolean] = cls.isInstance(_)
}
}
Expand Down
22 changes: 8 additions & 14 deletions src/reflect/scala/reflect/runtime/JavaMirrors.scala
Expand Up @@ -15,30 +15,24 @@ package reflect
package runtime

import scala.language.existentials

import scala.ref.WeakReference
import scala.collection.mutable.WeakHashMap
import scala.collection.immutable.ArraySeq

import java.lang.{ Class => jClass, Package => jPackage }
import java.lang.reflect.{
Method => jMethod, Constructor => jConstructor, Field => jField,
Member => jMember, Type => jType, TypeVariable => jTypeVariable,
Parameter => jParameter, GenericDeclaration, GenericArrayType,
ParameterizedType, WildcardType, AnnotatedElement }
import java.lang.annotation.{ Annotation => jAnnotation }
import java.lang.{Class => jClass, Package => jPackage}
import java.lang.reflect.{AnnotatedElement, GenericArrayType, GenericDeclaration, ParameterizedType, WildcardType, Constructor => jConstructor, Field => jField, Member => jMember, Method => jMethod, Parameter => jParameter, Type => jType, TypeVariable => jTypeVariable}
import java.lang.annotation.{Annotation => jAnnotation}
import java.io.IOException
import java.lang.ref.{ WeakReference => jWeakReference }

import scala.reflect.internal.{ JavaAccFlags, MissingRequirementError }
import java.lang.ref.{WeakReference => jWeakReference}
import scala.reflect.internal.{JavaAccFlags, MissingRequirementError}
import internal.pickling.ByteCodecs
import internal.pickling.UnPickler
import scala.collection.mutable.ListBuffer
import internal.Flags._
import ReflectionUtils._
import scala.annotation.nowarn
import scala.compat.ClassValueCompat
import scala.reflect.api.TypeCreator
import scala.runtime.{ BoxesRunTime, ScalaRunTime }
import scala.runtime.{BoxesRunTime, ScalaRunTime}

private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse with TwoWayCaches { thisUniverse: SymbolTable =>

Expand Down Expand Up @@ -120,7 +114,7 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive
private[this] val fieldCache = new TwoWayCache[jField, TermSymbol]
private[this] val tparamCache = new TwoWayCache[jTypeVariable[_ <: GenericDeclaration], TypeSymbol]

private[this] object typeTagCache extends ClassValue[jWeakReference[TypeTag[_]]]() {
private[this] object typeTagCache extends ClassValueCompat[jWeakReference[TypeTag[_]]]() {
val typeCreator = new ThreadLocal[TypeCreator]()

override protected def computeValue(cls: jClass[_]): jWeakReference[TypeTag[_]] = {
Expand Down

0 comments on commit c5a9d09

Please sign in to comment.