summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-04-22 18:49:09 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-04-23 17:55:26 +0200
commitf54e5c8bbdd719b5c9375c64c2f66b841984456e (patch)
tree975475778e6102c8f2dbbff0f25a2f114204cbbb /src/compiler/scala/tools/nsc/typechecker/Implicits.scala
parent0f0144c74088e396fc1440166bed5a7c6d5f44f4 (diff)
downloadscala-f54e5c8bbdd719b5c9375c64c2f66b841984456e.tar.gz
scala-f54e5c8bbdd719b5c9375c64c2f66b841984456e.tar.bz2
scala-f54e5c8bbdd719b5c9375c64c2f66b841984456e.zip
resurrects manifests in their pre-2.10 glory
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Implicits.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala107
1 files changed, 106 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 3f4e941ec6..fadb691cb6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -1129,7 +1129,10 @@ trait Implicits {
ConcreteTypeTagClass -> MacroInternal_materializeConcreteTypeTag
)
- def tagOfType(pre: Type, tp: Type, tagClass: Symbol): SearchResult = {
+ /** Creates a tree will produce a tag of the requested flavor.
+ * An EmptyTree is returned if materialization fails.
+ */
+ private def tagOfType(pre: Type, tp: Type, tagClass: Symbol): SearchResult = {
def success(arg: Tree) =
try {
val tree1 = typed(atPos(pos.focus)(arg))
@@ -1171,9 +1174,111 @@ trait Implicits {
else failure(materializer, "macros are disabled")
}
+ private val ManifestSymbols = Set[Symbol](PartialManifestClass, FullManifestClass, OptManifestClass)
+
+ /** Creates a tree that calls the relevant factory method in object
+ * 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 = {
+
+ /** Creates a tree that calls the factory method called constructor in object reflect.Manifest */
+ def manifestFactoryCall(constructor: String, tparg: Type, args: Tree*): Tree =
+ if (args contains EmptyTree) EmptyTree
+ else typedPos(tree.pos.focus) {
+ val mani = gen.mkManifestFactoryCall(full, constructor, tparg, args.toList)
+ if (settings.debug.value) println("generated manifest: "+mani) // DEBUG
+ mani
+ }
+
+ /** Creates a tree representing one of the singleton manifests.*/
+ def findSingletonManifest(name: String) = typedPos(tree.pos.focus) {
+ Select(gen.mkAttributedRef(FullManifestModule), name)
+ }
+
+ /** Re-wraps a type in a manifest before calling inferImplicit on the result */
+ def findManifest(tp: Type, manifestClass: Symbol = if (full) FullManifestClass else PartialManifestClass) =
+ inferImplicit(tree, appliedType(manifestClass, tp), true, false, context).tree
+
+ def findSubManifest(tp: Type) = findManifest(tp, if (full) FullManifestClass else OptManifestClass)
+ def mot(tp0: Type, from: List[Symbol], to: List[Type]): SearchResult = {
+ implicit def wrapResult(tree: Tree): SearchResult =
+ if (tree == EmptyTree) SearchFailure else new SearchResult(tree, if (from.isEmpty) EmptyTreeTypeSubstituter else new TreeTypeSubstituter(from, to))
+
+ val tp1 = tp0.normalize
+ tp1 match {
+ case ThisType(_) | SingleType(_, _) =>
+ // can't generate a reference to a value that's abstracted over by an existential
+ if (containsExistential(tp1)) EmptyTree
+ else manifestFactoryCall("singleType", tp, gen.mkAttributedQualifier(tp1))
+ case ConstantType(value) =>
+ manifestOfType(tp1.deconst, full)
+ case TypeRef(pre, sym, args) =>
+ if (isPrimitiveValueClass(sym) || isPhantomClass(sym)) {
+ findSingletonManifest(sym.name.toString)
+ } else if (sym == ObjectClass || sym == AnyRefClass) {
+ findSingletonManifest("Object")
+ } else if (sym == RepeatedParamClass || sym == ByNameParamClass) {
+ EmptyTree
+ } else if (sym == ArrayClass && args.length == 1) {
+ manifestFactoryCall("arrayType", args.head, findManifest(args.head))
+ } else if (sym.isClass) {
+ val classarg0 = gen.mkClassOf(tp1)
+ val classarg = tp match {
+ case _: ExistentialType => gen.mkCast(classarg0, ClassType(tp))
+ case _ => classarg0
+ }
+ val suffix = classarg :: (args map findSubManifest)
+ manifestFactoryCall(
+ "classType", tp,
+ (if ((pre eq NoPrefix) || pre.typeSymbol.isStaticOwner) suffix
+ else findSubManifest(pre) :: suffix): _*)
+ } else if (sym.isExistentiallyBound && full) {
+ manifestFactoryCall("wildcardType", tp,
+ findManifest(tp.bounds.lo), findManifest(tp.bounds.hi))
+ }
+ // looking for a manifest of a type parameter that hasn't been inferred by now,
+ // can't do much, but let's not fail
+ else if (undetParams contains sym) {
+ // #3859: need to include the mapping from sym -> NothingClass.tpe in the SearchResult
+ mot(NothingClass.tpe, sym :: from, NothingClass.tpe :: to)
+ } else {
+ // a manifest should have been found by normal searchImplicit
+ EmptyTree
+ }
+ case RefinedType(parents, decls) => // !!! not yet: if !full || decls.isEmpty =>
+ // refinement is not generated yet
+ if (hasLength(parents, 1)) findManifest(parents.head)
+ else if (full) manifestFactoryCall("intersectionType", tp, parents map findSubManifest: _*)
+ else mot(erasure.intersectionDominator(parents), from, to)
+ case ExistentialType(tparams, result) =>
+ 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)
+*/
+ }
+ }
+
+ mot(tp, Nil, Nil)
+ }
+
+ 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.
*/
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 =>