diff options
author | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2013-10-29 05:39:42 -0700 |
---|---|---|
committer | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2013-10-29 05:39:42 -0700 |
commit | 2c1e9af40e252bd9ed5bfe4305991ee6f7d25636 (patch) | |
tree | 79de3e45aa44ad0d1a8bee6d6bef16de283b1983 /src | |
parent | 6d4b08b4a03dcb623372ab60acf5ca016b068bed (diff) | |
parent | 4acac088dcbdce5b6a5b99a31a15c85a2715bbb6 (diff) | |
download | scala-2c1e9af40e252bd9ed5bfe4305991ee6f7d25636.tar.gz scala-2c1e9af40e252bd9ed5bfe4305991ee6f7d25636.tar.bz2 scala-2c1e9af40e252bd9ed5bfe4305991ee6f7d25636.zip |
Merge pull request #3082 from retronym/ticket/6385
SI-6385 Avoid bridges to identical signatures over value classes
Diffstat (limited to 'src')
5 files changed, 34 insertions, 24 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index e2902a74b8..f0d3db1296 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -545,8 +545,7 @@ abstract class Erasure extends AddInterfaces ldef setType ldef.rhs.tpe case _ => val tree1 = tree.tpe match { - case ErasedValueType(tref) => - val clazz = tref.sym + case ErasedValueType(clazz, _) => New(clazz, cast(tree, underlyingOfValueClass(clazz))) case _ => tree.tpe.typeSymbol match { @@ -597,9 +596,7 @@ abstract class Erasure extends AddInterfaces ldef setType ldef.rhs.tpe case _ => val tree1 = pt match { - case ErasedValueType(tref) => - val clazz = tref.sym - lazy val underlying = underlyingOfValueClass(clazz) + case ErasedValueType(clazz, underlying) => val tree0 = if (tree.tpe.typeSymbol == NullClass && isPrimitiveValueClass(underlying.typeSymbol)) { @@ -697,13 +694,11 @@ abstract class Erasure extends AddInterfaces case Apply(ta @ TypeApply(sel @ Select(qual, name), List(targ)), List()) if tree.symbol == Any_asInstanceOf => val qual1 = typedQualifier(qual, NOmode, ObjectTpe) // need to have an expected type, see #3037 - + // !!! Make pending/run/t5866b.scala work. The fix might be here and/or in unbox1. if (isPrimitiveValueType(targ.tpe) || isErasedValueType(targ.tpe)) { val noNullCheckNeeded = targ.tpe match { - case ErasedValueType(tref) => - enteringPhase(currentRun.erasurePhase) { - isPrimitiveValueClass(erasedValueClassArg(tref).typeSymbol) - } + case ErasedValueType(_, underlying) => + isPrimitiveValueClass(underlying.typeSymbol) case _ => true } @@ -724,7 +719,7 @@ abstract class Erasure extends AddInterfaces case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) if tree.symbol == Any_isInstanceOf => targ.tpe match { - case ErasedValueType(tref) => targ.setType(tref.sym.tpe) + case ErasedValueType(clazz, _) => targ.setType(clazz.tpe) case _ => } tree @@ -787,11 +782,11 @@ abstract class Erasure extends AddInterfaces (tree.attachments.get[TypeRefAttachment]: @unchecked) match { case Some(itype) => val tref = itype.tpe - val argPt = enteringPhase(currentRun.erasurePhase)(erasedValueClassArg(tref)) + val argPt = enteringErasure(erasedValueClassArg(tref)) log(s"transforming inject $arg -> $tref/$argPt") val result = typed(arg, mode, argPt) log(s"transformed inject $arg -> $tref/$argPt = $result:${result.tpe}") - return result setType ErasedValueType(tref) + return result setType ErasedValueType(tref.sym, result.tpe) } case _ => diff --git a/src/compiler/scala/tools/nsc/transform/PostErasure.scala b/src/compiler/scala/tools/nsc/transform/PostErasure.scala index 96263f3c0c..cc78e27282 100644 --- a/src/compiler/scala/tools/nsc/transform/PostErasure.scala +++ b/src/compiler/scala/tools/nsc/transform/PostErasure.scala @@ -22,7 +22,7 @@ trait PostErasure extends InfoTransform with TypingTransformers { object elimErasedValueType extends TypeMap { def apply(tp: Type) = tp match { case ConstantType(Constant(tp: Type)) => ConstantType(Constant(apply(tp))) - case ErasedValueType(tref) => enteringErasure(erasure.erasedValueClassArg(tref)) + case ErasedValueType(_, underlying) => underlying case _ => mapOver(tp) } } diff --git a/src/reflect/scala/reflect/internal/Constants.scala b/src/reflect/scala/reflect/internal/Constants.scala index 511b39b8c6..85d0efdcba 100644 --- a/src/reflect/scala/reflect/internal/Constants.scala +++ b/src/reflect/scala/reflect/internal/Constants.scala @@ -223,7 +223,15 @@ trait Constants extends api.Constants { case ClazzTag => def show(tpe: Type) = "classOf[" + signature(tpe) + "]" typeValue match { - case ErasedValueType(orig) => show(orig) + case ErasedValueType(clazz, underlying) => + // A note on tpe_* usage here: + // + // We've intentionally erased the type arguments to the value class so that different + // instantiations of a particular value class that erase to the same underlying type + // don't result in spurious bridges (e.g. run/t6385.scala). I don't think that matters; + // printing trees of `classOf[ValueClass[String]]` shows `classOf[ValueClass]` at phase + // erasure both before and after the use of `tpe_*` here. + show(clazz.tpe_*) case _ => show(typeValue) } case CharTag => "'" + escapedChar(charValue) + "'" diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 59d1e13142..653030e602 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -3341,18 +3341,25 @@ trait Types /** A temporary type representing the erasure of a user-defined value type. * Created during phase erasure, eliminated again in posterasure. * - * @param original The underlying type before erasure + * SI-6385 Erasure's creation of bridges considers method signatures `exitingErasure`, + * which contain `ErasedValueType`-s. In order to correctly consider the overriding + * and overriden signatures as equivalent in `run/t6385.scala`, it is critical that + * this type contains the erasure of the wrapped type, rather than the unerased type + * of the value class itself, as was originally done. + * + * @param valueClazz The value class symbol + * @param erasedUnderlying The erased type of the unboxed value */ - abstract case class ErasedValueType(original: TypeRef) extends UniqueType { - override def safeToString = "ErasedValueType("+original+")" + abstract case class ErasedValueType(valueClazz: Symbol, erasedUnderlying: Type) extends UniqueType { + override def safeToString = s"ErasedValueType($valueClazz, $erasedUnderlying)" } - final class UniqueErasedValueType(original: TypeRef) extends ErasedValueType(original) + final class UniqueErasedValueType(valueClazz: Symbol, erasedUnderlying: Type) extends ErasedValueType(valueClazz, erasedUnderlying) object ErasedValueType { - def apply(original: TypeRef): Type = { - assert(original.sym ne NoSymbol, "ErasedValueType over NoSymbol") - unique(new UniqueErasedValueType(original)) + def apply(valueClazz: Symbol, erasedUnderlying: Type): Type = { + assert(valueClazz ne NoSymbol, "ErasedValueType over NoSymbol") + unique(new UniqueErasedValueType(valueClazz, erasedUnderlying)) } } diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala index 185e2c3d1e..4aefc105e3 100644 --- a/src/reflect/scala/reflect/internal/transform/Erasure.scala +++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala @@ -257,11 +257,11 @@ trait Erasure { /** This is used as the Scala erasure during the erasure phase itself * It differs from normal erasure in that value classes are erased to ErasedValueTypes which - * are then later converted to the underlying parameter type in phase posterasure. + * are then later unwrapped to the underlying parameter type in phase posterasure. */ object specialScalaErasure extends ScalaErasureMap { override def eraseDerivedValueClassRef(tref: TypeRef): Type = - ErasedValueType(tref) + ErasedValueType(tref.sym, erasedValueClassArg(tref)) } object javaErasure extends JavaErasureMap |