summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2012-07-03 00:40:13 -0700
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-07-03 00:40:13 -0700
commitbc2e6fe8bf20b2aa985ea78a2c610ac33497da38 (patch)
tree5c8fd6a4121994ce6a62addf9566e13aa4e7e9f1 /src/compiler
parent035224a17def57b25f7a8ed69d050451b8e7103d (diff)
parent96dd73146f4317feeb59a242d692977f87c5211d (diff)
downloadscala-bc2e6fe8bf20b2aa985ea78a2c610ac33497da38.tar.gz
scala-bc2e6fe8bf20b2aa985ea78a2c610ac33497da38.tar.bz2
scala-bc2e6fe8bf20b2aa985ea78a2c610ac33497da38.zip
Merge pull request #810 from scalamacros/pullrequest/manifests-and-ticket6005
two pullrequests from this morning, combined to merge changes to starrs
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/reflect/makro/runtime/ExprUtils.scala2
-rw-r--r--src/compiler/scala/reflect/reify/Taggers.scala27
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenSymbols.scala6
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenTrees.scala10
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenTypes.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala94
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala5
-rw-r--r--src/compiler/scala/tools/reflect/StdTags.scala9
-rw-r--r--src/compiler/scala/tools/reflect/ToolBoxFactory.scala2
10 files changed, 97 insertions, 75 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