diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2012-06-07 15:44:04 +0200 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2012-06-08 15:32:46 +0200 |
commit | bc5f42f51982eb473075bbd2f474a5d628813031 (patch) | |
tree | a57578c5a21ced5ed38c1a098646fa95ea88f5c2 /src/compiler/scala/tools | |
parent | 07f7baa21c165d6c2302a8ea26c475968e7d775e (diff) | |
download | scala-bc5f42f51982eb473075bbd2f474a5d628813031.tar.gz scala-bc5f42f51982eb473075bbd2f474a5d628813031.tar.bz2 scala-bc5f42f51982eb473075bbd2f474a5d628813031.zip |
removes array tags
Before 2.10 we had a notion of ClassManifest that could be used to retain
erasures of abstract types (type parameters, abstract type members) for
being used at runtime.
With the advent of ClassManifest (and its subtype Manifest)
it became possible to write:
def mkGenericArray[T: Manifest] = Array[T]()
When compiling array instantiation, scalac would use a ClassManifest
implicit parameter from scope (in this case, provided by a context bound)
to remember Ts that have been passed to invoke mkGenericArray and
use that information to instantiate arrays at runtime (via Java reflection).
When redesigning manifests into what is now known as type tags, we decided
to explore a notion of ArrayTags that would stand for abstract and pure array
creators. Sure, ClassManifests were perfectly fine for this job, but they did
too much - technically speaking, one doesn't necessarily need a java.lang.Class
to create an array. Depending on a platform, e.g. within JavaScript runtime,
one would want to use a different mechanism.
As tempting as this idea was, it has also proven to be problematic.
First, it created an extra abstraction inside the compiler. Along with class tags
and type tags, we had a third flavor of tags - array tags. This has threaded the
additional complexity though implicits and typers.
Second, consequently, when redesigning tags multiple times over the course of
Scala 2.10.0 development, we had to carry this extra abstraction with us, which
exacerbated the overall feeling towards array tags.
Finally, array tags didn't fit into the naming scheme we had for tags.
Both class tags and type tags sound logical, because, they are descriptors for
the things they are supposed to tag, according to their names.
However array tags are the odd ones, because they don't actually tag any arrays.
As funny as it might sound, the naming problem was the last straw
that made us do away with the array tags. Hence this commit.
Diffstat (limited to 'src/compiler/scala/tools')
7 files changed, 22 insertions, 42 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index db3d8b2785..663b3dd2e9 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -418,23 +418,23 @@ abstract class UnCurry extends InfoTransform def sequenceToArray(tree: Tree) = { val toArraySym = tree.tpe member nme.toArray assert(toArraySym != NoSymbol) - def getArrayTag(tp: Type): Tree = { - val tag = localTyper.resolveArrayTag(tree.pos, tp) + def getClassTag(tp: Type): Tree = { + val tag = localTyper.resolveClassTag(tree.pos, tp) // Don't want bottom types getting any further than this (SI-4024) - if (tp.typeSymbol.isBottomClass) getArrayTag(AnyClass.tpe) + if (tp.typeSymbol.isBottomClass) getClassTag(AnyClass.tpe) else if (!tag.isEmpty) tag - else if (tp.bounds.hi ne tp) getArrayTag(tp.bounds.hi) - else localTyper.TyperErrorGen.MissingArrayTagError(tree, tp) + else if (tp.bounds.hi ne tp) getClassTag(tp.bounds.hi) + else localTyper.TyperErrorGen.MissingClassTagError(tree, tp) } - def traversableArrayTag(tpe: Type): Tree = { + def traversableClassTag(tpe: Type): Tree = { (tpe baseType TraversableClass).typeArgs match { - case targ :: _ => getArrayTag(targ) + case targ :: _ => getClassTag(targ) case _ => EmptyTree } } afterUncurry { localTyper.typedPos(pos) { - gen.mkMethodCall(tree, toArraySym, Nil, List(traversableArrayTag(tree.tpe))) + gen.mkMethodCall(tree, toArraySym, Nil, List(traversableClassTag(tree.tpe))) } } } @@ -688,7 +688,7 @@ abstract class UnCurry extends InfoTransform tree match { /* Some uncurry post transformations add members to templates. - * + * * Members registered by `addMembers` for the current template are added * once the template transformation has finished. * diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 94e7dc0d65..a2f0e053a8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -562,9 +562,9 @@ trait ContextErrors { def AbstractExistentiallyOverParamerizedTpeError(tree: Tree, tp: Type) = issueNormalTypeError(tree, "can't existentially abstract over parameterized type " + tp) - // resolveArrayTag - def MissingArrayTagError(tree: Tree, tp: Type) = { - issueNormalTypeError(tree, "cannot find array tag for element type "+tp) + // resolveClassTag + def MissingClassTagError(tree: Tree, tp: Type) = { + issueNormalTypeError(tree, "cannot find class tag for element type "+tp) setError(tree) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 1ec4a7dc44..6d8ddab743 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1133,7 +1133,6 @@ trait Implicits { private def TagSymbols = TagMaterializers.keySet private val TagMaterializers = Map[Symbol, Symbol]( - ArrayTagClass -> MacroInternal_materializeArrayTag, ClassTagClass -> MacroInternal_materializeClassTag, TypeTagClass -> MacroInternal_materializeTypeTag, ConcreteTypeTagClass -> MacroInternal_materializeConcreteTypeTag @@ -1166,9 +1165,8 @@ trait Implicits { } val prefix = ( - // ClassTags and ArrayTags only exist for scala.reflect, so their materializer - // doesn't care about prefixes - if ((tagClass eq ArrayTagClass) || (tagClass eq ClassTagClass)) gen.mkBasisUniverseRef + // ClassTags are not path-dependent, so their materializer doesn't care about prefixes + if (tagClass eq ClassTagClass) gen.mkBasisUniverseRef else pre match { // [Eugene to Martin] this is the crux of the interaction between // implicits and reifiers here we need to turn a (supposedly @@ -1296,7 +1294,7 @@ trait Implicits { val tagInScope = if (full) resolveTypeTag(pos, NoType, tp, concrete = true, allowMaterialization = false) - else resolveArrayTag(pos, tp, allowMaterialization = false) + else resolveClassTag(pos, tp, allowMaterialization = false) if (tagInScope.isEmpty) mot(tp, Nil, Nil) else { if (full) { @@ -1321,7 +1319,7 @@ trait Implicits { if (full) { val cm = typed(Ident(ReflectRuntimeCurrentMirror)) gen.mkMethodCall(ReflectRuntimeUniverse, nme.concreteTypeTagToManifest, List(tp), List(cm, tagInScope)) - } else gen.mkMethodCall(ReflectRuntimeUniverse, nme.arrayTagToClassManifest, List(tp), List(tagInScope)) + } else gen.mkMethodCall(ReflectRuntimeUniverse, nme.classTagToClassManifest, List(tp), List(tagInScope)) wrapResult(interop) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index f64c4a4ce1..61443faba0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -9,7 +9,7 @@ package typechecker import symtab.Flags._ import scala.collection.mutable import scala.ref.WeakReference -import scala.reflect.ArrayTag +import scala.reflect.ClassTag /** * @author Lukas Rytz @@ -40,14 +40,14 @@ trait NamesDefaults { self: Analyzer => def isNamed(arg: Tree) = nameOf(arg).isDefined /** @param pos maps indices from old to new */ - def reorderArgs[T: ArrayTag](args: List[T], pos: Int => Int): List[T] = { + def reorderArgs[T: ClassTag](args: List[T], pos: Int => Int): List[T] = { val res = new Array[T](args.length) foreachWithIndex(args)((arg, index) => res(pos(index)) = arg) res.toList } /** @param pos maps indices from new to old (!) */ - def reorderArgsInv[T: ArrayTag](args: List[T], pos: Int => Int): List[T] = { + def reorderArgsInv[T: ClassTag](args: List[T], pos: Int => Int): List[T] = { val argsArray = args.toArray (argsArray.indices map (i => argsArray(pos(i)))).toList } diff --git a/src/compiler/scala/tools/nsc/typechecker/Tags.scala b/src/compiler/scala/tools/nsc/typechecker/Tags.scala index d371f02d1d..753dbb8978 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Tags.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Tags.scala @@ -23,23 +23,6 @@ trait Tags { ).tree) } - /** Finds in scope or materializes an ArrayTag. - * Should be used instead of ClassTag or ClassManifest every time compiler needs to create an array. - * - * @param pos Position for error reporting. Please, provide meaningful value. - * @param tp Type we're looking an ArrayTag for, e.g. resolveArrayTag(pos, IntClass.tpe) will look for ArrayTag[Int]. - * @param allowMaterialization If true (default) then the resolver is allowed to launch materialization macros when there's no array tag in scope. - * If false then materialization macros are prohibited from running. - * - * @returns Tree that represents an `scala.reflect.ArrayTag` for `tp` if everything is okay. - * EmptyTree if `allowMaterialization` is false, and there is no array tag in scope. - * EmptyTree if the result contains unresolved (i.e. not spliced) type parameters and abstract type members. - */ - def resolveArrayTag(pos: Position, tp: Type, allowMaterialization: Boolean = true): Tree = { - val taggedTp = appliedType(ArrayTagClass.typeConstructor, List(tp)) - resolveTag(pos, taggedTp, allowMaterialization) - } - /** Finds in scope or materializes a ClassTag. * Should be used instead of ClassManifest every time compiler needs to persist an erasure. * diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index a7c69a4e39..0abf7b0c6a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3158,7 +3158,7 @@ trait Typers extends Modes with Adaptations with Tags { if (annInfo.atp.isErroneous) { hasError = true; None } else Some(NestedAnnotArg(annInfo)) - // use of Array.apply[T: ArrayTag](xs: T*): Array[T] + // use of Array.apply[T: ClassTag](xs: T*): Array[T] // and Array.apply(x: Int, xs: Int*): Array[Int] (and similar) case Apply(fun, args) => val typedFun = typed(fun, forFunMode(mode), WildcardType) @@ -4864,8 +4864,8 @@ trait Typers extends Modes with Adaptations with Tags { val Some((level, componentType)) = erasure.GenericArray.unapply(tpt.tpe) val tagType = List.iterate(componentType, level)(tpe => appliedType(ArrayClass.asType, List(tpe))).last val newArrayApp = atPos(tree.pos) { - val tag = resolveArrayTag(tree.pos, tagType) - if (tag.isEmpty) MissingArrayTagError(tree, tagType) + val tag = resolveClassTag(tree.pos, tagType) + if (tag.isEmpty) MissingClassTagError(tree, tagType) else new ApplyToImplicitArgs(Select(tag, nme.newArray), args) } typed(newArrayApp, mode, pt) diff --git a/src/compiler/scala/tools/reflect/FastTrack.scala b/src/compiler/scala/tools/reflect/FastTrack.scala index 534f6de682..2706087faa 100644 --- a/src/compiler/scala/tools/reflect/FastTrack.scala +++ b/src/compiler/scala/tools/reflect/FastTrack.scala @@ -36,7 +36,6 @@ trait FastTrack { lazy val fastTrack: Map[Symbol, FastTrackEntry] = { var registry = Map[Symbol, FastTrackEntry]() implicit class BindTo(sym: Symbol) { def bindTo(expander: FastTrackExpander): Unit = if (sym != NoSymbol) registry += sym -> FastTrackEntry(sym, expander) } - MacroInternal_materializeArrayTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeArrayTag(u, tt.tpe) } MacroInternal_materializeClassTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeClassTag(u, tt.tpe) } MacroInternal_materializeTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, EmptyTree, tt.tpe, concrete = false) } MacroInternal_materializeConcreteTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, EmptyTree, tt.tpe, concrete = true) } |