diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2012-04-16 11:52:25 +0200 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2012-04-17 21:27:40 +0200 |
commit | e408aa9ccaba736d0f85b7afecd288c3873d05bb (patch) | |
tree | b115dd0261cfe4f8a2f741d1cb4afd1412886e48 /src/library | |
parent | 17fa0b13480c7dd9796885e32ec562e162253350 (diff) | |
download | scala-e408aa9ccaba736d0f85b7afecd288c3873d05bb.tar.gz scala-e408aa9ccaba736d0f85b7afecd288c3873d05bb.tar.bz2 scala-e408aa9ccaba736d0f85b7afecd288c3873d05bb.zip |
adds erasures to concrete type tags
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/reflect/ClassTag.scala | 4 | ||||
-rw-r--r-- | src/library/scala/reflect/DynamicProxy.scala | 20 | ||||
-rw-r--r-- | src/library/scala/reflect/TagMaterialization.scala | 49 | ||||
-rwxr-xr-x | src/library/scala/reflect/api/Symbols.scala | 10 | ||||
-rw-r--r-- | src/library/scala/reflect/api/TreeBuildUtil.scala | 20 | ||||
-rw-r--r-- | src/library/scala/reflect/api/TypeTags.scala | 43 | ||||
-rwxr-xr-x | src/library/scala/reflect/api/Types.scala | 14 | ||||
-rw-r--r-- | src/library/scala/reflect/makro/Reifiers.scala | 4 | ||||
-rw-r--r-- | src/library/scala/reflect/makro/internal/Utils.scala | 45 | ||||
-rw-r--r-- | src/library/scala/reflect/package.scala | 2 |
10 files changed, 96 insertions, 115 deletions
diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index 7138837f0d..fe8a16a484 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -117,6 +117,10 @@ object ClassTag { case _ => apply[T](rm.typeToClass(tpe.erasure)) } + def apply[T](ttag: rm.ConcreteTypeTag[T]): ClassTag[T] = + if (ttag.erasure != null) ClassTag[T](ttag.erasure) + else ClassTag[T](ttag.tpe) + implicit def toDeprecatedClassManifestApis[T](ctag: ClassTag[T]): DeprecatedClassManifestApis[T] = new DeprecatedClassManifestApis[T](ctag) } diff --git a/src/library/scala/reflect/DynamicProxy.scala b/src/library/scala/reflect/DynamicProxy.scala index ffd1e7a39f..02872977f5 100644 --- a/src/library/scala/reflect/DynamicProxy.scala +++ b/src/library/scala/reflect/DynamicProxy.scala @@ -2,13 +2,13 @@ package scala.reflect /** * A dynamic proxy which redirects method calls and attribute access to a given * target object at runtime using reflection. - * + * * Usage example: - * + * * object x{ def hello = "hello world" } * val d = new DynamicProxy{ val dynamicProxyTarget = x } * assert( d.hello == "hello world" ) - * + * * Not supported (yet): * - implicit conversions and parameters * - multiple arguments lists @@ -26,7 +26,7 @@ trait DynamicProxy extends Dynamic{ object DynamicReflectBoxed{ implicit def box[@specialized T]( v:T ) = DynamicReflectBoxed( v.getClass, v ) } - + def selectDynamic( method:String ) = { val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method).encodedName ) invoke( dynamicProxyTarget, symbol )() @@ -38,7 +38,7 @@ trait DynamicProxy extends Dynamic{ } def applyDynamic( method:String )( args:DynamicReflectBoxed* ) : Any - = applyDynamicNamed( method )( args.map( value => ("",value) ) :_* ) + = applyDynamicNamed( method )( args.map( value => ("",value) ) :_* ) def applyDynamicNamed( method:String )( args:(String,DynamicReflectBoxed)* ) : Any = { val class_ = dynamicProxyTarget.getClass @@ -48,27 +48,27 @@ trait DynamicProxy extends Dynamic{ if(args.size == 0){ invoke( dynamicProxyTarget, symbol )() } else { - val call = + val call = Apply( Select( TypeApply( Select( Select( - Ident(newFreeTerm("__this", symbolForName("scala.reflect.DynamicProxy").asType, this, null)) + Ident(newFreeTerm("__this", symbolForName("scala.reflect.DynamicProxy").asType, this)) , newTermName("dynamicProxyTarget") - ), + ), newTermName("asInstanceOf") ) , List(TypeTree().setType(classToType(class_))) ) ,newTermName(method).encodedName ) ,args.map{ case(name,box) => - val value = Ident(newFreeTerm("__arg"+({i+=1;i}.toString), classToType(box.class_), box.value, null)) + val value = Ident(newFreeTerm("__arg"+({i+=1;i}.toString), classToType(box.class_), box.value)) if( name == "" ) value else AssignOrNamedArg( Ident(name), value ) }.toList ) toolbox.runExpr( call ) - } + } } } diff --git a/src/library/scala/reflect/TagMaterialization.scala b/src/library/scala/reflect/TagMaterialization.scala index aede00020f..a7237223f1 100644 --- a/src/library/scala/reflect/TagMaterialization.scala +++ b/src/library/scala/reflect/TagMaterialization.scala @@ -65,59 +65,22 @@ object TagMaterialization { val ConcreteTypeTagClass = selectType(TypeTagsClass, "ConcreteTypeTag") val ConcreteTypeTagModule = selectTerm(TypeTagsClass, "ConcreteTypeTag") - def materializeClassTag(tpe: Type): Tree = { - val prefix = gen.mkAttributedRef(Reflect_mirror) setType singleType(Reflect_mirror.owner.thisPrefix, Reflect_mirror) - materializeClassTag(prefix, tpe) - } - - def materializeClassTag(prefix: Tree, tpe: Type): Tree = { - val typetagInScope = c.inferImplicitValue(appliedType(typeRef(prefix.tpe, ConcreteTypeTagClass, Nil), List(tpe))) - def typetagIsSynthetic(tree: Tree) = tree.isInstanceOf[Block] || (tree exists (sub => sub.symbol == TypeTagModule || sub.symbol == ConcreteTypeTagModule)) - typetagInScope match { - case success if !success.isEmpty && !typetagIsSynthetic(success) => - val factory = TypeApply(Select(Ident(ClassTagModule), newTermName("apply")), List(TypeTree(tpe))) - Apply(factory, List(Select(typetagInScope, newTermName("tpe")))) - case _ => - val result = - tpe match { - case coreTpe if coreTags contains coreTpe => - Select(Ident(ClassTagModule), coreTags(coreTpe)) - case _ => - if (tpe.typeSymbol == ArrayClass) { - val componentTpe = tpe.typeArguments(0) - val classtagInScope = c.inferImplicitValue(appliedType(typeRef(NoPrefix, ClassTagClass, Nil), List(componentTpe))) - val componentTag = classtagInScope orElse materializeClassTag(prefix, componentTpe) - Select(componentTag, newTermName("wrap")) - } else { - // [Eugene] what's the intended behavior? there's no spec on ClassManifests - // for example, should we ban Array[T] or should we tag them with Array[AnyRef]? - // if its the latter, what should be the result of tagging Array[T] where T <: Int? - if (tpe.typeSymbol.isAbstractType) fail("tpe is an abstract type") - val erasure = - if (tpe.typeSymbol.isDerivedValueClass) tpe // [Eugene to Martin] is this correct? - else tpe.erasure.normalize // necessary to deal with erasures of HK types - val factory = TypeApply(Select(Ident(ClassTagModule), newTermName("apply")), List(TypeTree(tpe))) - Apply(factory, List(TypeApply(Ident(newTermName("classOf")), List(TypeTree(erasure))))) - } - } - try c.typeCheck(result) - catch { case terr @ c.TypeError(pos, msg) => fail(terr) } - } - } + def materializeClassTag(tpe: Type): Tree = + materializeTag(c.reflectMirrorPrefix, tpe, ClassTagModule, c.reifyErasure(tpe)) def materializeTypeTag(tpe: Type, requireConcreteTypeTag: Boolean): Tree = { def prefix: Tree = ??? // todo. needs to be synthesized from c.prefix - materializeTypeTag(prefix, tpe, requireConcreteTypeTag) + val tagModule = if (requireConcreteTypeTag) ConcreteTypeTagModule else TypeTagModule + materializeTag(prefix, tpe, tagModule, c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, requireConcreteTypeTag = requireConcreteTypeTag)) } - def materializeTypeTag(prefix: Tree, tpe: Type, requireConcreteTypeTag: Boolean): Tree = { - val tagModule = if (requireConcreteTypeTag) ConcreteTypeTagModule else TypeTagModule + private def materializeTag(prefix: Tree, tpe: Type, tagModule: Symbol, materializer: => Tree): Tree = { val result = tpe match { case coreTpe if coreTags contains coreTpe => Select(Select(prefix, tagModule.name), coreTags(coreTpe)) case _ => - try c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, requireConcreteTypeTag = requireConcreteTypeTag) + try materializer catch { case ex: Throwable => // [Eugene] cannot pattern match on an abstract type, so had to do this diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala index e47bc7216e..d9293888d9 100755 --- a/src/library/scala/reflect/api/Symbols.scala +++ b/src/library/scala/reflect/api/Symbols.scala @@ -120,6 +120,11 @@ trait Symbols { self: Universe => */ def isTerm : Boolean + /** Does this symbol represent a package? + * If yes, `isTerm` is also guaranteed to be true. + */ + def isPackage : Boolean + /** Does this symbol represent the definition of method? * If yes, `isTerm` is also guaranteed to be true. */ @@ -146,6 +151,11 @@ trait Symbols { self: Universe => */ def isClass : Boolean + /** Does this symbol represent a package class? + * If yes, `isClass` is also guaranteed to be true. + */ + def isPackageClass : Boolean + /** Does this symbol represent the definition of a primitive class? * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]], * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]? diff --git a/src/library/scala/reflect/api/TreeBuildUtil.scala b/src/library/scala/reflect/api/TreeBuildUtil.scala index 32d7eefa5b..4f510337c2 100644 --- a/src/library/scala/reflect/api/TreeBuildUtil.scala +++ b/src/library/scala/reflect/api/TreeBuildUtil.scala @@ -62,20 +62,34 @@ trait TreeBuildUtil { self: Universe => * @param name the name of the free variable * @param info the type signature of the free variable * @param value the value of the free variable at runtime + * @param flags (optional) flags of the free variable * @param origin debug information that tells where this symbol comes from */ - def newFreeTerm(name: String, info: Type, value: => Any, origin: String): Symbol + def newFreeTerm(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): Symbol - /** Create a fresh free type symbol. + /** Create a fresh free non-existential type symbol. * @param name the name of the free variable * @param info the type signature of the free variable * @param value a type tag that captures the value of the free variable * is completely phantom, since the captured type cannot be propagated to the runtime * if it could be, we wouldn't be creating a free type to begin with * the only usage for it is preserving the captured symbol for compile-time analysis + * @param flags (optional) flags of the free variable * @param origin debug information that tells where this symbol comes from */ - def newFreeType(name: String, info: Type, value: => Any, origin: String): Symbol + def newFreeType(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): Symbol + + /** Create a fresh free existential type symbol. + * @param name the name of the free variable + * @param info the type signature of the free variable + * @param value a type tag that captures the value of the free variable + * is completely phantom, since the captured type cannot be propagated to the runtime + * if it could be, we wouldn't be creating a free type to begin with + * the only usage for it is preserving the captured symbol for compile-time analysis + * @param flags (optional) flags of the free variable + * @param origin (optional) debug information that tells where this symbol comes from + */ + def newFreeExistential(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): Symbol /** Create a Modiiers structure given internal flags, qualifier, annotations */ def modifiersFromInternalFlags(flags: Long, privateWithin: Name, annotations: List[Tree]): Modifiers diff --git a/src/library/scala/reflect/api/TypeTags.scala b/src/library/scala/reflect/api/TypeTags.scala index 59a7c87f44..85755cd2f2 100644 --- a/src/library/scala/reflect/api/TypeTags.scala +++ b/src/library/scala/reflect/api/TypeTags.scala @@ -7,6 +7,7 @@ package scala.reflect package api import scala.reflect.{ mirror => rm } +import java.lang.{ Class => jClass } import language.implicitConversions /** @@ -119,7 +120,7 @@ trait TypeTags { self: Universe => * @see [[scala.reflect.api.TypeTags]] */ @annotation.implicitNotFound(msg = "No ConcreteTypeTag available for ${T}") - class ConcreteTypeTag[T](tpe: Type) extends TypeTag[T](tpe) { + abstract class ConcreteTypeTag[T](tpe: Type, val erasure: jClass[_]) extends TypeTag[T](tpe) { // it's unsafe to use assert here, because we might run into deadlocks with Predef // also see comments in ClassTags.scala //assert(isConcrete, tpe) @@ -128,24 +129,24 @@ trait TypeTags { self: Universe => } object ConcreteTypeTag { - val Byte : ConcreteTypeTag[scala.Byte] = new ConcreteTypeTag[scala.Byte](ByteTpe) { private def readResolve() = ConcreteTypeTag.Byte } - val Short : ConcreteTypeTag[scala.Short] = new ConcreteTypeTag[scala.Short](ShortTpe) { private def readResolve() = ConcreteTypeTag.Short } - val Char : ConcreteTypeTag[scala.Char] = new ConcreteTypeTag[scala.Char](CharTpe) { private def readResolve() = ConcreteTypeTag.Char } - val Int : ConcreteTypeTag[scala.Int] = new ConcreteTypeTag[scala.Int](IntTpe) { private def readResolve() = ConcreteTypeTag.Int } - val Long : ConcreteTypeTag[scala.Long] = new ConcreteTypeTag[scala.Long](LongTpe) { private def readResolve() = ConcreteTypeTag.Long } - val Float : ConcreteTypeTag[scala.Float] = new ConcreteTypeTag[scala.Float](FloatTpe) { private def readResolve() = ConcreteTypeTag.Float } - val Double : ConcreteTypeTag[scala.Double] = new ConcreteTypeTag[scala.Double](DoubleTpe) { private def readResolve() = ConcreteTypeTag.Double } - val Boolean : ConcreteTypeTag[scala.Boolean] = new ConcreteTypeTag[scala.Boolean](BooleanTpe) { private def readResolve() = ConcreteTypeTag.Boolean } - val Unit : ConcreteTypeTag[scala.Unit] = new ConcreteTypeTag[scala.Unit](UnitTpe) { private def readResolve() = ConcreteTypeTag.Unit } - val Any : ConcreteTypeTag[scala.Any] = new ConcreteTypeTag[scala.Any](AnyTpe) { private def readResolve() = ConcreteTypeTag.Any } - val Object : ConcreteTypeTag[java.lang.Object] = new ConcreteTypeTag[java.lang.Object](ObjectTpe) { private def readResolve() = ConcreteTypeTag.Object } - val AnyVal : ConcreteTypeTag[scala.AnyVal] = new ConcreteTypeTag[scala.AnyVal](AnyValTpe) { private def readResolve() = ConcreteTypeTag.AnyVal } - val AnyRef : ConcreteTypeTag[scala.AnyRef] = new ConcreteTypeTag[scala.AnyRef](AnyRefTpe) { private def readResolve() = ConcreteTypeTag.AnyRef } - val Nothing : ConcreteTypeTag[scala.Nothing] = new ConcreteTypeTag[scala.Nothing](NothingTpe) { private def readResolve() = ConcreteTypeTag.Nothing } - val Null : ConcreteTypeTag[scala.Null] = new ConcreteTypeTag[scala.Null](NullTpe) { private def readResolve() = ConcreteTypeTag.Null } - val String : ConcreteTypeTag[java.lang.String] = new ConcreteTypeTag[java.lang.String](StringTpe) { private def readResolve() = ConcreteTypeTag.String } - - def apply[T](tpe: Type): ConcreteTypeTag[T] = + val Byte : ConcreteTypeTag[scala.Byte] = new ConcreteTypeTag[scala.Byte](ByteTpe, ClassTag.Byte.erasure) { private def readResolve() = ConcreteTypeTag.Byte } + val Short : ConcreteTypeTag[scala.Short] = new ConcreteTypeTag[scala.Short](ShortTpe, ClassTag.Short.erasure) { private def readResolve() = ConcreteTypeTag.Short } + val Char : ConcreteTypeTag[scala.Char] = new ConcreteTypeTag[scala.Char](CharTpe, ClassTag.Char.erasure) { private def readResolve() = ConcreteTypeTag.Char } + val Int : ConcreteTypeTag[scala.Int] = new ConcreteTypeTag[scala.Int](IntTpe, ClassTag.Int.erasure) { private def readResolve() = ConcreteTypeTag.Int } + val Long : ConcreteTypeTag[scala.Long] = new ConcreteTypeTag[scala.Long](LongTpe, ClassTag.Long.erasure) { private def readResolve() = ConcreteTypeTag.Long } + val Float : ConcreteTypeTag[scala.Float] = new ConcreteTypeTag[scala.Float](FloatTpe, ClassTag.Float.erasure) { private def readResolve() = ConcreteTypeTag.Float } + val Double : ConcreteTypeTag[scala.Double] = new ConcreteTypeTag[scala.Double](DoubleTpe, ClassTag.Double.erasure) { private def readResolve() = ConcreteTypeTag.Double } + val Boolean : ConcreteTypeTag[scala.Boolean] = new ConcreteTypeTag[scala.Boolean](BooleanTpe, ClassTag.Boolean.erasure) { private def readResolve() = ConcreteTypeTag.Boolean } + val Unit : ConcreteTypeTag[scala.Unit] = new ConcreteTypeTag[scala.Unit](UnitTpe, ClassTag.Unit.erasure) { private def readResolve() = ConcreteTypeTag.Unit } + val Any : ConcreteTypeTag[scala.Any] = new ConcreteTypeTag[scala.Any](AnyTpe, ClassTag.Any.erasure) { private def readResolve() = ConcreteTypeTag.Any } + val Object : ConcreteTypeTag[java.lang.Object] = new ConcreteTypeTag[java.lang.Object](ObjectTpe, ClassTag.Object.erasure) { private def readResolve() = ConcreteTypeTag.Object } + val AnyVal : ConcreteTypeTag[scala.AnyVal] = new ConcreteTypeTag[scala.AnyVal](AnyValTpe, ClassTag.AnyVal.erasure) { private def readResolve() = ConcreteTypeTag.AnyVal } + val AnyRef : ConcreteTypeTag[scala.AnyRef] = new ConcreteTypeTag[scala.AnyRef](AnyRefTpe, ClassTag.AnyRef.erasure) { private def readResolve() = ConcreteTypeTag.AnyRef } + val Nothing : ConcreteTypeTag[scala.Nothing] = new ConcreteTypeTag[scala.Nothing](NothingTpe, ClassTag.Nothing.erasure) { private def readResolve() = ConcreteTypeTag.Nothing } + val Null : ConcreteTypeTag[scala.Null] = new ConcreteTypeTag[scala.Null](NullTpe, ClassTag.Null.erasure) { private def readResolve() = ConcreteTypeTag.Null } + val String : ConcreteTypeTag[java.lang.String] = new ConcreteTypeTag[java.lang.String](StringTpe, ClassTag.String.erasure) { private def readResolve() = ConcreteTypeTag.String } + + def apply[T](tpe: Type, erasure: jClass[_] = null): ConcreteTypeTag[T] = tpe match { case ByteTpe => ConcreteTypeTag.Byte.asInstanceOf[ConcreteTypeTag[T]] case ShortTpe => ConcreteTypeTag.Short.asInstanceOf[ConcreteTypeTag[T]] @@ -163,12 +164,12 @@ trait TypeTags { self: Universe => case NothingTpe => ConcreteTypeTag.Nothing.asInstanceOf[ConcreteTypeTag[T]] case NullTpe => ConcreteTypeTag.Null.asInstanceOf[ConcreteTypeTag[T]] case StringTpe => ConcreteTypeTag.String.asInstanceOf[ConcreteTypeTag[T]] - case _ => new ConcreteTypeTag[T](tpe) {} + case _ => new ConcreteTypeTag[T](tpe, erasure) {} } def unapply[T](ttag: TypeTag[T]): Option[Type] = if (ttag.isConcrete) Some(ttag.tpe) else None - implicit def toClassTag[T](ttag: rm.ConcreteTypeTag[T]): ClassTag[T] = ClassTag[T](rm.typeToClass(ttag.tpe.erasure)) + implicit def toClassTag[T](ttag: rm.ConcreteTypeTag[T]): ClassTag[T] = ClassTag[T](ttag) implicit def toDeprecatedManifestApis[T](ttag: rm.ConcreteTypeTag[T]): DeprecatedManifestApis[T] = new DeprecatedManifestApis[T](ttag) diff --git a/src/library/scala/reflect/api/Types.scala b/src/library/scala/reflect/api/Types.scala index 5e1c1af2fe..4cb5609166 100755 --- a/src/library/scala/reflect/api/Types.scala +++ b/src/library/scala/reflect/api/Types.scala @@ -53,14 +53,26 @@ trait Types { self: Universe => */ def typeArguments: List[Type] + /** For a (potentially wrapped) poly type, its type parameters, + * the empty list for all other types */ + def typeParams: List[Symbol] + /** Is this type a type constructor that is missing its type arguments? */ def isHigherKinded: Boolean // !!! This should be called "isTypeConstructor", no? - /** Does this type refer to abstract types or is an abstract type? + /** Returns the corresponding type constructor (e.g. List for List[T] or List[String]) + */ + def typeConstructor: Type + + /** Does this type refer to spliceable types or is a spliceable type? */ def isConcrete: Boolean + /** Is this type an abstract type that needs to be resolved? + */ + def isSpliceable: Boolean + /** * Expands type aliases and converts higher-kinded TypeRefs to PolyTypes. * Functions on types are also implemented as PolyTypes. diff --git a/src/library/scala/reflect/makro/Reifiers.scala b/src/library/scala/reflect/makro/Reifiers.scala index d690df6aee..b9e82e0387 100644 --- a/src/library/scala/reflect/makro/Reifiers.scala +++ b/src/library/scala/reflect/makro/Reifiers.scala @@ -48,6 +48,10 @@ trait Reifiers { */ def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, requireConcreteTypeTag: Boolean = false): Tree + /** Given a type, generate a tree that when compiled and executed produces the erasure of the original type. + */ + def reifyErasure(tpe: Type): Tree + /** Undoes reification of a tree. * * This reversion doesn't simply restore the original tree (that would lose the context of reification), diff --git a/src/library/scala/reflect/makro/internal/Utils.scala b/src/library/scala/reflect/makro/internal/Utils.scala index db658fd637..604bba10b6 100644 --- a/src/library/scala/reflect/makro/internal/Utils.scala +++ b/src/library/scala/reflect/makro/internal/Utils.scala @@ -55,49 +55,22 @@ package internal { NothingClass.asType -> newTermName("Nothing"), NullClass.asType -> newTermName("Null")) - def materializeClassTag(prefix: Tree, tpe: Type): Tree = { - val typetagInScope = c.inferImplicitValue(appliedType(typeRef(prefix.tpe, ConcreteTypeTagClass, Nil), List(tpe))) - def typetagIsSynthetic(tree: Tree) = tree.isInstanceOf[Block] || (tree exists (sub => sub.symbol == TypeTagModule || sub.symbol == ConcreteTypeTagModule)) - typetagInScope match { - case success if !success.isEmpty && !typetagIsSynthetic(success) => - val factory = TypeApply(Select(Ident(ClassTagModule), newTermName("apply")), List(TypeTree(tpe))) - Apply(factory, List(Select(typetagInScope, newTermName("tpe")))) - case _ => - val result = - tpe match { - case coreTpe if coreTags contains coreTpe => - Select(Ident(ClassTagModule), coreTags(coreTpe)) - case _ => - if (tpe.typeSymbol == ArrayClass) { - val componentTpe = tpe.typeArguments(0) - val classtagInScope = c.inferImplicitValue(appliedType(typeRef(NoPrefix, ClassTagClass, Nil), List(componentTpe))) - val componentTag = classtagInScope orElse materializeClassTag(prefix, componentTpe) - Select(componentTag, newTermName("wrap")) - } else { - // [Eugene] what's the intended behavior? there's no spec on ClassManifests - // for example, should we ban Array[T] or should we tag them with Array[AnyRef]? - // if its the latter, what should be the result of tagging Array[T] where T <: Int? - if (tpe.typeSymbol.isAbstractType) fail("tpe is an abstract type") - val erasure = - if (tpe.typeSymbol.isDerivedValueClass) tpe // [Eugene to Martin] is this correct? - else tpe.erasure.normalize // necessary to deal with erasures of HK types - val factory = TypeApply(Select(Ident(ClassTagModule), newTermName("apply")), List(TypeTree(tpe))) - Apply(factory, List(TypeApply(Ident(newTermName("classOf")), List(TypeTree(erasure))))) - } - } - try c.typeCheck(result) - catch { case terr @ c.TypeError(pos, msg) => fail(terr) } - } - } + def materializeClassTag(prefix: Tree, tpe: Type): Tree = + materializeTag(prefix, tpe, ClassTagModule, c.reifyErasure(tpe)) def materializeTypeTag(prefix: Tree, tpe: Type, requireConcreteTypeTag: Boolean): Tree = { val tagModule = if (requireConcreteTypeTag) ConcreteTypeTagModule else TypeTagModule + materializeTag(prefix, tpe, tagModule, c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, requireConcreteTypeTag = requireConcreteTypeTag)) + } + + private def materializeTag(prefix: Tree, tpe: Type, tagModule: Symbol, materializer: => Tree): Tree = { val result = tpe match { case coreTpe if coreTags contains coreTpe => - Select(Select(prefix, tagModule.name), coreTags(coreTpe)) + val ref = if (tagModule.owner.isPackageClass) Ident(tagModule) else Select(prefix, tagModule.name) + Select(ref, coreTags(coreTpe)) case _ => - try c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, requireConcreteTypeTag = requireConcreteTypeTag) + try materializer catch { case ex: Throwable => // [Eugene] cannot pattern match on an abstract type, so had to do this diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala index 6d50a96dfd..93fd0bb711 100644 --- a/src/library/scala/reflect/package.scala +++ b/src/library/scala/reflect/package.scala @@ -64,7 +64,7 @@ package object reflect { @deprecated("Use `@scala.reflect.ConcreteTypeTag` instead", "2.10.0") lazy val Manifest = ConcreteTypeTag @deprecated("NoManifest is no longer supported, and using it may lead to incorrect results, Use `@scala.reflect.TypeTag` instead", "2.10.0") - object NoManifest extends OptManifest[Nothing](scala.reflect.mirror.definitions.NothingClass.asType) with Serializable + object NoManifest extends OptManifest[Nothing](scala.reflect.mirror.TypeTag.Nothing.tpe) // ClassTag class is defined separately from the mirror type TypeTag[T] = scala.reflect.mirror.TypeTag[T] |