diff options
Diffstat (limited to 'src')
29 files changed, 326 insertions, 233 deletions
diff --git a/src/compiler/scala/reflect/makro/runtime/ExprUtils.scala b/src/compiler/scala/reflect/makro/runtime/ExprUtils.scala index 4775138e5a..e301dfc2a4 100644 --- a/src/compiler/scala/reflect/makro/runtime/ExprUtils.scala +++ b/src/compiler/scala/reflect/makro/runtime/ExprUtils.scala @@ -29,7 +29,7 @@ trait ExprUtils { def literal(x: Double) = Expr[Double](Literal(Constant(x)))(TypeTag.Double) - def literal(x: String) = Expr[String](Literal(Constant(x)))(TypeTag.String) + def literal(x: String) = Expr[String](Literal(Constant(x)))(TypeTag[String](definitions.StringClass.asTypeConstructor)) def literal(x: Char) = Expr[Char](Literal(Constant(x)))(TypeTag.Char) } diff --git a/src/compiler/scala/reflect/reify/Taggers.scala b/src/compiler/scala/reflect/reify/Taggers.scala index b70c3f44a3..e4c3d02f22 100644 --- a/src/compiler/scala/reflect/reify/Taggers.scala +++ b/src/compiler/scala/reflect/reify/Taggers.scala @@ -11,20 +11,19 @@ abstract class Taggers { import treeBuild._ val coreTags = Map( - ByteClass.asType -> nme.Byte, - ShortClass.asType -> nme.Short, - CharClass.asType -> nme.Char, - IntClass.asType -> nme.Int, - LongClass.asType -> nme.Long, - FloatClass.asType -> nme.Float, - DoubleClass.asType -> nme.Double, - BooleanClass.asType -> nme.Boolean, - UnitClass.asType -> nme.Unit, - AnyClass.asType -> nme.Any, - ObjectClass.asType -> nme.Object, - NothingClass.asType -> nme.Nothing, - NullClass.asType -> nme.Null, - StringClass.asType -> nme.String) + ByteTpe -> nme.Byte, + ShortTpe -> nme.Short, + CharTpe -> nme.Char, + IntTpe -> nme.Int, + LongTpe -> nme.Long, + FloatTpe -> nme.Float, + DoubleTpe -> nme.Double, + BooleanTpe -> nme.Boolean, + UnitTpe -> nme.Unit, + AnyTpe -> nme.Any, + ObjectTpe -> nme.Object, + NothingTpe -> nme.Nothing, + NullTpe -> nme.Null) def materializeClassTag(prefix: Tree, tpe: Type): Tree = { val tagModule = ClassTagModule diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala index 3a98d308a7..9b0777580b 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala @@ -23,10 +23,8 @@ trait GenSymbols { def symtab: SymbolTable = state.symtab /** Reify a reference to a symbol */ - def reifySymRef(sym0: Symbol): Tree = { - assert(sym0 != null, "sym is null") - val sym = sym0.dealias - + def reifySymRef(sym: Symbol): Tree = { + assert(sym != null, "sym is null") if (sym == NoSymbol) mirrorSelect(nme.NoSymbol) else if (sym.isRootPackage) diff --git a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala index b97bf6b0cd..f48df8df65 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala @@ -161,11 +161,9 @@ trait GenTrees { if (tree.symbol.isLocalToReifee || tree.tpe.isLocalToReifee) reifyProduct(tree) else { - val sym0 = tree.symbol - val sym = sym0.dealias - val tpe0 = tree.tpe - val tpe = tpe0.dealias - if (reifyDebug) println("reifying bound type %s (underlying type is %s, dealiased is %s)".format(sym0, tpe0, tpe)) + val sym = tree.symbol + val tpe = tree.tpe + if (reifyDebug) println("reifying bound type %s (underlying type is %s)".format(sym, tpe)) if (tpe.isSpliceable) { val spliced = spliceType(tpe) @@ -187,7 +185,7 @@ trait GenTrees { if (reifyDebug) println("tpe is locatable: reify as Ident(%s)".format(sym)) mirrorBuildCall(nme.Ident, reify(sym)) } else { - if (reifyDebug) println("tpe is an alias, but not a locatable: reify as TypeTree(%s)".format(tpe)) + if (reifyDebug) println("tpe is not locatable: reify as TypeTree(%s)".format(tpe)) mirrorBuildCall(nme.TypeTree, reify(tpe)) } } diff --git a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala index f4e2200edc..82951a2434 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala @@ -11,9 +11,8 @@ trait GenTypes { * Reify a type. * For internal use only, use ``reified'' instead. */ - def reifyType(tpe0: Type): Tree = { - assert(tpe0 != null, "tpe is null") - val tpe = tpe0.dealias + def reifyType(tpe: Type): Tree = { + assert(tpe != null, "tpe is null") if (tpe.isErroneous) CannotReifyErroneousReifee(tpe) @@ -29,9 +28,9 @@ trait GenTypes { if (spliced != EmptyTree) return spliced - val tsym = tpe.typeSymbol + val tsym = tpe.typeSymbolDirect if (tsym.isClass && tpe == tsym.typeConstructor && tsym.isStatic) - Select(Select(reify(tpe.typeSymbol), nme.asTypeSymbol), nme.asTypeConstructor) + Select(Select(reify(tsym), nme.asTypeSymbol), nme.asTypeConstructor) else tpe match { case tpe @ NoType => reifyMirrorObject(tpe) @@ -107,13 +106,11 @@ trait GenTypes { } private def spliceAsManifest(tpe: Type): Tree = { - val ManifestClass = rootMirror.staticClass("scala.reflect.Manifest") - val ManifestModule = rootMirror.staticModule("scala.reflect.Manifest") - def isSynthetic(manifest: Tree) = manifest exists (sub => sub.symbol != null && (sub.symbol == ManifestModule || sub.symbol.owner == ManifestModule)) + def isSynthetic(manifest: Tree) = manifest exists (sub => sub.symbol != null && (sub.symbol == FullManifestModule || sub.symbol.owner == FullManifestModule)) def searchForManifest(typer: analyzer.Typer): Tree = analyzer.inferImplicit( EmptyTree, - appliedType(ManifestClass.asTypeConstructor, List(tpe)), + appliedType(FullManifestClass.asTypeConstructor, List(tpe)), reportAmbiguous = false, isView = false, context = typer.context, diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 60cc9e5fb8..49f5fca19d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -106,7 +106,7 @@ trait ContextErrors { def errMsg = { val paramName = param.name val paramTp = param.tpe - paramTp.typeSymbol match { + paramTp.typeSymbolDirect match { case ImplicitNotFoundMsg(msg) => msg.format(paramName, paramTp) case _ => "could not find implicit value for "+ diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 68782379a6..da045e1a48 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1224,7 +1224,9 @@ trait Implicits { * reflect.Manifest for type 'tp'. An EmptyTree is returned if * no manifest is found. todo: make this instantiate take type params as well? */ - private def manifestOfType(tp: Type, full: Boolean): SearchResult = { + private def manifestOfType(tp: Type, flavor: Symbol): SearchResult = { + val full = flavor == FullManifestClass + val opt = flavor == OptManifestClass /** Creates a tree that calls the factory method called constructor in object reflect.Manifest */ def manifestFactoryCall(constructor: String, tparg: Type, args: Tree*): Tree = @@ -1256,7 +1258,7 @@ trait Implicits { if (containsExistential(tp1)) EmptyTree else manifestFactoryCall("singleType", tp, gen.mkAttributedQualifier(tp1)) case ConstantType(value) => - manifestOfType(tp1.deconst, full) + manifestOfType(tp1.deconst, FullManifestClass) case TypeRef(pre, sym, args) => if (isPrimitiveValueClass(sym) || isPhantomClass(sym)) { findSingletonManifest(sym.name.toString) @@ -1299,22 +1301,13 @@ trait Implicits { mot(tp1.skolemizeExistential, from, to) case _ => EmptyTree -/* !!! the following is almost right, but we have to splice nested manifest - * !!! types into this type. This requires a substantial extension of - * !!! reifiers. - val reifier = new Reifier() - val rtree = reifier.reifyTopLevel(tp1) - manifestFactoryCall("apply", tp, rtree) -*/ } } - val tagInScope = - if (full) resolveTypeTag(pos, NoType, tp, concrete = true, allowMaterialization = false) - else resolveClassTag(pos, tp, allowMaterialization = false) - if (tagInScope.isEmpty) mot(tp, Nil, Nil) - else { - if (full) { + if (full) { + val tagInScope = resolveTypeTag(pos, NoType, tp, concrete = true, allowMaterialization = false) + if (tagInScope.isEmpty) mot(tp, Nil, Nil) + else { if (ReflectRuntimeUniverse == NoSymbol) { // todo. write a test for this context.error(pos, s""" @@ -1330,44 +1323,62 @@ trait Implicits { |to proceed add a class tag to the type `$tp` (e.g. by introducing a context bound) and recompile.""".trim.stripMargin) return SearchFailure } + val cm = typed(Ident(ReflectRuntimeCurrentMirror)) + val interop = gen.mkMethodCall(ReflectRuntimeUniverse, nme.typeTagToManifest, List(tp), List(cm, tagInScope)) + wrapResult(interop) + } + } else { + mot(tp, Nil, Nil) match { + case SearchFailure if opt => wrapResult(gen.mkAttributedRef(NoManifest)) + case result => result } - - val interop = - if (full) { - val cm = typed(Ident(ReflectRuntimeCurrentMirror)) - gen.mkMethodCall(ReflectRuntimeUniverse, nme.typeTagToManifest, List(tp), List(cm, tagInScope)) - } else gen.mkMethodCall(ReflectBasis, nme.classTagToClassManifest, List(tp), List(tagInScope)) - wrapResult(interop) } } def wrapResult(tree: Tree): SearchResult = if (tree == EmptyTree) SearchFailure else new SearchResult(tree, EmptyTreeTypeSubstituter) - /** The tag corresponding to type `pt`, provided `pt` is a flavor of a tag. + /** Materializes implicits of magic types (currently, manifests and tags). + * Will be replaced by implicit macros once we fix them. */ - private def implicitTagOrOfExpectedType(pt: Type): SearchResult = pt.dealias match { - case TypeRef(pre, sym, arg :: Nil) if ManifestSymbols(sym) => - manifestOfType(arg, sym == FullManifestClass) match { - case SearchFailure if sym == OptManifestClass => wrapResult(gen.mkAttributedRef(NoManifest)) - case result => result - } - case TypeRef(pre, sym, arg :: Nil) if TagSymbols(sym) => - tagOfType(pre, arg, sym) - case tp@TypeRef(_, sym, _) if sym.isAbstractType => - implicitTagOrOfExpectedType(tp.bounds.lo) // #3977: use tp (==pt.dealias), not pt (if pt is a type alias, pt.bounds.lo == pt) - case _ => + private def materializeImplicit(pt: Type): SearchResult = { + def fallback = { searchImplicit(implicitsOfExpectedType, false) // shouldn't we pass `pt` to `implicitsOfExpectedType`, or is the recursive case // for an abstract type really only meant for tags? + } + + pt match { + case TypeRef(_, sym, _) if sym.isAbstractType => + materializeImplicit(pt.dealias.bounds.lo) // #3977: use pt.dealias, not pt (if pt is a type alias, pt.bounds.lo == pt) + case pt @ TypeRef(pre, sym, arg :: Nil) => + sym match { + case sym if ManifestSymbols(sym) => manifestOfType(arg, sym) + case sym if TagSymbols(sym) => tagOfType(pre, arg, sym) + // as of late ClassManifest is an alias of ClassTag + // hence we need to take extra care when performing dealiasing + // because it might destroy the flavor of the manifest requested by the user + // when the user wants ClassManifest[T], we should invoke `manifestOfType` not `tagOfType` + // hence we don't do `pt.dealias` as we did before, but rather do `pt.betaReduce` + // unlike `dealias`, `betaReduce` performs at most one step of dealiasing + // while dealias pops all aliases in a single invocation + case sym if sym.isAliasType => materializeImplicit(pt.betaReduce) + case _ => fallback + } + case _ => + fallback + } } /** The result of the implicit search: * First search implicits visible in current context. * If that fails, search implicits in expected type `pt`. - * // [Eugene] the following two lines should be deleted after we migrate delegate tag materialization to implicit macros + * // [Eugene] the following lines should be deleted after we migrate delegate tag materialization to implicit macros * If that fails, and `pt` is an instance of a ClassTag, try to construct a class tag. * If that fails, and `pt` is an instance of a TypeTag, try to construct a type tag. + * If that fails, and `pt` is an instance of a ClassManifest, try to construct a class manifest. + * If that fails, and `pt` is an instance of a Manifest, try to construct a manifest. + * If that fails, and `pt` is an instance of a OptManifest, try to construct a class manifest and return NoManifest if construction fails. * If all fails return SearchFailure */ def bestImplicit: SearchResult = { @@ -1387,7 +1398,7 @@ trait Implicits { val failstart = Statistics.startTimer(oftypeFailNanos) val succstart = Statistics.startTimer(oftypeSucceedNanos) - result = implicitTagOrOfExpectedType(pt) + result = materializeImplicit(pt) if (result == SearchFailure) { context.updateBuffer(previousErrs) @@ -1434,7 +1445,16 @@ trait Implicits { } object ImplicitNotFoundMsg { - def unapply(sym: Symbol): Option[(Message)] = sym.implicitNotFoundMsg map (m => (new Message(sym, m))) + def unapply(sym: Symbol): Option[(Message)] = sym.implicitNotFoundMsg match { + case Some(m) => Some(new Message(sym, m)) + case None if sym.isAliasType => + // perform exactly one step of dealiasing + // this is necessary because ClassManifests are now aliased to ClassTags + // but we don't want to intimidate users by showing unrelated error messages + unapply(sym.info.resultType.betaReduce.typeSymbolDirect) + case _ => None + } + // check the message's syntax: should be a string literal that may contain occurrences of the string "${X}", // where `X` refers to a type parameter of `sym` def check(sym: Symbol): Option[String] = diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index d157666e47..322b9ebb25 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -1221,7 +1221,10 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { case ex: Throwable => None } - } getOrElse realex.getMessage + } getOrElse { + val msg = realex.getMessage + if (msg != null) msg else realex.getClass.getName + } fail(typer, expandee, msg = "exception during macro expansion: " + message) } } diff --git a/src/compiler/scala/tools/reflect/StdTags.scala b/src/compiler/scala/tools/reflect/StdTags.scala index c782181f21..18cbf9c4b7 100644 --- a/src/compiler/scala/tools/reflect/StdTags.scala +++ b/src/compiler/scala/tools/reflect/StdTags.scala @@ -12,7 +12,14 @@ import scala.reflect.runtime.{universe => ru} object StdTags { // root mirror is fine for these guys, since scala-library.jar is guaranteed to be reachable from the root mirror - lazy val tagOfString = ru.TypeTag.String + lazy val tagOfString = ru.TypeTag[String]( + ru.rootMirror, + new TypeCreator { + def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Type = { + val u = m.universe + u.definitions.StringClass.asTypeConstructor + } + }) lazy val tagOfListOfString = ru.TypeTag[List[String]]( ru.rootMirror, new TypeCreator { diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index b4178102b9..589c5c7eb0 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -216,7 +216,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => (singleton, jmeth) } - def runExpr(expr: Tree, freeTypes: Map[TypeName, Type] = Map[TypeName, Type]()): Any = { + def runExpr(expr: Tree): Any = { val freeTerms = expr.freeTerms // need to calculate them here, because later on they will be erased val thunks = freeTerms map (fte => () => fte.value) // need to be lazy in order not to distort evaluation order diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 99bd7f0736..44025d5358 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -100,11 +100,19 @@ object Predef extends LowPriorityImplicits { // def AnyRef = scala.AnyRef // Manifest types, companions, and incantations for summoning + @annotation.implicitNotFound(msg = "No ClassManifest available for ${T}.") + @deprecated("Use scala.reflect.ClassTag instead", "2.10.0") type ClassManifest[T] = scala.reflect.ClassManifest[T] + @deprecated("This notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") type OptManifest[T] = scala.reflect.OptManifest[T] + @annotation.implicitNotFound(msg = "No Manifest available for ${T}.") + @deprecated("Use scala.reflect.ClassTag (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") type Manifest[T] = scala.reflect.Manifest[T] + @deprecated("Use scala.reflect.ClassTag instead", "2.10.0") val ClassManifest = scala.reflect.ClassManifest + @deprecated("Use scala.reflect.ClassTag (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") val Manifest = scala.reflect.Manifest + @deprecated("This notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") val NoManifest = scala.reflect.NoManifest def manifest[T](implicit m: Manifest[T]) = m diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala index d89d31f689..f143bf8712 100644 --- a/src/library/scala/reflect/ClassManifest.scala +++ b/src/library/scala/reflect/ClassManifest.scala @@ -11,23 +11,12 @@ package scala.reflect import scala.collection.mutable.{ WrappedArray, ArrayBuilder } import java.lang.{ Class => jClass } -/** A `ClassManifest[T]` is an opaque descriptor for type `T`. - * It is used by the compiler to preserve information necessary - * for instantiating `Arrays` in those cases where the element type - * is unknown at compile time. - * - * The type-relation operators make an effort to present a more accurate - * picture than can be realized with erased types, but they should not be - * relied upon to give correct answers. In particular they are likely to - * be wrong when variance is involved or when a subtype has a different - * number of type arguments than a supertype. - */ -@deprecated("Use `@scala.reflect.ClassTag` instead", "2.10.0") -trait ClassManifest[T] extends OptManifest[T] with ClassTag[T] with Equals with Serializable { - /** A class representing the type `U` to which `T` would be erased. Note - * that there is no subtyping relationship between `T` and `U`. */ - def erasure: jClass[_] - override def runtimeClass: jClass[_] = erasure +@deprecated("Use scala.reflect.ClassTag instead", "2.10.0") +trait ClassManifestDeprecatedApis[T] extends OptManifest[T] { + self: ClassManifest[T] => + + @deprecated("Use runtimeClass instead", "2.10.0") + def erasure: jClass[_] = runtimeClass private def subtype(sub: jClass[_], sup: jClass[_]): Boolean = { def loop(left: Set[jClass[_]], seen: Set[jClass[_]]): Boolean = { @@ -53,6 +42,7 @@ trait ClassManifest[T] extends OptManifest[T] with ClassTag[T] with Equals with * of the type represented by `that` manifest, subject to the limitations * described in the header. */ + @deprecated("Use scala.reflect.runtime.universe.TypeTag for subtype checking instead", "2.10.0") def <:<(that: ClassManifest[_]): Boolean = { // All types which could conform to these types will override <:<. def cannotMatch = { @@ -86,6 +76,7 @@ trait ClassManifest[T] extends OptManifest[T] with ClassTag[T] with Equals with * of the type represented by `that` manifest, subject to the limitations * described in the header. */ + @deprecated("Use scala.reflect.runtime.universe.TypeTag for subtype checking instead", "2.10.0") def >:>(that: ClassManifest[_]): Boolean = that <:< this @@ -94,49 +85,47 @@ trait ClassManifest[T] extends OptManifest[T] with ClassTag[T] with Equals with case _ => false } - /** Tests whether the type represented by this manifest is equal to - * the type represented by `that` manifest, subject to the limitations - * described in the header. - */ - override def equals(that: Any): Boolean = that match { - case m: ClassManifest[_] => (m canEqual this) && (this.erasure == m.erasure) - case _ => false - } - override def hashCode = this.erasure.## - protected def arrayClass[T](tp: jClass[_]): jClass[Array[T]] = java.lang.reflect.Array.newInstance(tp, 0).getClass.asInstanceOf[jClass[Array[T]]] + @deprecated("Use wrap instead", "2.10.0") def arrayManifest: ClassManifest[Array[T]] = ClassManifest.classType[Array[T]](arrayClass[T](erasure), this) override def newArray(len: Int): Array[T] = java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]] + @deprecated("Use wrap.newArray instead", "2.10.0") def newArray2(len: Int): Array[Array[T]] = java.lang.reflect.Array.newInstance(arrayClass[T](erasure), len) .asInstanceOf[Array[Array[T]]] + @deprecated("Use wrap.wrap.newArray instead", "2.10.0") def newArray3(len: Int): Array[Array[Array[T]]] = java.lang.reflect.Array.newInstance(arrayClass[Array[T]](arrayClass[T](erasure)), len) .asInstanceOf[Array[Array[Array[T]]]] + @deprecated("Use wrap.wrap.wrap.newArray instead", "2.10.0") def newArray4(len: Int): Array[Array[Array[Array[T]]]] = java.lang.reflect.Array.newInstance(arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](erasure))), len) .asInstanceOf[Array[Array[Array[Array[T]]]]] + @deprecated("Use wrap.wrap.wrap.wrap.newArray instead", "2.10.0") def newArray5(len: Int): Array[Array[Array[Array[Array[T]]]]] = java.lang.reflect.Array.newInstance(arrayClass[Array[Array[Array[T]]]](arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](erasure)))), len) .asInstanceOf[Array[Array[Array[Array[Array[T]]]]]] + @deprecated("Create WrappedArray directly instead", "2.10.0") def newWrappedArray(len: Int): WrappedArray[T] = // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests new WrappedArray.ofRef[T with AnyRef](newArray(len).asInstanceOf[Array[T with AnyRef]]).asInstanceOf[WrappedArray[T]] + @deprecated("Use ArrayBuilder.make(this) instead", "2.10.0") def newArrayBuilder(): ArrayBuilder[T] = // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests new ArrayBuilder.ofRef[T with AnyRef]()(this.asInstanceOf[ClassManifest[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]] + @deprecated("Use scala.reflect.runtime.universe.TypeTag to capture type structure instead", "2.10.0") def typeArguments: List[OptManifest[_]] = List() protected def argString = @@ -145,25 +134,33 @@ trait ClassManifest[T] extends OptManifest[T] with ClassTag[T] with Equals with else "" } -/** The object `ClassManifest` defines factory methods for manifests. +/** `ClassManifestFactory` defines factory methods for manifests. * It is intended for use by the compiler and should not be used in client code. + * + * Unlike `ClassManifest`, this factory isn't annotated with a deprecation warning. + * This is done to prevent avalanches of deprecation warnings in the code that calls methods with manifests. + * + * In a perfect world, we would just remove the @deprecated annotation from `ClassManifest` the object + * and then delete it in 2.11. After all, that object is explicitly marked as internal, so noone should use it. + * However a lot of existing libraries disregarded the scaladoc that comes with `ClassManifest`, + * so we need to somehow nudge them into migrating prior to removing stuff out of the blue. + * Hence we've introduced this design decision as the lesser of two evils. */ -@deprecated("Use `@scala.reflect.ClassTag` instead", "2.10.0") -object ClassManifest { - val Byte = Manifest.Byte - val Short = Manifest.Short - val Char = Manifest.Char - val Int = Manifest.Int - val Long = Manifest.Long - val Float = Manifest.Float - val Double = Manifest.Double - val Boolean = Manifest.Boolean - val Unit = Manifest.Unit - val Any = Manifest.Any - val Object = Manifest.Object - val AnyVal = Manifest.AnyVal - val Nothing = Manifest.Nothing - val Null = Manifest.Null +object ClassManifestFactory { + val Byte = ManifestFactory.Byte + val Short = ManifestFactory.Short + val Char = ManifestFactory.Char + val Int = ManifestFactory.Int + val Long = ManifestFactory.Long + val Float = ManifestFactory.Float + val Double = ManifestFactory.Double + val Boolean = ManifestFactory.Boolean + val Unit = ManifestFactory.Unit + val Any = ManifestFactory.Any + val Object = ManifestFactory.Object + val AnyVal = ManifestFactory.AnyVal + val Nothing = ManifestFactory.Nothing + val Null = ManifestFactory.Null def fromClass[T](clazz: jClass[T]): ClassManifest[T] = clazz match { case java.lang.Byte.TYPE => Byte.asInstanceOf[ClassManifest[T]] @@ -211,7 +208,7 @@ object ClassManifest { * added so that erasure can be calculated without reflection. */ def abstractType[T](prefix: OptManifest[_], name: String, clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] = new ClassManifest[T] { - def erasure = clazz + override def runtimeClass = clazz override val typeArguments = args.toList override def toString = prefix.toString+"#"+name+argString } @@ -223,7 +220,7 @@ object ClassManifest { */ def abstractType[T](prefix: OptManifest[_], name: String, upperbound: ClassManifest[_], args: OptManifest[_]*): ClassManifest[T] = new ClassManifest[T] { - def erasure = upperbound.erasure + override def runtimeClass = upperbound.erasure override val typeArguments = args.toList override def toString = prefix.toString+"#"+name+argString } @@ -233,7 +230,7 @@ object ClassManifest { * a top-level or static class */ private class ClassTypeManifest[T <: AnyRef]( prefix: Option[OptManifest[_]], - val erasure: jClass[_], + val runtimeClass: jClass[_], override val typeArguments: List[OptManifest[_]]) extends ClassManifest[T] { override def toString = diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index 860e7bac28..8d7b0858ef 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -19,18 +19,20 @@ import scala.runtime.ScalaRunTime.arrayClass * @see [[scala.reflect.base.TypeTags]] */ @annotation.implicitNotFound(msg = "No ClassTag available for ${T}") -trait ClassTag[T] extends Equals with Serializable { +trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serializable { // please, don't add any APIs here, like it was with `newWrappedArray` and `newArrayBuilder` // class tags, and all tags in general, should be as minimalistic as possible - /** Returns a runtime class of type `T` */ + /** A class representing the type `U` to which `T` would be erased. + * Note that there is no subtyping relationship between `T` and `U`. + */ def runtimeClass: jClass[_] /** Produces a `ClassTag` that knows how to build `Array[Array[T]]` */ def wrap: ClassTag[Array[T]] = ClassTag[Array[T]](arrayClass(runtimeClass)) /** Produces a new array with element type `T` and length `len` */ - def newArray(len: Int): Array[T] = + override def newArray(len: Int): Array[T] = runtimeClass match { case java.lang.Byte.TYPE => new Array[Byte](len).asInstanceOf[Array[T]] case java.lang.Short.TYPE => new Array[Short](len).asInstanceOf[Array[T]] @@ -65,7 +67,6 @@ object ClassTag { private val NothingTYPE = classOf[scala.runtime.Nothing$] private val NullTYPE = classOf[scala.runtime.Null$] private val ObjectTYPE = classOf[java.lang.Object] - private val StringTYPE = classOf[java.lang.String] val Byte : ClassTag[scala.Byte] = new ClassTag[scala.Byte]{ def runtimeClass = java.lang.Byte.TYPE; private def readResolve() = ClassTag.Byte } val Short : ClassTag[scala.Short] = new ClassTag[scala.Short]{ def runtimeClass = java.lang.Short.TYPE; private def readResolve() = ClassTag.Short } @@ -82,7 +83,6 @@ object ClassTag { val AnyRef : ClassTag[scala.AnyRef] = new ClassTag[scala.AnyRef]{ def runtimeClass = ObjectTYPE; private def readResolve() = ClassTag.AnyRef } val Nothing : ClassTag[scala.Nothing] = new ClassTag[scala.Nothing]{ def runtimeClass = NothingTYPE; private def readResolve() = ClassTag.Nothing } val Null : ClassTag[scala.Null] = new ClassTag[scala.Null]{ def runtimeClass = NullTYPE; private def readResolve() = ClassTag.Null } - val String : ClassTag[java.lang.String] = new ClassTag[java.lang.String]{ def runtimeClass = StringTYPE; private def readResolve() = ClassTag.String } def apply[T](runtimeClass1: jClass[_]): ClassTag[T] = runtimeClass1 match { @@ -96,7 +96,6 @@ object ClassTag { case java.lang.Boolean.TYPE => ClassTag.Boolean.asInstanceOf[ClassTag[T]] case java.lang.Void.TYPE => ClassTag.Unit.asInstanceOf[ClassTag[T]] case ObjectTYPE => ClassTag.Object.asInstanceOf[ClassTag[T]] - case StringTYPE => ClassTag.String.asInstanceOf[ClassTag[T]] case _ => new ClassTag[T]{ def runtimeClass = runtimeClass1 } } diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index 7e320b42eb..9347f5b6bb 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -39,7 +39,7 @@ import scala.collection.mutable.{ ArrayBuilder, WrappedArray } * */ @annotation.implicitNotFound(msg = "No Manifest available for ${T}.") -@deprecated("Use TypeTag instead", "2.10.0") +@deprecated("Use scala.reflect.ClassTag (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") trait Manifest[T] extends ClassManifest[T] with Equals { override def typeArguments: List[Manifest[_]] = Nil @@ -72,17 +72,19 @@ abstract class AnyValManifest[T <: AnyVal](override val toString: String) extend override val hashCode = System.identityHashCode(this) } -/** The object `Manifest` defines factory methods for manifests. - * It is intended for use by the compiler and should not be used - * in client code. +/** `ManifestFactory` defines factory methods for manifests. + * It is intended for use by the compiler and should not be used in client code. + * + * Unlike `Manifest`, this factory isn't annotated with a deprecation warning. + * This is done to prevent avalanches of deprecation warnings in the code that calls methods with manifests. + * Why so complicated? Read up the comments for `ClassManifestFactory`. */ -@deprecated("Use TypeTag instead", "2.10.0") -object Manifest { +object ManifestFactory { def valueManifests: List[AnyValManifest[_]] = List(Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit) val Byte: AnyValManifest[Byte] = new AnyValManifest[scala.Byte]("Byte") { - def erasure = java.lang.Byte.TYPE + def runtimeClass = java.lang.Byte.TYPE override def newArray(len: Int): Array[Byte] = new Array[Byte](len) override def newWrappedArray(len: Int): WrappedArray[Byte] = new WrappedArray.ofByte(new Array[Byte](len)) override def newArrayBuilder(): ArrayBuilder[Byte] = new ArrayBuilder.ofByte() @@ -90,7 +92,7 @@ object Manifest { } val Short: AnyValManifest[Short] = new AnyValManifest[scala.Short]("Short") { - def erasure = java.lang.Short.TYPE + def runtimeClass = java.lang.Short.TYPE override def newArray(len: Int): Array[Short] = new Array[Short](len) override def newWrappedArray(len: Int): WrappedArray[Short] = new WrappedArray.ofShort(new Array[Short](len)) override def newArrayBuilder(): ArrayBuilder[Short] = new ArrayBuilder.ofShort() @@ -98,7 +100,7 @@ object Manifest { } val Char: AnyValManifest[Char] = new AnyValManifest[scala.Char]("Char") { - def erasure = java.lang.Character.TYPE + def runtimeClass = java.lang.Character.TYPE override def newArray(len: Int): Array[Char] = new Array[Char](len) override def newWrappedArray(len: Int): WrappedArray[Char] = new WrappedArray.ofChar(new Array[Char](len)) override def newArrayBuilder(): ArrayBuilder[Char] = new ArrayBuilder.ofChar() @@ -106,7 +108,7 @@ object Manifest { } val Int: AnyValManifest[Int] = new AnyValManifest[scala.Int]("Int") { - def erasure = java.lang.Integer.TYPE + def runtimeClass = java.lang.Integer.TYPE override def newArray(len: Int): Array[Int] = new Array[Int](len) override def newWrappedArray(len: Int): WrappedArray[Int] = new WrappedArray.ofInt(new Array[Int](len)) override def newArrayBuilder(): ArrayBuilder[Int] = new ArrayBuilder.ofInt() @@ -114,7 +116,7 @@ object Manifest { } val Long: AnyValManifest[Long] = new AnyValManifest[scala.Long]("Long") { - def erasure = java.lang.Long.TYPE + def runtimeClass = java.lang.Long.TYPE override def newArray(len: Int): Array[Long] = new Array[Long](len) override def newWrappedArray(len: Int): WrappedArray[Long] = new WrappedArray.ofLong(new Array[Long](len)) override def newArrayBuilder(): ArrayBuilder[Long] = new ArrayBuilder.ofLong() @@ -122,7 +124,7 @@ object Manifest { } val Float: AnyValManifest[Float] = new AnyValManifest[scala.Float]("Float") { - def erasure = java.lang.Float.TYPE + def runtimeClass = java.lang.Float.TYPE override def newArray(len: Int): Array[Float] = new Array[Float](len) override def newWrappedArray(len: Int): WrappedArray[Float] = new WrappedArray.ofFloat(new Array[Float](len)) override def newArrayBuilder(): ArrayBuilder[Float] = new ArrayBuilder.ofFloat() @@ -130,7 +132,7 @@ object Manifest { } val Double: AnyValManifest[Double] = new AnyValManifest[scala.Double]("Double") { - def erasure = java.lang.Double.TYPE + def runtimeClass = java.lang.Double.TYPE override def newArray(len: Int): Array[Double] = new Array[Double](len) override def newWrappedArray(len: Int): WrappedArray[Double] = new WrappedArray.ofDouble(new Array[Double](len)) override def newArrayBuilder(): ArrayBuilder[Double] = new ArrayBuilder.ofDouble() @@ -138,7 +140,7 @@ object Manifest { } val Boolean: AnyValManifest[Boolean] = new AnyValManifest[scala.Boolean]("Boolean") { - def erasure = java.lang.Boolean.TYPE + def runtimeClass = java.lang.Boolean.TYPE override def newArray(len: Int): Array[Boolean] = new Array[Boolean](len) override def newWrappedArray(len: Int): WrappedArray[Boolean] = new WrappedArray.ofBoolean(new Array[Boolean](len)) override def newArrayBuilder(): ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean() @@ -146,7 +148,7 @@ object Manifest { } val Unit: AnyValManifest[Unit] = new AnyValManifest[scala.Unit]("Unit") { - def erasure = java.lang.Void.TYPE + def runtimeClass = java.lang.Void.TYPE override def newArray(len: Int): Array[Unit] = new Array[Unit](len) override def newWrappedArray(len: Int): WrappedArray[Unit] = new WrappedArray.ofUnit(new Array[Unit](len)) override def newArrayBuilder(): ArrayBuilder[Unit] = new ArrayBuilder.ofUnit() @@ -180,7 +182,7 @@ object Manifest { } private class SingletonTypeManifest[T <: AnyRef](value: AnyRef) extends Manifest[T] { - lazy val erasure = value.getClass + lazy val runtimeClass = value.getClass override lazy val toString = value.toString + ".type" } @@ -217,7 +219,7 @@ object Manifest { /** Manifest for the class type `clazz[args]`, where `clazz` is * a top-level or static class. */ private class ClassTypeManifest[T](prefix: Option[Manifest[_]], - val erasure: Predef.Class[_], + val runtimeClass: Predef.Class[_], override val typeArguments: List[Manifest[_]]) extends Manifest[T] { override def toString = (if (prefix.isEmpty) "" else prefix.get.toString+"#") + @@ -233,7 +235,7 @@ object Manifest { * added so that erasure can be calculated without reflection. */ def abstractType[T](prefix: Manifest[_], name: String, upperBound: Predef.Class[_], args: Manifest[_]*): Manifest[T] = new Manifest[T] { - def erasure = upperBound + def runtimeClass = upperBound override val typeArguments = args.toList override def toString = prefix.toString+"#"+name+argString } @@ -242,7 +244,7 @@ object Manifest { */ def wildcardType[T](lowerBound: Manifest[_], upperBound: Manifest[_]): Manifest[T] = new Manifest[T] { - def erasure = upperBound.erasure + def runtimeClass = upperBound.erasure override def toString = "_" + (if (lowerBound eq Nothing) "" else " >: "+lowerBound) + @@ -252,7 +254,7 @@ object Manifest { /** Manifest for the intersection type `parents_0 with ... with parents_n'. */ def intersectionType[T](parents: Manifest[_]*): Manifest[T] = new Manifest[T] { - def erasure = parents.head.erasure + def runtimeClass = parents.head.erasure override def toString = parents.mkString(" with ") } }
\ No newline at end of file diff --git a/src/library/scala/reflect/NoManifest.scala b/src/library/scala/reflect/NoManifest.scala index 7b8037272c..95b4ddca1c 100644 --- a/src/library/scala/reflect/NoManifest.scala +++ b/src/library/scala/reflect/NoManifest.scala @@ -10,7 +10,7 @@ package scala.reflect /** One of the branches of an [[scala.reflect.OptManifest]]. */ -@deprecated("Use `@scala.reflect.TypeTag` instead", "2.10.0") +@deprecated("This notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") object NoManifest extends OptManifest[Nothing] with Serializable { override def toString = "<?>" }
\ No newline at end of file diff --git a/src/library/scala/reflect/OptManifest.scala b/src/library/scala/reflect/OptManifest.scala index 46f23c4e22..0ea66cb53d 100644 --- a/src/library/scala/reflect/OptManifest.scala +++ b/src/library/scala/reflect/OptManifest.scala @@ -14,5 +14,5 @@ package scala.reflect * * @author Martin Odersky */ -@deprecated("Use `@scala.reflect.TypeTag` instead", "2.10.0") +@deprecated("This notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") trait OptManifest[+T] extends Serializable
\ No newline at end of file diff --git a/src/library/scala/reflect/base/Base.scala b/src/library/scala/reflect/base/Base.scala index e9d963dc78..a4e6256f4d 100644 --- a/src/library/scala/reflect/base/Base.scala +++ b/src/library/scala/reflect/base/Base.scala @@ -101,8 +101,8 @@ class Base extends Universe { self => } implicit val TypeTagg = ClassTag[Type](classOf[Type]) - val NoType = new Type - val NoPrefix = new Type + val NoType = new Type { override def toString = "NoType" } + val NoPrefix = new Type { override def toString = "NoPrefix" } class SingletonType extends Type implicit val SingletonTypeTag = ClassTag[SingletonType](classOf[SingletonType]) @@ -425,7 +425,6 @@ class Base extends Universe { self => lazy val NullTpe = TypeRef(ScalaPrefix, NullClass, Nil) lazy val ObjectTpe = TypeRef(JavaLangPrefix, ObjectClass, Nil) lazy val AnyRefTpe = ObjectTpe - lazy val StringTpe = TypeRef(JavaLangPrefix, StringClass, Nil) private var nodeCount = 0 // not synchronized diff --git a/src/library/scala/reflect/base/StandardDefinitions.scala b/src/library/scala/reflect/base/StandardDefinitions.scala index eff23b539e..2f270a5911 100644 --- a/src/library/scala/reflect/base/StandardDefinitions.scala +++ b/src/library/scala/reflect/base/StandardDefinitions.scala @@ -27,7 +27,6 @@ trait StandardTypes { val NothingTpe: Type val NullTpe: Type - val StringTpe: Type } trait StandardDefinitions extends StandardTypes { diff --git a/src/library/scala/reflect/base/TagInterop.scala b/src/library/scala/reflect/base/TagInterop.scala index 158d1979e5..a9f0b60fd2 100644 --- a/src/library/scala/reflect/base/TagInterop.scala +++ b/src/library/scala/reflect/base/TagInterop.scala @@ -4,17 +4,6 @@ package base import scala.runtime.ScalaRunTime._ trait TagInterop { self: Universe => - def classTagToClassManifest[T](tag: ClassTag[T]): ClassManifest[T] = { - val runtimeClass = tag.runtimeClass - if (runtimeClass.isArray) { - val elementClass = arrayElementClass(runtimeClass) - val elementManifest = classTagToClassManifest(ClassTag(elementClass)) - ClassManifest.arrayType(elementManifest).asInstanceOf[ClassManifest[T]] - } else { - ClassManifest.fromClass(runtimeClass.asInstanceOf[Class[T]]) - } - } - // [Eugene++] `mirror` parameters are now of type `Any`, because I can't make these path-dependent types work // if you're brave enough, replace `Any` with `Mirror`, recompile and run interop_typetags_are_manifests.scala diff --git a/src/library/scala/reflect/base/TypeTags.scala b/src/library/scala/reflect/base/TypeTags.scala index 774bc6ebea..1906118ed1 100644 --- a/src/library/scala/reflect/base/TypeTags.scala +++ b/src/library/scala/reflect/base/TypeTags.scala @@ -137,7 +137,6 @@ trait TypeTags { self: Universe => val Object : AbsTypeTag[java.lang.Object] = TypeTag.Object val Nothing : AbsTypeTag[scala.Nothing] = TypeTag.Nothing val Null : AbsTypeTag[scala.Null] = TypeTag.Null - val String : AbsTypeTag[java.lang.String] = TypeTag.String def apply[T](mirror1: MirrorOf[self.type], tpec1: TypeCreator): AbsTypeTag[T] = tpec1(mirror1) match { @@ -154,7 +153,6 @@ trait TypeTags { self: Universe => case ObjectTpe => AbsTypeTag.Object.asInstanceOf[AbsTypeTag[T]] case NothingTpe => AbsTypeTag.Nothing.asInstanceOf[AbsTypeTag[T]] case NullTpe => AbsTypeTag.Null.asInstanceOf[AbsTypeTag[T]] - case StringTpe => AbsTypeTag.String.asInstanceOf[AbsTypeTag[T]] case _ => new AbsTypeTagImpl[T](mirror1.asInstanceOf[Mirror], tpec1) } @@ -200,7 +198,6 @@ trait TypeTags { self: Universe => val Object: TypeTag[java.lang.Object] = new PredefTypeTag[java.lang.Object] (ObjectTpe, _.TypeTag.Object) val Nothing: TypeTag[scala.Nothing] = new PredefTypeTag[scala.Nothing] (NothingTpe, _.TypeTag.Nothing) val Null: TypeTag[scala.Null] = new PredefTypeTag[scala.Null] (NullTpe, _.TypeTag.Null) - val String: TypeTag[java.lang.String] = new PredefTypeTag[java.lang.String] (StringTpe, _.TypeTag.String) def apply[T](mirror1: MirrorOf[self.type], tpec1: TypeCreator): TypeTag[T] = tpec1(mirror1) match { @@ -217,7 +214,6 @@ trait TypeTags { self: Universe => case ObjectTpe => TypeTag.Object.asInstanceOf[TypeTag[T]] case NothingTpe => TypeTag.Nothing.asInstanceOf[TypeTag[T]] case NullTpe => TypeTag.Null.asInstanceOf[TypeTag[T]] - case StringTpe => TypeTag.String.asInstanceOf[TypeTag[T]] case _ => new TypeTagImpl[T](mirror1.asInstanceOf[Mirror], tpec1) } diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala index 2ebc82875e..9f9d4089c4 100644 --- a/src/library/scala/reflect/package.scala +++ b/src/library/scala/reflect/package.scala @@ -4,14 +4,51 @@ package object reflect { lazy val basis: base.Universe = new base.Base + // in the new scheme of things ClassManifests are aliased to ClassTags + // this is done because we want `toArray` in collections work with ClassTags + // but changing it to use the ClassTag context bound without aliasing ClassManifest + // will break everyone who subclasses and overrides `toArray` + // luckily for us, aliasing doesn't hamper backward compatibility, so it's ideal in this situation + // I wish we could do the same for Manifests and TypeTags though + + // note, by the way, that we don't touch ClassManifest the object + // because its Byte, Short and so on factory fields are incompatible with ClassTag's + + /** A `ClassManifest[T]` is an opaque descriptor for type `T`. + * It is used by the compiler to preserve information necessary + * for instantiating `Arrays` in those cases where the element type + * is unknown at compile time. + * + * The type-relation operators make an effort to present a more accurate + * picture than can be realized with erased types, but they should not be + * relied upon to give correct answers. In particular they are likely to + * be wrong when variance is involved or when a subtype has a different + * number of type arguments than a supertype. + */ + @deprecated("Use scala.reflect.ClassTag instead", "2.10.0") + @annotation.implicitNotFound(msg = "No ClassManifest available for ${T}.") + type ClassManifest[T] = scala.reflect.ClassTag[T] + + /** The object `ClassManifest` defines factory methods for manifests. + * It is intended for use by the compiler and should not be used in client code. + */ + @deprecated("Use scala.reflect.ClassTag instead", "2.10.0") + val ClassManifest = ClassManifestFactory + + /** The object `Manifest` defines factory methods for manifests. + * It is intended for use by the compiler and should not be used in client code. + */ + @deprecated("Use scala.reflect.ClassTag (to capture erasures), scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") + val Manifest = ManifestFactory + def classTag[T](implicit ctag: ClassTag[T]) = ctag // typeTag incantation is defined inside scala.reflect.basis and scala.reflect.runtime.universe // ClassTag class is defined in ClassTag.scala - type TypeTag[T] = scala.reflect.basis.TypeTag[T] + type TypeTag[T] = scala.reflect.basis.TypeTag[T] // ClassTag object is defined in ClassTag.scala - lazy val TypeTag = scala.reflect.basis.TypeTag + lazy val TypeTag = scala.reflect.basis.TypeTag @deprecated("Use `@scala.beans.BeanDescription` instead", "2.10.0") type BeanDescription = scala.beans.BeanDescription diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala index 7f4ff8a7fb..27d3b8ba7d 100644 --- a/src/reflect/scala/reflect/api/Printers.scala +++ b/src/reflect/scala/reflect/api/Printers.scala @@ -10,12 +10,15 @@ trait Printers { self: Universe => protected var printTypes = false protected var printIds = false protected var printKinds = false + protected var printMirrors = false def withTypes: this.type = { printTypes = true; this } def withoutTypes: this.type = { printTypes = false; this } def withIds: this.type = { printIds = true; this } def withoutIds: this.type = { printIds = false; this } def withKinds: this.type = { printKinds = true; this } def withoutKinds: this.type = { printKinds = false; this } + def withMirrors: this.type = { printMirrors = true; this } + def withoutMirrors: this.type = { printMirrors = false; this } } case class BooleanFlag(val value: Option[Boolean]) @@ -25,13 +28,14 @@ trait Printers { self: Universe => implicit def optionToBooleanFlag(value: Option[Boolean]): BooleanFlag = BooleanFlag(value) } - protected def render(what: Any, mkPrinter: PrintWriter => TreePrinter, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None): String = { + protected def render(what: Any, mkPrinter: PrintWriter => TreePrinter, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None): String = { val buffer = new StringWriter() val writer = new PrintWriter(buffer) var printer = mkPrinter(writer) printTypes.value.map(printTypes => if (printTypes) printer.withTypes else printer.withoutTypes) printIds.value.map(printIds => if (printIds) printer.withIds else printer.withoutIds) printKinds.value.map(printKinds => if (printKinds) printer.withKinds else printer.withoutKinds) + printMirrors.value.map(printMirrors => if (printMirrors) printer.withMirrors else printer.withoutMirrors) printer.print(what) writer.flush() buffer.toString @@ -40,42 +44,25 @@ trait Printers { self: Universe => /** By default trees are printed with `show` */ override protected def treeToString(tree: Tree) = show(tree) - /** Renders a prettified representation of a tree. + /** Renders a prettified representation of a reflection artifact. * Typically it looks very close to the Scala code it represents. - * This function is used in Tree.toString. */ - def show(tree: Tree, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None): String = - render(tree, newTreePrinter(_), printTypes, printIds, printKinds) + def show(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None): String = + render(any, newTreePrinter(_), printTypes, printIds, printKinds, printMirrors) - /** Hook to define what `show(tree)` means. + /** Hook to define what `show(...)` means. */ def newTreePrinter(out: PrintWriter): TreePrinter - /** Renders internal structure of a tree. + /** Renders internal structure of a reflection artifact. */ - def showRaw(tree: Tree, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None): String = - render(tree, newRawTreePrinter(_), printTypes, printIds, printKinds) + def showRaw(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None): String = + render(any, newRawTreePrinter(_), printTypes, printIds, printKinds, printMirrors) - /** Hook to define what `showRaw(tree)` means. + /** Hook to define what `showRaw(...)` means. */ def newRawTreePrinter(out: PrintWriter): TreePrinter - /** Renders a prettified representation of a symbol. - */ - def show(sym: Symbol): String = sym.toString - - /** Renders internal structure of a symbol. - */ - def showRaw(sym: Symbol): String = render(sym, newRawTreePrinter(_)) - - /** Renders a prettified representation of a type. - */ - def show(tpe: Type): String = tpe.toString - - /** Renders internal structure of a type. - */ - def showRaw(tpe: Type): String = render(tpe, newRawTreePrinter(_)) - /** Renders a prettified representation of a name. */ def show(name: Name): String diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 320cd3ddae..7891433b4f 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -35,7 +35,6 @@ trait Definitions extends api.StandardDefinitions { lazy val AnyRefTpe = definitions.AnyRefClass.asType lazy val NothingTpe = definitions.NothingClass.asType lazy val NullTpe = definitions.NullClass.asType - lazy val StringTpe = definitions.StringClass.asType /** Since both the value parameter types and the result type may * require access to the type parameter symbols, we model polymorphic @@ -454,10 +453,10 @@ trait Definitions extends api.StandardDefinitions { def ReflectRuntimeUniverse = if (ReflectRuntimePackage != NoSymbol) getMemberValue(ReflectRuntimePackage, nme.universe) else NoSymbol def ReflectRuntimeCurrentMirror = if (ReflectRuntimePackage != NoSymbol) getMemberMethod(ReflectRuntimePackage, nme.currentMirror) else NoSymbol - lazy val PartialManifestClass = requiredClass[scala.reflect.ClassManifest[_]] - lazy val PartialManifestModule = requiredModule[scala.reflect.ClassManifest.type] + lazy val PartialManifestClass = getMemberType(ReflectPackage, tpnme.ClassManifest) + lazy val PartialManifestModule = requiredModule[scala.reflect.ClassManifestFactory.type] lazy val FullManifestClass = requiredClass[scala.reflect.Manifest[_]] - lazy val FullManifestModule = requiredModule[scala.reflect.Manifest.type] + lazy val FullManifestModule = requiredModule[scala.reflect.ManifestFactory.type] lazy val OptManifestClass = requiredClass[scala.reflect.OptManifest[_]] lazy val NoManifest = requiredModule[scala.reflect.NoManifest.type] diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala index 82a8c42f7c..c018ddc88e 100644 --- a/src/reflect/scala/reflect/internal/Printers.scala +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -10,6 +10,7 @@ package internal import java.io.{ OutputStream, PrintWriter, StringWriter, Writer } import Flags._ +import compat.Platform.EOL trait Printers extends api.Printers { self: SymbolTable => @@ -65,6 +66,7 @@ trait Printers extends api.Printers { self: SymbolTable => printTypes = settings.printtypes.value printIds = settings.uniqid.value printKinds = settings.Yshowsymkinds.value + printMirrors = false // typically there's no point to print mirrors inside the compiler, as there is only one mirror there protected def doPrintPositions = settings.Xprintpos.value def indent() = indentMargin += indentStep @@ -477,22 +479,61 @@ trait Printers extends api.Printers { self: SymbolTable => def flush = { /* do nothing */ } } - // provides footnotes for types - private var typeCounter = 0 - private val typeMap = collection.mutable.WeakHashMap[Type, Int]() - def newRawTreePrinter(writer: PrintWriter): RawTreePrinter = new RawTreePrinter(writer) def newRawTreePrinter(stream: OutputStream): RawTreePrinter = newRawTreePrinter(new PrintWriter(stream)) def newRawTreePrinter(): RawTreePrinter = newRawTreePrinter(new PrintWriter(ConsoleWriter)) + // provides footnotes for types and mirrors + import scala.collection.mutable.{Map, WeakHashMap, SortedSet} + private val footnoteIndex = new FootnoteIndex + private class FootnoteIndex { + private val index = Map[Class[_], WeakHashMap[Any, Int]]() + private def classIndex[T: ClassTag] = index.getOrElseUpdate(classTag[T].runtimeClass, WeakHashMap[Any, Int]()) + private val counters = Map[Class[_], Int]() + private def nextCounter[T: ClassTag] = { + val clazz = classTag[T].runtimeClass + counters.getOrElseUpdate(clazz, 0) + counters(clazz) = counters(clazz) + 1 + counters(clazz) + } + + def mkFootnotes() = new Footnotes + class Footnotes { + private val footnotes = Map[Class[_], SortedSet[Int]]() + private def classFootnotes[T: ClassTag] = footnotes.getOrElseUpdate(classTag[T].runtimeClass, SortedSet[Int]()) + + def put[T: ClassTag](any: T): Int = { + val index = classIndex[T].getOrElseUpdate(any, nextCounter[T]) + classFootnotes[T] += index + index + } + + def get[T: ClassTag]: List[(Int, Any)] = + classFootnotes[T].toList map (fi => (fi, classIndex[T].find{ case (any, ii) => ii == fi }.get._1)) + + def print[T: ClassTag](printer: Printers.super.TreePrinter): Unit = { + val footnotes = get[T] + if (footnotes.nonEmpty) { + printer.print(EOL) + footnotes.zipWithIndex foreach { + case ((fi, any), ii) => + printer.print("[", fi, "] ", any) + if (ii < footnotes.length - 1) printer.print(EOL) + } + } + } + } + } + // emits more or less verbatim representation of the provided tree class RawTreePrinter(out: PrintWriter) extends super.TreePrinter { private var depth = 0 - private var footnotes = collection.mutable.Map[Int, Type]() - private var printingFootnotes = false private var printTypesInFootnotes = true + private var printingFootnotes = false + private var footnotes = footnoteIndex.mkFootnotes() def print(args: Any*): Unit = { + // don't print type footnotes if the argument is a mere type if (depth == 0 && args.length == 1 && args(0) != null && args(0).isInstanceOf[Type]) printTypesInFootnotes = false @@ -544,14 +585,15 @@ trait Printers extends api.Printers { self: SymbolTable => else print(sym.name) if (printIds) print("#", sym.id) if (printKinds) print("#", sym.abbreviatedKindString) + if (printMirrors) print("%M", footnotes.put[MirrorOf[_]](mirrorThatLoaded(sym))) case NoType => print("NoType") case NoPrefix => print("NoPrefix") - case tpe: Type if printTypesInFootnotes && !printingFootnotes => - val index = typeMap.getOrElseUpdate(tpe, { typeCounter += 1; typeCounter }) - footnotes(index) = tpe - print("[", index, "]") + case tpe: Type => + val defer = printTypesInFootnotes && !printingFootnotes + if (defer) print("[", footnotes.put(tpe), "]") + else printProduct(tpe.asInstanceOf[Product]) case mods: Modifiers => print("Modifiers(") if (mods.flags != NoFlags || mods.privateWithin != tpnme.EMPTY || mods.annotations.nonEmpty) print(show(mods.flags)) @@ -569,16 +611,11 @@ trait Printers extends api.Printers { self: SymbolTable => out.print(arg) } depth -= 1 - if (depth == 0 && footnotes.nonEmpty && !printingFootnotes) { + if (depth == 0 && !printingFootnotes) { printingFootnotes = true - out.println() - val typeIndices = footnotes.keys.toList.sorted - typeIndices.zipWithIndex foreach { - case (typeIndex, i) => - print("[" + typeIndex + "] ") - print(footnotes(typeIndex)) - if (i < typeIndices.length - 1) out.println() - } + footnotes.print[Type](this) + footnotes.print[MirrorOf[_]](this) + printingFootnotes = false } } diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index bd02013037..72a99589d5 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -232,6 +232,7 @@ trait StdNames { final val Annotation: NameType = "Annotation" final val ClassfileAnnotation: NameType = "ClassfileAnnotation" + final val ClassManifest: NameType = "ClassManifest" final val Enum: NameType = "Enum" final val Group: NameType = "Group" final val Tree: NameType = "Tree" @@ -639,8 +640,8 @@ trait StdNames { val bytes: NameType = "bytes" val canEqual_ : NameType = "canEqual" val checkInitialized: NameType = "checkInitialized" + val ClassManifestFactory: NameType = "ClassManifestFactory" val classOf: NameType = "classOf" - val classTagToClassManifest: NameType = "classTagToClassManifest" val clone_ : NameType = if (forMSIL) "MemberwiseClone" else "clone" // sn.OClone causes checkinit failure val conforms: NameType = "conforms" val copy: NameType = "copy" @@ -696,6 +697,7 @@ trait StdNames { val macroContext : NameType = "c" val main: NameType = "main" val manifest: NameType = "manifest" + val ManifestFactory: NameType = "ManifestFactory" val manifestToTypeTag: NameType = "manifestToTypeTag" val map: NameType = "map" val materializeClassTag: NameType = "materializeClassTag" diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index abdb344b92..119c3d42fd 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -899,15 +899,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => if (owner.isTerm) return false if (isLocalDummy) return false + if (isAliasType) return true if (isType && isNonClassType) return false if (isRefinementClass) return false return true } - // [Eugene] is it a good idea to add ``dealias'' to Symbol? - /** Expands type aliases */ - def dealias: Symbol = this - /** The variance of this symbol as an integer */ final def variance: Int = if (isCovariant) 1 @@ -2563,7 +2560,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => extends TypeSymbol(initOwner, initPos, initName) { type TypeOfClonedSymbol = TypeSymbol final override def isAliasType = true - final override def dealias = info.typeSymbol.dealias override def cloneSymbolImpl(owner: Symbol, newFlags: Long): TypeSymbol = owner.newNonClassSymbol(name, pos, newFlags) } diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 4cf2cceb81..5a382cf518 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -568,6 +568,24 @@ trait Types extends api.Types { self: SymbolTable => /** Expands type aliases. */ def dealias = this + def etaExpand: Type = this + + /** Performs a single step of beta-reduction on types. + * Given: + * + * type C[T] = B[T] + * type B[T] = A + * class A + * + * The following will happen after `betaReduce` is invoked: + * TypeRef(pre, <C>, List(Int)) is replaced by + * TypeRef(pre, <B>, List(Int)) + * + * Unlike `dealias`, which recursively applies beta reduction, until it's stuck, + * `betaReduce` performs exactly one step and then returns. + */ + def betaReduce: Type = this + /** For a classtype or refined type, its defined or declared members; * inherited by subtypes and typerefs. * The empty scope for all other types. @@ -2110,7 +2128,7 @@ trait Types extends api.Types { self: SymbolTable => // // this crashes pos/depmet_implicit_tpbetareduce.scala // appliedType(sym.info, typeArgs).asSeenFrom(pre, sym.owner) - def betaReduce = transform(sym.info.resultType) + override def betaReduce = transform(sym.info.resultType) // #3731: return sym1 for which holds: pre bound sym.name to sym and // pre1 now binds sym.name to sym1, conceptually exactly the same @@ -2221,7 +2239,7 @@ trait Types extends api.Types { self: SymbolTable => || pre.isGround && args.forall(_.isGround) ) - def etaExpand: Type = { + override def etaExpand: Type = { // must initialise symbol, see test/files/pos/ticket0137.scala val tpars = initializedTypeParams if (tpars.isEmpty) this diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 38d280ec73..41955170bd 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -972,6 +972,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym case ExistentialType(_, rtpe) => typeToJavaClass(rtpe) case TypeRef(_, ArrayClass, List(elemtpe)) => jArrayClass(typeToJavaClass(elemtpe)) case TypeRef(_, sym: ClassSymbol, _) => classToJava(sym.asClassSymbol) + case tpe @ TypeRef(_, sym: AliasTypeSymbol, _) => typeToJavaClass(tpe.dealias) case _ => throw new NoClassDefFoundError("no Java class corresponding to "+tpe+" found") } } diff --git a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala index 4e82fe8ad2..7839850529 100644 --- a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala +++ b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala @@ -37,12 +37,17 @@ object ReflectionUtils { systemProperties find (_._1 endsWith ".boot.class.path") map (_._2) getOrElse "" ) - def show(cl: ClassLoader) = { + def show(cl: ClassLoader): String = { + def isAbstractFileClassLoader(clazz: Class[_]): Boolean = { + if (clazz == null) return false + if (clazz.getName == "scala.tools.nsc.interpreter.AbstractFileClassLoader") return true + return isAbstractFileClassLoader(clazz.getSuperclass) + } def inferClasspath(cl: ClassLoader): String = cl match { case cl: java.net.URLClassLoader => - "[" + (cl.getURLs mkString ",") + "]" - case cl if cl != null && cl.getClass.getName == "scala.tools.nsc.interpreter.AbstractFileClassLoader" => - "[" + cl.asInstanceOf[{val root: scala.reflect.internal.AbstractFileApi}].root + "] and " + inferClasspath(cl.getParent) + (cl.getURLs mkString ",") + case cl if cl != null && isAbstractFileClassLoader(cl.getClass) => + cl.asInstanceOf[{val root: scala.reflect.internal.AbstractFileApi}].root.canonicalPath case null => inferBootClasspath case _ => @@ -50,7 +55,7 @@ object ReflectionUtils { } cl match { case cl if cl != null => - "%s of type %s with classpath %s".format(cl, cl.getClass, inferClasspath(cl)) + "%s of type %s with classpath [%s] and parent being %s".format(cl, cl.getClass, inferClasspath(cl), show(cl.getParent)) case null => "primordial classloader with boot classpath [%s]".format(inferClasspath(cl)) } |