diff options
-rw-r--r-- | src/reflect/scala/reflect/internal/Constants.scala | 9 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Definitions.scala | 7 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Types.scala | 39 | ||||
-rw-r--r-- | test/files/run/constant-type.check | 30 | ||||
-rw-r--r-- | test/files/run/constant-type.scala | 17 |
5 files changed, 58 insertions, 44 deletions
diff --git a/src/reflect/scala/reflect/internal/Constants.scala b/src/reflect/scala/reflect/internal/Constants.scala index 61fa553484..4e232e486b 100644 --- a/src/reflect/scala/reflect/internal/Constants.scala +++ b/src/reflect/scala/reflect/internal/Constants.scala @@ -73,13 +73,8 @@ trait Constants extends api.Constants { case DoubleTag => DoubleClass.tpe case StringTag => StringClass.tpe case NullTag => NullClass.tpe - case ClazzTag => ClassType(value.asInstanceOf[Type]) - case EnumTag => - // given (in java): "class A { enum E { VAL1 } }" - // - symbolValue: the symbol of the actual enumeration value (VAL1) - // - .owner: the ModuleClasSymbol of the enumeration (object E) - // - .linkedClassOfClass: the ClassSymbol of the enumeration (class E) - symbolValue.owner.linkedClassOfClass.tpe + case ClazzTag => ClassType(typeValue) + case EnumTag => EnumType(symbolValue) } /** We need the equals method to take account of tags as well as values. diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 2db8c29a63..b607f8cad9 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -713,6 +713,13 @@ trait Definitions extends api.StandardDefinitions { if (phase.erasedTypes || forMSIL) ClassClass.tpe else appliedType(ClassClass, arg) + def EnumType(sym: Symbol) = + // given (in java): "class A { enum E { VAL1 } }" + // - sym: the symbol of the actual enumeration value (VAL1) + // - .owner: the ModuleClassSymbol of the enumeration (object E) + // - .linkedClassOfClass: the ClassSymbol of the enumeration (class E) + sym.owner.linkedClassOfClass.tpe + def vmClassType(arg: Type): Type = ClassType(arg) def vmSignature(sym: Symbol, info: Type): String = signature(info) // !!! diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index ee488c9d18..4311f1dd4f 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -2018,45 +2018,10 @@ trait Types extends api.Types { self: SymbolTable => override def kind = "ConstantType" } - final class UniqueConstantType(value: Constant) extends ConstantType(value) { - /** Save the type of `value`. For Java enums, it depends on finding the linked class, - * which might not be found after `flatten`. */ - private lazy val _tpe: Type = value.tpe - override def underlying: Type = _tpe - } + final class UniqueConstantType(value: Constant) extends ConstantType(value) object ConstantType extends ConstantTypeExtractor { - def apply(value: Constant): ConstantType = { - val tpe = new UniqueConstantType(value) - if (value.tag == ClazzTag) { - // if we carry a classOf, we might be in trouble - // http://groups.google.com/group/scala-internals/browse_thread/thread/45185b341aeb6a30 - // I don't have time for a thorough fix, so I put a hacky workaround here - val alreadyThere = uniques findEntry tpe - if ((alreadyThere ne null) && (alreadyThere ne tpe) && (alreadyThere.toString != tpe.toString)) { - // we need to remove a stale type that has the same hashcode as we do - // HashSet doesn't support removal, and this makes our task non-trivial - // also we cannot simply recreate it, because that'd skew hashcodes (that change over time, omg!) - // the only solution I can see is getting into the underlying array and sneakily manipulating it - val ftable = uniques.getClass.getDeclaredFields().find(f => f.getName endsWith "table").get - ftable.setAccessible(true) - val table = ftable.get(uniques).asInstanceOf[Array[AnyRef]] - def overwrite(hc: Int, x: Type) { - def index(x: Int): Int = math.abs(x % table.length) - var h = index(hc) - var entry = table(h) - while (entry ne null) { - if (x == entry) - table(h) = x - h = index(h + 1) - entry = table(h) - } - } - overwrite(tpe.##, tpe) - } - } - unique(tpe).asInstanceOf[ConstantType] - } + def apply(value: Constant) = unique(new UniqueConstantType(value)) } /* Syncnote: The `volatile` var and `pendingVolatiles` mutable set need not be protected diff --git a/test/files/run/constant-type.check b/test/files/run/constant-type.check new file mode 100644 index 0000000000..dfd8be5297 --- /dev/null +++ b/test/files/run/constant-type.check @@ -0,0 +1,30 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> :power +** Power User mode enabled - BEEP WHIR GYVE ** +** :phase has been set to 'typer'. ** +** scala.tools.nsc._ has been imported ** +** global._, definitions._ also imported ** +** Try :help, :vals, power.<tab> ** + +scala> val s = transformedType(StringClass.toType).asInstanceOf[Type] +s: $r.intp.global.Type = String + +scala> { println(afterPhase(currentRun.erasurePhase)(ConstantType(Constant(s)))) } +Class[String](classOf[java.lang.String]) + +scala> { afterPhase(currentRun.erasurePhase)(println(ConstantType(Constant(s)))) } +Class(classOf[java.lang.String]) + +scala> { ConstantType(Constant(s)); println(afterPhase(currentRun.erasurePhase)(ConstantType(Constant(s)))); } +Class[String](classOf[java.lang.String]) + +scala> { ConstantType(Constant(s)); afterPhase(currentRun.erasurePhase)(println(ConstantType(Constant(s)))); } +Class(classOf[java.lang.String]) + +scala> + +scala> diff --git a/test/files/run/constant-type.scala b/test/files/run/constant-type.scala new file mode 100644 index 0000000000..84539e2895 --- /dev/null +++ b/test/files/run/constant-type.scala @@ -0,0 +1,17 @@ +import scala.tools.partest.ReplTest + +// see the commit message to understand what this stuff is about +// just a quick note: +// transformedType returns an erased version of the type +// as explained in the commit message, Type.erasure won't do for this test +// because it does some postprocessing to the result of transformedType +object Test extends ReplTest { + def code = """ +:power +val s = transformedType(StringClass.toType).asInstanceOf[Type] +{ println(afterPhase(currentRun.erasurePhase)(ConstantType(Constant(s)))) } +{ afterPhase(currentRun.erasurePhase)(println(ConstantType(Constant(s)))) } +{ ConstantType(Constant(s)); println(afterPhase(currentRun.erasurePhase)(ConstantType(Constant(s)))); } +{ ConstantType(Constant(s)); afterPhase(currentRun.erasurePhase)(println(ConstantType(Constant(s)))); } + """ +} |