Permalink
Browse files

Be discriminating about custom hashcodes.

If there are no primitives, use the regular boxy one.
  • Loading branch information...
paulp committed May 10, 2012
1 parent 1bff570 commit 4db08212f63d3a5cd5467b91b25ff5b36e79fd5c
@@ -1207,7 +1207,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
def isPrimitiveValueClass(sym: Symbol) = ScalaValueClasses contains sym
def isNonUnitValueClass(sym: Symbol) = isPrimitiveValueClass(sym) && (sym != UnitClass)
def isSpecializableClass(sym: Symbol) = isPrimitiveValueClass(sym) || (sym == AnyRefClass)
def isScalaValueType(tp: Type) = ScalaValueClasses contains tp.typeSymbol
def isPrimitiveValueType(tp: Type) = isPrimitiveValueClass(tp.typeSymbol)
/** Is symbol a boxed value class, e.g. java.lang.Integer? */
def isBoxedValueClass(sym: Symbol) = boxedValueClassesSet(sym)
@@ -236,7 +236,7 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL {
mkMethodCall(
PredefModule,
wrapArrayMethodName(elemtp),
if (isScalaValueType(elemtp)) Nil else List(elemtp),
if (isPrimitiveValueType(elemtp)) Nil else List(elemtp),
List(tree)
)
}
@@ -261,7 +261,7 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL {
* elem type elemtp to expected type pt.
*/
def mkCastArray(tree: Tree, elemtp: Type, pt: Type) =
if (elemtp.typeSymbol == AnyClass && isScalaValueType(tree.tpe.typeArgs.head))
if (elemtp.typeSymbol == AnyClass && isPrimitiveValueType(tree.tpe.typeArgs.head))
mkCast(mkRuntimeCall(nme.toObjectArray, List(tree)), pt)
else
mkCast(tree, pt)
@@ -179,7 +179,7 @@ trait ModelFactoryImplicitSupport {
hardcoded.arraySkipConversions.contains(conv.conversionQualifiedName))
// Filter out non-sensical conversions from value types
if (isScalaValueType(sym.tpe))
if (isPrimitiveValueType(sym.tpe))
conversions = conversions.filter((ic: ImplicitConversion) =>
hardcoded.valueClassFilter(sym.nameString, ic.conversionQualifiedName))
@@ -619,7 +619,7 @@ abstract class Erasure extends AddInterfaces
tree.duplicate setType pt
} else if (tree.tpe != null && tree.tpe.typeSymbol == ArrayClass && pt.typeSymbol == ArrayClass) {
// See SI-2386 for one example of when this might be necessary.
val needsExtraCast = isScalaValueType(tree.tpe.typeArgs.head) && !isScalaValueType(pt.typeArgs.head)
val needsExtraCast = isPrimitiveValueType(tree.tpe.typeArgs.head) && !isPrimitiveValueType(pt.typeArgs.head)
val tree1 = if (needsExtraCast) gen.mkRuntimeCall(nme.toObjectArray, List(tree)) else tree
gen.mkAttributedCast(tree1, pt)
} else gen.mkAttributedCast(tree, pt)
@@ -67,7 +67,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
import definitions.{
RootClass, BooleanClass, UnitClass, ArrayClass,
ScalaValueClasses, isPrimitiveValueClass, isScalaValueType,
ScalaValueClasses, isPrimitiveValueClass, isPrimitiveValueType,
SpecializedClass, UnspecializedClass, AnyRefClass, ObjectClass, AnyRefModule,
GroupOfSpecializable, uncheckedVarianceClass, ScalaInlineClass
}
@@ -145,7 +145,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
def includes(t1: TypeEnv, t2: TypeEnv) = t1 forall {
case (sym, tpe) =>
t2 get sym exists { t2tp =>
(tpe == t2tp) || !(isScalaValueType(tpe) || isScalaValueType(t2tp)) // u.t.b. (t2tp <:< AnyRefClass.tpe)
(tpe == t2tp) || !(isPrimitiveValueType(tpe) || isPrimitiveValueType(t2tp)) // u.t.b. (t2tp <:< AnyRefClass.tpe)
}
}
@@ -266,7 +266,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* specialized type.
*/
def survivingArgs(sym: Symbol, args: List[Type]): List[Type] =
for ((tvar, tpe) <- sym.info.typeParams.zip(args) if !tvar.isSpecialized || !isScalaValueType(tpe))
for ((tvar, tpe) <- sym.info.typeParams.zip(args) if !tvar.isSpecialized || !isPrimitiveValueType(tpe))
yield tpe
val specializedType = new TypeMap {
@@ -448,7 +448,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Type parameters that survive when specializing in the specified environment. */
def survivingParams(params: List[Symbol], env: TypeEnv) =
params.filter(p => !p.isSpecialized || !isScalaValueType(env(p)))
params.filter(p => !p.isSpecialized || !isPrimitiveValueType(env(p)))
/** Produces the symbols from type parameters `syms` of the original owner,
* in the given type environment `env`. The new owner is `nowner`.
@@ -1588,7 +1588,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
// val (_, origtparams) = splitParams(source.typeParams)
val env = typeEnv(symbol)
val boundTvars = env.keySet
val origtparams = source.typeParams.filter(tparam => !boundTvars(tparam) || !isScalaValueType(env(tparam)))
val origtparams = source.typeParams.filter(tparam => !boundTvars(tparam) || !isPrimitiveValueType(env(tparam)))
if (origtparams.nonEmpty || symbol.typeParams.nonEmpty)
debuglog("substituting " + origtparams + " for " + symbol.typeParams)
@@ -254,14 +254,20 @@ trait SyntheticMethods extends ast.TreeDSL {
Block(valdef :: mixes, finish)
}
}
def chooseHashcode = {
if (accessors exists (x => isPrimitiveValueType(x.tpe.finalResultType)))
specializedHashcode
else
forwardToRuntime(Object_hashCode)
}
def valueClassMethods = List(
Any_hashCode -> (() => hashCodeDerivedValueClassMethod),
Any_equals -> (() => equalsDerivedValueClassMethod)
)
def caseClassMethods = productMethods ++ productNMethods ++ Seq(
Object_hashCode -> (() => specializedHashcode),
Object_hashCode -> (() => chooseHashcode),
Object_toString -> (() => forwardToRuntime(Object_toString)),
Object_equals -> (() => equalsCaseClassMethod)
)

0 comments on commit 4db0821

Please sign in to comment.