diff options
40 files changed, 669 insertions, 593 deletions
diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala index ab5e19fca9..596d400628 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/compiler/scala/reflect/internal/Importers.scala @@ -71,9 +71,9 @@ trait Importers { self: SymbolTable => case x: from.ModuleSymbol => linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, importSymbol) case x: from.FreeTerm => - newFreeTerm(importName(x.name).toTermName, importType(x.info), x.value, x.origin, myflags) + newFreeTermSymbol(importName(x.name).toTermName, importType(x.info), x.value, x.flags, x.origin) case x: from.FreeType => - newFreeType(importName(x.name).toTypeName, importType(x.info), x.value, x.origin, myflags) + newFreeTypeSymbol(importName(x.name).toTypeName, importType(x.info), x.value, x.flags, x.origin) case x: from.TermSymbol => linkReferenced(myowner.newValue(myname, mypos, myflags), x, importSymbol) case x: from.TypeSkolem => diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index bf468affe6..c5fe1ecb45 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -291,11 +291,14 @@ trait StdNames extends NameManglers { self: SymbolTable => val AnnotationInfo: NameType = "AnnotationInfo" val Any: NameType = "Any" val AnyVal: NameType = "AnyVal" + val AppliedTypeTree: NameType = "AppliedTypeTree" val Apply: NameType = "Apply" val ArrayAnnotArg: NameType = "ArrayAnnotArg" + val Constant: NameType = "Constant" val ConstantType: NameType = "ConstantType" val EmptyPackage: NameType = "EmptyPackage" val EmptyPackageClass: NameType = "EmptyPackageClass" + val ExistentialTypeTree: NameType = "ExistentialTypeTree" val Expr: NameType = "Expr" val Ident: NameType = "Ident" val Import: NameType = "Import" @@ -404,13 +407,15 @@ trait StdNames extends NameManglers { self: SymbolTable => val name: NameType = "name" val ne: NameType = "ne" val newArray: NameType = "newArray" + val newFreeExistential: NameType = "newFreeExistential" val newFreeTerm: NameType = "newFreeTerm" val newFreeType: NameType = "newFreeType" val newNestedSymbol: NameType = "newNestedSymbol" val newScopeWith: NameType = "newScopeWith" + val next: NameType = "next" val nmeNewTermName: NameType = "newTermName" val nmeNewTypeName: NameType = "newTypeName" - val next: NameType = "next" + val normalize: NameType = "normalize" val notifyAll_ : NameType = "notifyAll" val notify_ : NameType = "notify" val null_ : NameType = "null" @@ -465,6 +470,7 @@ trait StdNames extends NameManglers { self: SymbolTable => val view_ : NameType = "view" val wait_ : NameType = "wait" val withFilter: NameType = "withFilter" + val wrap: NameType = "wrap" val zip: NameType = "zip" val synthSwitch: NameType = "$synthSwitch" diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index 6eaae7f1ee..74e924add4 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -47,13 +47,13 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Create a new free term. Its owner is NoSymbol. */ - def newFreeTerm(name: TermName, info: Type, value: => Any, origin: String, newFlags: Long = 0L): FreeTerm = - new FreeTerm(name, value, origin) initFlags newFlags setInfo info + def newFreeTermSymbol(name: TermName, info: Type, value: => Any, flags: Long = 0L, origin: String): FreeTerm = + new FreeTerm(name, value, origin) initFlags flags setInfo info /** Create a new free type. Its owner is NoSymbol. */ - def newFreeType(name: TypeName, info: Type, value: => Any, origin: String, newFlags: Long = 0L): FreeType = - new FreeType(name, value, origin) initFlags newFlags setInfo info + def newFreeTypeSymbol(name: TypeName, info: Type, value: => Any, flags: Long = 0L, origin: String): FreeType = + new FreeType(name, value, origin) initFlags flags setInfo info /** The original owner of a class. Used by the backend to generate * EnclosingMethod attributes. diff --git a/src/compiler/scala/reflect/internal/TreeBuildUtil.scala b/src/compiler/scala/reflect/internal/TreeBuildUtil.scala index fbcd5043bc..d4d4652e91 100644 --- a/src/compiler/scala/reflect/internal/TreeBuildUtil.scala +++ b/src/compiler/scala/reflect/internal/TreeBuildUtil.scala @@ -1,6 +1,8 @@ package scala.reflect package internal +import Flags._ + trait TreeBuildUtil extends api.TreeBuildUtil { self: SymbolTable => // ``staticClass'' and ``staticModule'' rely on ClassLoaders @@ -51,9 +53,11 @@ trait TreeBuildUtil extends api.TreeBuildUtil { self: SymbolTable => try selectOverloadedMethod(owner, name, index) catch { case _: MissingRequirementError => NoSymbol } - def newFreeTerm(name: String, info: Type, value: => Any, origin: String) = newFreeTerm(newTermName(name), info, value, origin) + def newFreeTerm(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null) = newFreeTermSymbol(newTermName(name), info, value, flags, origin) + + def newFreeType(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null) = newFreeTypeSymbol(newTypeName(name), info, value, (if (flags == 0L) PARAM else flags) | DEFERRED, origin) - def newFreeType(name: String, info: Type, value: => Any, origin: String) = newFreeType(newTypeName(name), info, value, origin) + def newFreeExistential(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null) = newFreeTypeSymbol(newTypeName(name), info, value, (if (flags == 0L) EXISTENTIAL else flags) | DEFERRED, origin) def modifiersFromInternalFlags(flags: Long, privateWithin: Name, annotations: List[Tree]): Modifiers = Modifiers(flags, privateWithin, annotations) diff --git a/src/compiler/scala/reflect/internal/TreeInfo.scala b/src/compiler/scala/reflect/internal/TreeInfo.scala index 039c8e557a..937b3ea5d6 100644 --- a/src/compiler/scala/reflect/internal/TreeInfo.scala +++ b/src/compiler/scala/reflect/internal/TreeInfo.scala @@ -629,7 +629,7 @@ abstract class TreeInfo { object ReifiedType { def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match { - case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(_, List(tpe))) if mrDef.name == nme.MIRROR_SHORT => + case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(_, tpe :: _)) if mrDef.name == nme.MIRROR_SHORT => Some(reifee, symbolTable, tpe) case _ => None @@ -646,11 +646,11 @@ abstract class TreeInfo { } object FreeDef { - def unapply(tree: Tree): Option[(Tree, TermName, Tree, String)] = tree match { - case FreeTermDef(mrRef, name, binding, origin) => - Some(mrRef, name, binding, origin) - case FreeTypeDef(mrRef, name, binding, origin) => - Some(mrRef, name, binding, origin) + def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match { + case FreeTermDef(mrRef, name, binding, flags, origin) => + Some(mrRef, name, binding, flags, origin) + case FreeTypeDef(mrRef, name, binding, flags, origin) => + Some(mrRef, name, binding, flags, origin) case _ => None } @@ -659,28 +659,29 @@ abstract class TreeInfo { object FreeTermDef { lazy val newFreeTermMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeTerm) - def unapply(tree: Tree): Option[(Tree, TermName, Tree, String)] = tree match { - case ValDef(_, name, _, Apply(Select(mrRef @ Ident(_), newFreeTerm), List(_, _, binding, Literal(Constant(origin: String))))) + def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match { + case ValDef(_, name, _, Apply(Select(mrRef @ Ident(_), newFreeTerm), List(_, _, binding, Literal(Constant(flags: Long)), Literal(Constant(origin: String))))) if mrRef.name == nme.MIRROR_SHORT && newFreeTerm == newFreeTermMethod.name => - Some(mrRef, name, binding, origin) + Some(mrRef, name, binding, flags, origin) case _ => None } } object FreeTypeDef { - lazy val newFreeTypeMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeType) + lazy val newFreeExistentialMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeType) + lazy val newFreeTypeMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeExistential) - def unapply(tree: Tree): Option[(Tree, TermName, Tree, String)] = tree match { - case ValDef(_, name, _, Apply(Select(mrRef1 @ Ident(_), newFreeType), List(_, _, value, Literal(Constant(origin: String))))) - if mrRef1.name == nme.MIRROR_SHORT && newFreeType == newFreeTypeMethod.name => + def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match { + case ValDef(_, name, _, Apply(Select(mrRef1 @ Ident(_), newFreeType), List(_, _, value, Literal(Constant(flags: Long)), Literal(Constant(origin: String))))) + if mrRef1.name == nme.MIRROR_SHORT && (newFreeType == newFreeTypeMethod.name || newFreeType == newFreeExistentialMethod.name) => value match { case Apply(TypeApply(Select(Select(mrRef2 @ Ident(_), typeTag), apply), List(binding)), List(Literal(Constant(null)))) if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag && apply == nme.apply => - Some(mrRef1, name, binding, origin) + Some(mrRef1, name, binding, flags, origin) case Apply(TypeApply(Select(mrRef2 @ Ident(_), typeTag), List(binding)), List(Literal(Constant(null)))) if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag => - Some(mrRef1, name, binding, origin) + Some(mrRef1, name, binding, flags, origin) case _ => throw new Error("unsupported free type def: " + showRaw(tree)) } diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index fc57a130d1..7115cafc33 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -277,7 +277,7 @@ trait Types extends api.Types { self: SymbolTable => case SuperType(_, _) => false case SingleType(pre, sym) => notConcreteSym(sym) case ConstantType(_) => false - case TypeRef(_, sym, _) => notConcreteSym(sym) + case TypeRef(_, sym, args) => notConcreteSym(sym) || (args exists (arg => notConcreteTpe(arg))) case RefinedType(_, _) => false case ExistentialType(_, _) => false case AnnotatedType(_, tp, _) => notConcreteTpe(tp) diff --git a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala index 2488b06d6c..3586adc590 100644 --- a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala +++ b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala @@ -10,6 +10,7 @@ trait Reifiers { self: Context => import mirror._ + import definitions._ lazy val reflectMirrorPrefix: Tree = { // [Eugene] how do I typecheck this without undergoing this tiresome (and, in general, incorrect) procedure? @@ -24,6 +25,44 @@ trait Reifiers { def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, requireConcreteTypeTag: Boolean = false): Tree = reifyTopLevel(prefix, tpe, dontSpliceAtTopLevel, requireConcreteTypeTag) + def reifyErasure(tpe: Type): Tree = { + val positionBearer = enclosingMacros.find(c => c.macroApplication.pos != NoPosition).map(_.macroApplication).getOrElse(EmptyTree).asInstanceOf[Tree] + val typetagInScope = callsiteTyper.context.withMacrosDisabled(callsiteTyper.resolveTypeTag(positionBearer, gen.mkAttributedRef(Reflect_mirror).tpe, tpe, full = true)) + def typetagIsSynthetic(tree: Tree) = tree.isInstanceOf[Block] || (tree exists (sub => sub.symbol == TypeTagModule || sub.symbol == ConcreteTypeTagModule)) + typetagInScope match { + case success if !success.isEmpty && !typetagIsSynthetic(success) => + val factory = TypeApply(Select(Ident(ClassTagModule), nme.apply), List(TypeTree(tpe))) + Apply(factory, List(typetagInScope)) + case _ => + if (tpe.typeSymbol == ArrayClass) { + val componentTpe = tpe.typeArguments(0) + val componentTag = callsiteTyper.resolveClassTag(positionBearer, componentTpe) + Select(componentTag, nme.wrap) + } else { + // [Eugene] what's the intended behavior? there's no spec on ClassManifests + // for example, should we ban Array[T] or should we tag them with Array[AnyRef]? + // if its the latter, what should be the result of tagging Array[T] where T <: Int? + if (tpe.isSpliceable) throw new ReificationError(enclosingPosition, "tpe %s is an unresolved spliceable type".format(tpe)) + // [Eugene] imho this logic should be moved into `erasure` + var erasure = tpe match { + case tpe if tpe.typeSymbol.isDerivedValueClass => tpe // [Eugene to Martin] is this correct? + case ConstantType(value) => tpe.widen.erasure + case _ => { + // [Eugene] magikz. needs review + var result = tpe.erasure.normalize // necessary to deal with erasures of HK types, typeConstructor won't work + result = result match { + case PolyType(undets, underlying) => existentialAbstraction(undets, underlying) // we don't want undets in the result + case _ => result + } + result + } + } + val factory = TypeApply(Select(Ident(ClassTagModule), nme.apply), List(TypeTree(tpe))) + Apply(factory, List(TypeApply(Select(Ident(PredefModule), nme.classOf), List(TypeTree(erasure))))) + } + } + } + def unreifyTree(tree: Tree): Tree = Select(tree, definitions.ExprEval) @@ -34,7 +73,7 @@ trait Reifiers { try { val result = reifier.reified - logFreeVars(expandee.pos, result) + logFreeVars(enclosingPosition, result) result } catch { case ex: reifier.ReificationError => diff --git a/src/compiler/scala/reflect/makro/runtime/Typers.scala b/src/compiler/scala/reflect/makro/runtime/Typers.scala index 38e819746d..b32d4fb7b1 100644 --- a/src/compiler/scala/reflect/makro/runtime/Typers.scala +++ b/src/compiler/scala/reflect/makro/runtime/Typers.scala @@ -34,9 +34,9 @@ trait Typers { def trace(msg: Any) = if (mirror.settings.Ymacrodebug.value) println(msg) trace("inferring implicit value of type %s, macros = %s".format(pt, !withMacrosDisabled)) import mirror.analyzer.SearchResult - val wrapper1 = if (!withMacrosDisabled) (callsiteTyper.context.withMacrosEnabled[SearchResult] _) else (callsiteTyper.context.withMacrosDisabled[SearchResult] _) - def wrapper (inference: => SearchResult) = wrapper1(inference) val context = callsiteTyper.context.makeImplicit(true) + val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _) + def wrapper (inference: => SearchResult) = wrapper1(inference) wrapper(mirror.analyzer.inferImplicit(mirror.EmptyTree, pt, true, false, context, !silent, pos)) match { case failure if failure.tree.isEmpty => trace("implicit search has failed. to find out the reason, turn on -Xlog-implicits") @@ -51,11 +51,11 @@ trait Typers { def trace(msg: Any) = if (mirror.settings.Ymacrodebug.value) println(msg) trace("inferring implicit view from %s to %s for %s, macros = %s, reportAmbiguous = %s".format(from, to, tree, !withMacrosDisabled, reportAmbiguous)) import mirror.analyzer.SearchResult - val wrapper1 = if (!withMacrosDisabled) (callsiteTyper.context.withMacrosEnabled[SearchResult] _) else (callsiteTyper.context.withMacrosDisabled[SearchResult] _) + val context = callsiteTyper.context.makeImplicit(reportAmbiguous) + val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _) def wrapper (inference: => SearchResult) = wrapper1(inference) val fun1 = mirror.definitions.FunctionClass(1) val viewTpe = mirror.TypeRef(fun1.typeConstructor.prefix, fun1, List(from, to)) - val context = callsiteTyper.context.makeImplicit(reportAmbiguous) wrapper(mirror.analyzer.inferImplicit(mirror.EmptyTree, viewTpe, reportAmbiguous, true, context, !silent, pos)) match { case failure if failure.tree.isEmpty => trace("implicit search has failed. to find out the reason, turn on -Xlog-implicits") diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala index 16c26734b2..c89ebf0d39 100644 --- a/src/compiler/scala/reflect/reify/Reifier.scala +++ b/src/compiler/scala/reflect/reify/Reifier.scala @@ -47,6 +47,15 @@ abstract class Reifier extends Phases if (prefix exists (_.isErroneous)) CannotReifyErroneousPrefix(prefix) if (prefix.tpe == null) CannotReifyUntypedPrefix(prefix) + def reifyErasure(tpe: Type): Tree = { + val result = typer.resolveClassTag(positionBearer, tpe) + if (result == EmptyTree) throw new Error("cannot reify erasure for %s: ".format(tpe)) + result match { + case Apply(TypeApply(Select(_, _), _), List(clazz)) => clazz + case _ => Select(result, nme.erasure) + } + } + val rtree = reifee match { case tree: Tree => reifyTrace("reifying = ")(if (opt.showTrees) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString) @@ -73,11 +82,11 @@ abstract class Reifier extends Phases CannotReifyReifeeThatHasTypeLocalToReifee(tree) val manifestedType = typer.packedType(tree, NoSymbol) - val manifestedRtype = reifyType(manifestedType) val tagModule = if (definitelyConcrete) ConcreteTypeTagModule else TypeTagModule - var typeTagCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(manifestedType))) - var exprCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), ExprModule.name), List(TypeTree(manifestedType))) - Apply(Apply(exprCtor, List(rtree)), List(Apply(typeTagCtor, List(manifestedRtype)))) + val tagCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(manifestedType))) + val exprCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), ExprModule.name), List(TypeTree(manifestedType))) + val tagArgs = if (definitelyConcrete) List(reify(manifestedType), reifyErasure(manifestedType)) else List(reify(manifestedType)) + Apply(Apply(exprCtor, List(rtree)), List(Apply(tagCtor, tagArgs))) case tpe: Type => reifyTrace("reifying = ")(tpe.toString) @@ -85,9 +94,10 @@ abstract class Reifier extends Phases val rtree = reify(tpe) val manifestedType = tpe - var tagModule = if (definitelyConcrete) ConcreteTypeTagModule else TypeTagModule - var ctor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(manifestedType))) - Apply(ctor, List(rtree)) + val tagModule = if (definitelyConcrete) ConcreteTypeTagModule else TypeTagModule + val ctor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(manifestedType))) + val args = if (definitelyConcrete) List(rtree, reifyErasure(manifestedType)) else List(rtree) + Apply(ctor, args) case _ => throw new Error("reifee %s of type %s is not supported".format(reifee, if (reifee == null) "null" else reifee.getClass.toString)) @@ -126,7 +136,7 @@ abstract class Reifier extends Phases // 3) local freeterm inlining in Metalevels // 4) trivial tree splice inlining in Reify (Trees.scala) // 5) trivial type splice inlining in Reify (Types.scala) - val freevarBindings = symbolTable collect { case freedef @ FreeDef(_, _, binding, _) => binding.symbol } toSet + val freevarBindings = symbolTable collect { case entry @ FreeDef(_, _, binding, _, _) => binding.symbol } toSet val untyped = resetAllAttrs(wrapped, leaveAlone = { case ValDef(_, mr, _, _) if mr == nme.MIRROR_SHORT => true case tree if freevarBindings contains tree.symbol => true diff --git a/src/compiler/scala/reflect/reify/codegen/Symbols.scala b/src/compiler/scala/reflect/reify/codegen/Symbols.scala index 2fc0002838..0513f99366 100644 --- a/src/compiler/scala/reflect/reify/codegen/Symbols.scala +++ b/src/compiler/scala/reflect/reify/codegen/Symbols.scala @@ -63,9 +63,9 @@ trait Symbols { assert(value.isInstanceOf[Ident], showRaw(value)) val capturedTpe = capturedVariableType(sym) val capturedValue = referenceCapturedVariable(sym) - locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(capturedTpe), capturedValue, reify(origin(sym)))) + locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(capturedTpe), capturedValue, reify(sym.flags), reify(origin(sym)))) } else { - locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(sym.tpe), value, reify(origin(sym)))) + locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(sym.tpe), value, reify(sym.flags), reify(origin(sym)))) } } @@ -77,8 +77,8 @@ trait Symbols { if (reifyDebug) println("Free type: %s (%s)".format(sym, sym.accurateKindString)) var name = newTermName(nme.MIRROR_FREE_PREFIX + sym.name) val phantomTypeTag = Apply(TypeApply(Select(Ident(nme.MIRROR_SHORT), nme.TypeTag), List(value)), List(Literal(Constant(null)))) - // todo. implement info reification for free types: type bounds, HK-arity, whatever else that can be useful - locallyReify(sym, name, mirrorCall(nme.newFreeType, reify(sym.name.toString), reify(sym.info), phantomTypeTag, reify(origin(sym)))) + val flavor = if (sym.isExistential) nme.newFreeExistential else nme.newFreeType + locallyReify(sym, name, mirrorCall(flavor, reify(sym.name.toString), reify(sym.info), phantomTypeTag, reify(sym.flags), reify(origin(sym)))) } def reifySymDef(sym: Symbol): Tree = @@ -169,7 +169,7 @@ trait Symbols { if (sym.annotations.isEmpty) EmptyTree else Apply(Select(locallyReified(sym), nme.setAnnotations), List(reify(sym.annotations))) } else { - val rset = Apply(Select(locallyReified(sym), nme.setTypeSignature), List(reifyType(sym.info))) + val rset = Apply(Select(locallyReified(sym), nme.setTypeSignature), List(reify(sym.info))) if (sym.annotations.isEmpty) rset else Apply(Select(rset, nme.setAnnotations), List(reify(sym.annotations))) } diff --git a/src/compiler/scala/reflect/reify/codegen/Trees.scala b/src/compiler/scala/reflect/reify/codegen/Trees.scala index 5ad53c0009..c9f5fc5b8d 100644 --- a/src/compiler/scala/reflect/reify/codegen/Trees.scala +++ b/src/compiler/scala/reflect/reify/codegen/Trees.scala @@ -7,6 +7,7 @@ trait Trees { import mirror._ import definitions._ import treeInfo._ + import scala.reflect.api.Modifier // unfortunately, these are necessary to reify AnnotatedTypes // I'd gladly got rid of them, but I don't fancy making a metaprogramming API that doesn't work with annotated types @@ -46,7 +47,7 @@ trait Trees { reifyMirrorObject(EmptyTree) case mirror.emptyValDef => mirrorSelect(nme.emptyValDef) - case FreeDef(_, _, _, _) => + case FreeDef(_, _, _, _, _) => reifyNestedFreeDef(tree) case FreeRef(_, _) => reifyNestedFreeRef(tree) @@ -57,6 +58,28 @@ trait Trees { case NestedExpr(_, _, _) => reifyNestedExpr(tree) case Literal(const @ Constant(_)) => + // [Eugene] was necessary when we reified erasures as normalized tycons + // now, when we do existentialAbstraction on normalizations, everything works great + // todo. find an explanation +// if (const.tag == ClazzTag) { +//// def preprocess(tpe: Type): Type = tpe.typeSymbol match { +//// case ArrayClass => appliedType(ArrayClass, preprocess(tpe.typeArgs.head)) +//// case _ => tpe.typeConstructor +//// } +//// val tpe = preprocess(const.typeValue) +// val tpe = const.typeValue +// var reified = reify(tpe) +// reified = mirrorCall(nme.Literal, mirrorCall(nme.Constant, reified)) +//// val skolems = ClassClass.typeParams map (_ => newTypeName(typer.context.unit.fresh.newName("_$"))) +//// var existential = mirrorCall(nme.AppliedTypeTree, mirrorCall(nme.TypeTree, reify(ClassClass.typeConstructor)), mkList(skolems map (skolem => mirrorCall(nme.Ident, reify(skolem))))) +//// existential = mirrorCall(nme.ExistentialTypeTree, existential, reify(skolems map (skolem => TypeDef(Modifiers(Set(Modifier.deferred: Modifier)), skolem, Nil, TypeBoundsTree(Ident(NothingClass) setType NothingClass.tpe, Ident(AnyClass) setType AnyClass.tpe))))) +//// reified = mirrorCall(nme.TypeApply, mirrorCall(nme.Select, reified, reify(nme.asInstanceOf_)), mkList(List(existential))) +// // why is this required?? +//// reified = mirrorCall(nme.TypeApply, mirrorCall(nme.Select, reified, reify(nme.asInstanceOf_)), mkList(List(mirrorCall(nme.TypeTree, reify(appliedType(ClassClass.tpe, List(AnyClass.tpe))))))) +// reified +// } else { +// mirrorCall(nme.Literal, reifyProduct(const)) +// } mirrorCall(nme.Literal, reifyProduct(const)) case Import(expr, selectors) => mirrorCall(nme.Import, reify(expr), mkList(selectors map reifyProduct)) @@ -68,11 +91,11 @@ trait Trees { // however, reification of AnnotatedTypes is special. see ``reifyType'' to find out why. if (reifyTreeSymbols && tree.hasSymbol) { if (reifyDebug) println("reifying symbol %s for tree %s".format(tree.symbol, tree)) - rtree = Apply(Select(rtree, nme.setSymbol), List(reifySymRef(tree.symbol))) + rtree = Apply(Select(rtree, nme.setSymbol), List(reify(tree.symbol))) } if (reifyTreeTypes && tree.tpe != null) { if (reifyDebug) println("reifying type %s for tree %s".format(tree.tpe, tree)) - rtree = Apply(Select(rtree, nme.setType), List(reifyType(tree.tpe))) + rtree = Apply(Select(rtree, nme.setType), List(reify(tree.tpe))) } rtree @@ -98,7 +121,7 @@ trait Trees { case InlinedTreeSplice(_, inlinedSymbolTable, tree, _) => if (reifyDebug) println("inlining the splicee") // all free vars local to the enclosing reifee should've already been inlined by ``Metalevels'' - inlinedSymbolTable collect { case freedef @ FreeDef(_, _, binding, _) if binding.symbol.isLocalToReifee => assert(false, freedef) } + inlinedSymbolTable collect { case freedef @ FreeDef(_, _, binding, _, _) if binding.symbol.isLocalToReifee => assert(false, freedef) } symbolTable ++= inlinedSymbolTable tree case tree => @@ -172,7 +195,7 @@ trait Trees { val spliced = spliceType(tpe) if (spliced == EmptyTree) { if (reifyDebug) println("splicing failed: reify as is") - mirrorCall(nme.TypeTree, reifyType(tpe)) + mirrorCall(nme.TypeTree, reify(tpe)) } else { spliced match { case TypeRefToFreeType(freeType) => @@ -189,7 +212,7 @@ trait Trees { mirrorCall(nme.Ident, reify(sym)) } else { if (reifyDebug) println("tpe is an alias, but not a locatable: reify as TypeTree(%s)".format(tpe)) - mirrorCall(nme.TypeTree, reifyType(tpe)) + mirrorCall(nme.TypeTree, reify(tpe)) } } } diff --git a/src/compiler/scala/reflect/reify/codegen/Types.scala b/src/compiler/scala/reflect/reify/codegen/Types.scala index 948728088e..e2a2a69828 100644 --- a/src/compiler/scala/reflect/reify/codegen/Types.scala +++ b/src/compiler/scala/reflect/reify/codegen/Types.scala @@ -65,8 +65,16 @@ trait Types { private var spliceTypesEnabled = !dontSpliceAtTopLevel /** Keeps track of whether this reification contains abstract type parameters */ - var maybeConcrete = true - var definitelyConcrete = true + private var _definitelyConcrete = true + def definitelyConcrete = _definitelyConcrete + def definitelyConcrete_=(value: Boolean) { + _definitelyConcrete = value + if (!value && requireConcreteTypeTag) { + assert(current.isInstanceOf[Type], current) + val offender = current.asInstanceOf[Type] + CannotReifyConcreteTypeTagHavingUnresolvedTypeParameters(offender) + } + } private type SpliceCacheKey = (Symbol, Symbol) private lazy val spliceCache: collection.mutable.Map[SpliceCacheKey, Tree] = { @@ -75,7 +83,9 @@ trait Types { } def spliceType(tpe: Type): Tree = { - if (tpe.isSpliceable) { + // [Eugene] it seems that depending on the context the very same symbol can be either a spliceable tparam or a quantified existential. very weird! + val quantified = currents collect { case ExistentialType(quantified, _) => quantified } flatMap identity + if (tpe.isSpliceable && !(quantified contains tpe.typeSymbol)) { if (reifyDebug) println("splicing " + tpe) if (spliceTypesEnabled) { @@ -89,22 +99,18 @@ trait Types { // if this fails, it might produce the dreaded "erroneous or inaccessible type" error // to find out the whereabouts of the error run scalac with -Ydebug if (reifyDebug) println("launching implicit search for %s.%s[%s]".format(prefix, tagClass.name, tpe)) - val positionBearer = mirror.analyzer.openMacros.find(c => c.macroApplication.pos != NoPosition).map(_.macroApplication).getOrElse(EmptyTree).asInstanceOf[Tree] typer.resolveTypeTag(positionBearer, prefix.tpe, tpe, requireConcreteTypeTag) match { case failure if failure.isEmpty => if (reifyDebug) println("implicit search was fruitless") - definitelyConcrete &= false - maybeConcrete &= false EmptyTree case success => if (reifyDebug) println("implicit search has produced a result: " + success) - definitelyConcrete |= requireConcreteTypeTag - maybeConcrete |= true + definitelyConcrete &= requireConcreteTypeTag var splice = Select(success, nme.tpe) splice match { case InlinedTypeSplice(_, inlinedSymbolTable, tpe) => // all free vars local to the enclosing reifee should've already been inlined by ``Metalevels'' - inlinedSymbolTable collect { case freedef @ FreeDef(_, _, binding, _) if binding.symbol.isLocalToReifee => assert(false, freedef) } + inlinedSymbolTable collect { case freedef @ FreeDef(_, _, binding, _, _) if binding.symbol.isLocalToReifee => assert(false, freedef) } symbolTable ++= inlinedSymbolTable reifyTrace("inlined the splicee: ")(tpe) case tpe => @@ -117,8 +123,7 @@ trait Types { if (reifyDebug) println("splicing has been cancelled: spliceTypesEnabled = false") } - if (requireConcreteTypeTag) - CannotReifyConcreteTypeTagHavingUnresolvedTypeParameters(tpe) + definitelyConcrete = false } spliceTypesEnabled = true diff --git a/src/compiler/scala/reflect/reify/codegen/Util.scala b/src/compiler/scala/reflect/reify/codegen/Util.scala index bb369a1adb..8d7cf39ff7 100644 --- a/src/compiler/scala/reflect/reify/codegen/Util.scala +++ b/src/compiler/scala/reflect/reify/codegen/Util.scala @@ -14,6 +14,8 @@ trait Util { object reifiedNodePrinters extends { val global: mirror.type = mirror } with tools.nsc.ast.NodePrinters with NodePrinters val reifiedNodeToString = reifiedNodePrinters.reifiedNodeToString + val positionBearer = mirror.analyzer.openMacros.find(c => c.macroApplication.pos != NoPosition).map(_.macroApplication).getOrElse(EmptyTree).asInstanceOf[Tree] + def reifyList(xs: List[Any]): Tree = mkList(xs map reify) diff --git a/src/compiler/scala/reflect/reify/phases/Metalevels.scala b/src/compiler/scala/reflect/reify/phases/Metalevels.scala index bb0b8ac138..206f3b1118 100644 --- a/src/compiler/scala/reflect/reify/phases/Metalevels.scala +++ b/src/compiler/scala/reflect/reify/phases/Metalevels.scala @@ -115,7 +115,7 @@ trait Metalevels { if (reifyDebug) println("entering inlineable splice: " + splicee) val Block(mrDef :: symbolTable, expr) = splicee // [Eugene] how to express the fact that a scrutinee is both of some type and matches an extractor? - val freedefsToInline = symbolTable collect { case freedef @ FreeTermDef(_, _, binding, _) if binding.symbol.isLocalToReifee => freedef.asInstanceOf[ValDef] } + val freedefsToInline = symbolTable collect { case freedef @ FreeTermDef(_, _, binding, _, _) if binding.symbol.isLocalToReifee => freedef.asInstanceOf[ValDef] } freedefsToInline foreach (vdef => this.freedefsToInline(vdef.name) = vdef) val symbolTable1 = symbolTable diff freedefsToInline val tree1 = Select(Block(mrDef :: symbolTable1, expr), flavor) @@ -138,7 +138,7 @@ trait Metalevels { // some of them need to be rebuilt, some of them need to be removed, because they're no longer necessary case FreeRef(mr, name) if freedefsToInline contains name => if (reifyDebug) println("inlineable free ref: %s in %s".format(name, showRaw(tree))) - val freedef @ FreeDef(_, _, binding, _) = freedefsToInline(name) + val freedef @ FreeDef(_, _, binding, _, _) = freedefsToInline(name) if (reifyDebug) println("related definition: %s".format(showRaw(freedef))) val inlined = reify(binding) if (reifyDebug) println("verdict: inlined as %s".format(showRaw(inlined))) diff --git a/src/compiler/scala/reflect/reify/phases/Reify.scala b/src/compiler/scala/reflect/reify/phases/Reify.scala index 02a96987ed..a1ff486ed7 100644 --- a/src/compiler/scala/reflect/reify/phases/Reify.scala +++ b/src/compiler/scala/reflect/reify/phases/Reify.scala @@ -23,24 +23,33 @@ trait Reify extends Symbols * Reifies any supported value. * For internal use only, use ``reified'' instead. */ - def reify(reifee: Any): Tree = reifee match { - // before adding some case here, in global scope, please, consider - // whether it can be localized like reifyAnnotationInfo or reifyScope - // this will help reification stay as sane as possible - case sym: Symbol => reifySymRef(sym) - case tpe: Type => reifyType(tpe) - case name: Name => reifyName(name) - case tree: Tree => reifyTree(tree) - // disabled because this is a very special case that I plan to remove later - // why do I dislike annotations? see comments to `reifyAnnotationInfo` -// case ann: AnnotationInfo => reifyAnnotationInfo(ann) - case pos: Position => reifyPosition(pos) - case mods: mirror.Modifiers => reifyModifiers(mods) - case xs: List[_] => reifyList(xs) - case s: String => Literal(Constant(s)) - case v if isAnyVal(v) => Literal(Constant(v)) - case null => Literal(Constant(null)) - case _ => - throw new Error("reifee %s of type %s is not supported".format(reifee, reifee.getClass)) + var currents: List[Any] = reifee :: Nil + def current = currents.head + def reify(reifee: Any): Tree = { + currents = reifee :: currents + try { + reifee match { + // before adding some case here, in global scope, please, consider + // whether it can be localized like reifyAnnotationInfo or reifyScope + // this will help reification stay as sane as possible + case sym: Symbol => reifySymRef(sym) + case tpe: Type => reifyType(tpe) + case name: Name => reifyName(name) + case tree: Tree => reifyTree(tree) + // disabled because this is a very special case that I plan to remove later + // why do I dislike annotations? see comments to `reifyAnnotationInfo` +// case ann: AnnotationInfo => reifyAnnotationInfo(ann) + case pos: Position => reifyPosition(pos) + case mods: mirror.Modifiers => reifyModifiers(mods) + case xs: List[_] => reifyList(xs) + case s: String => Literal(Constant(s)) + case v if isAnyVal(v) => Literal(Constant(v)) + case null => Literal(Constant(null)) + case _ => + throw new Error("reifee %s of type %s is not supported".format(reifee, reifee.getClass)) + } + } finally { + currents = currents.tail + } } }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala index e700604612..4ab306a13f 100644 --- a/src/compiler/scala/reflect/reify/phases/Reshape.scala +++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala @@ -78,12 +78,6 @@ trait Reshape { if (reifyDebug) println("unapplying unapply: " + tree) val fun1 = extractExtractor(fun) Apply(fun1, args).copyAttrs(unapply) - case Literal(const @ Constant(tpe: Type)) => - // todo. implement this - ??? - case Literal(const @ Constant(sym: Symbol)) => - // todo. implement this - ??? case _ => tree } diff --git a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala index 6fc5f7ed8a..4048e94d0f 100644 --- a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala @@ -14,11 +14,11 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => override def connectModuleToClass(m: ModuleSymbol, moduleClass: ClassSymbol): ModuleSymbol = synchronized { super.connectModuleToClass(m, moduleClass) } - override def newFreeTerm(name: TermName, info: Type, value: => Any, origin: String = null, newFlags: Long = 0L): FreeTerm = - new FreeTerm(name, value, origin) with SynchronizedTermSymbol initFlags newFlags setInfo info + override def newFreeTermSymbol(name: TermName, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeTerm = + new FreeTerm(name, value, origin) with SynchronizedTermSymbol initFlags flags setInfo info - override def newFreeType(name: TypeName, info: Type, value: => Any, origin: String = null, newFlags: Long = 0L): FreeType = - new FreeType(name, value, origin) with SynchronizedTypeSymbol initFlags newFlags setInfo info + override def newFreeTypeSymbol(name: TypeName, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeType = + new FreeType(name, value, origin) with SynchronizedTypeSymbol initFlags flags setInfo info override protected def makeNoSymbol: NoSymbol = new NoSymbol with SynchronizedSymbol diff --git a/src/compiler/scala/tools/nsc/ast/FreeVars.scala b/src/compiler/scala/tools/nsc/ast/FreeVars.scala index 1bf36e8bf2..a1983d1834 100644 --- a/src/compiler/scala/tools/nsc/ast/FreeVars.scala +++ b/src/compiler/scala/tools/nsc/ast/FreeVars.scala @@ -13,9 +13,9 @@ trait FreeVars extends reflect.internal.FreeVars { self: Global => case Reified(_, symbolTable, _) => // logging free vars only when they are untyped prevents avalanches of duplicate messages symbolTable foreach { - case FreeTermDef(_, _, binding, origin) if settings.logFreeTerms.value && binding.tpe == null => + case FreeTermDef(_, _, binding, _, origin) if settings.logFreeTerms.value && binding.tpe == null => reporter.echo(position, "free term: %s %s".format(showRaw(binding), origin)) - case FreeTypeDef(_, _, binding, origin) if settings.logFreeTypes.value && binding.tpe == null => + case FreeTypeDef(_, _, binding, _, origin) if settings.logFreeTypes.value && binding.tpe == null => reporter.echo(position, "free type: %s %s".format(showRaw(binding), origin)) case _ => // do nothing diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 4fb9362ccc..30a79917c9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1161,7 +1161,8 @@ trait Implicits { // todo. migrate hardcoded materialization in Implicits to corresponding implicit macros var materializer = atPos(pos.focus)(Apply(TypeApply(Ident(TagMaterializers(tagClass)), List(TypeTree(tp))), List(prefix))) if (settings.XlogImplicits.value) println("materializing requested %s.%s[%s] using %s".format(pre, tagClass.name, tp, materializer)) - success(materializer) + if (context.macrosEnabled) success(materializer) + else failure(materializer, "macros are disabled") } /** The manifest corresponding to type `pt`, provided `pt` is an instance of Manifest. diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index 7138837f0d..fe8a16a484 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -117,6 +117,10 @@ object ClassTag { case _ => apply[T](rm.typeToClass(tpe.erasure)) } + def apply[T](ttag: rm.ConcreteTypeTag[T]): ClassTag[T] = + if (ttag.erasure != null) ClassTag[T](ttag.erasure) + else ClassTag[T](ttag.tpe) + implicit def toDeprecatedClassManifestApis[T](ctag: ClassTag[T]): DeprecatedClassManifestApis[T] = new DeprecatedClassManifestApis[T](ctag) } diff --git a/src/library/scala/reflect/DynamicProxy.scala b/src/library/scala/reflect/DynamicProxy.scala index ffd1e7a39f..02872977f5 100644 --- a/src/library/scala/reflect/DynamicProxy.scala +++ b/src/library/scala/reflect/DynamicProxy.scala @@ -2,13 +2,13 @@ package scala.reflect /** * A dynamic proxy which redirects method calls and attribute access to a given * target object at runtime using reflection. - * + * * Usage example: - * + * * object x{ def hello = "hello world" } * val d = new DynamicProxy{ val dynamicProxyTarget = x } * assert( d.hello == "hello world" ) - * + * * Not supported (yet): * - implicit conversions and parameters * - multiple arguments lists @@ -26,7 +26,7 @@ trait DynamicProxy extends Dynamic{ object DynamicReflectBoxed{ implicit def box[@specialized T]( v:T ) = DynamicReflectBoxed( v.getClass, v ) } - + def selectDynamic( method:String ) = { val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method).encodedName ) invoke( dynamicProxyTarget, symbol )() @@ -38,7 +38,7 @@ trait DynamicProxy extends Dynamic{ } def applyDynamic( method:String )( args:DynamicReflectBoxed* ) : Any - = applyDynamicNamed( method )( args.map( value => ("",value) ) :_* ) + = applyDynamicNamed( method )( args.map( value => ("",value) ) :_* ) def applyDynamicNamed( method:String )( args:(String,DynamicReflectBoxed)* ) : Any = { val class_ = dynamicProxyTarget.getClass @@ -48,27 +48,27 @@ trait DynamicProxy extends Dynamic{ if(args.size == 0){ invoke( dynamicProxyTarget, symbol )() } else { - val call = + val call = Apply( Select( TypeApply( Select( Select( - Ident(newFreeTerm("__this", symbolForName("scala.reflect.DynamicProxy").asType, this, null)) + Ident(newFreeTerm("__this", symbolForName("scala.reflect.DynamicProxy").asType, this)) , newTermName("dynamicProxyTarget") - ), + ), newTermName("asInstanceOf") ) , List(TypeTree().setType(classToType(class_))) ) ,newTermName(method).encodedName ) ,args.map{ case(name,box) => - val value = Ident(newFreeTerm("__arg"+({i+=1;i}.toString), classToType(box.class_), box.value, null)) + val value = Ident(newFreeTerm("__arg"+({i+=1;i}.toString), classToType(box.class_), box.value)) if( name == "" ) value else AssignOrNamedArg( Ident(name), value ) }.toList ) toolbox.runExpr( call ) - } + } } } diff --git a/src/library/scala/reflect/TagMaterialization.scala b/src/library/scala/reflect/TagMaterialization.scala index aede00020f..a7237223f1 100644 --- a/src/library/scala/reflect/TagMaterialization.scala +++ b/src/library/scala/reflect/TagMaterialization.scala @@ -65,59 +65,22 @@ object TagMaterialization { val ConcreteTypeTagClass = selectType(TypeTagsClass, "ConcreteTypeTag") val ConcreteTypeTagModule = selectTerm(TypeTagsClass, "ConcreteTypeTag") - def materializeClassTag(tpe: Type): Tree = { - val prefix = gen.mkAttributedRef(Reflect_mirror) setType singleType(Reflect_mirror.owner.thisPrefix, Reflect_mirror) - materializeClassTag(prefix, tpe) - } - - def materializeClassTag(prefix: Tree, tpe: Type): Tree = { - val typetagInScope = c.inferImplicitValue(appliedType(typeRef(prefix.tpe, ConcreteTypeTagClass, Nil), List(tpe))) - def typetagIsSynthetic(tree: Tree) = tree.isInstanceOf[Block] || (tree exists (sub => sub.symbol == TypeTagModule || sub.symbol == ConcreteTypeTagModule)) - typetagInScope match { - case success if !success.isEmpty && !typetagIsSynthetic(success) => - val factory = TypeApply(Select(Ident(ClassTagModule), newTermName("apply")), List(TypeTree(tpe))) - Apply(factory, List(Select(typetagInScope, newTermName("tpe")))) - case _ => - val result = - tpe match { - case coreTpe if coreTags contains coreTpe => - Select(Ident(ClassTagModule), coreTags(coreTpe)) - case _ => - if (tpe.typeSymbol == ArrayClass) { - val componentTpe = tpe.typeArguments(0) - val classtagInScope = c.inferImplicitValue(appliedType(typeRef(NoPrefix, ClassTagClass, Nil), List(componentTpe))) - val componentTag = classtagInScope orElse materializeClassTag(prefix, componentTpe) - Select(componentTag, newTermName("wrap")) - } else { - // [Eugene] what's the intended behavior? there's no spec on ClassManifests - // for example, should we ban Array[T] or should we tag them with Array[AnyRef]? - // if its the latter, what should be the result of tagging Array[T] where T <: Int? - if (tpe.typeSymbol.isAbstractType) fail("tpe is an abstract type") - val erasure = - if (tpe.typeSymbol.isDerivedValueClass) tpe // [Eugene to Martin] is this correct? - else tpe.erasure.normalize // necessary to deal with erasures of HK types - val factory = TypeApply(Select(Ident(ClassTagModule), newTermName("apply")), List(TypeTree(tpe))) - Apply(factory, List(TypeApply(Ident(newTermName("classOf")), List(TypeTree(erasure))))) - } - } - try c.typeCheck(result) - catch { case terr @ c.TypeError(pos, msg) => fail(terr) } - } - } + def materializeClassTag(tpe: Type): Tree = + materializeTag(c.reflectMirrorPrefix, tpe, ClassTagModule, c.reifyErasure(tpe)) def materializeTypeTag(tpe: Type, requireConcreteTypeTag: Boolean): Tree = { def prefix: Tree = ??? // todo. needs to be synthesized from c.prefix - materializeTypeTag(prefix, tpe, requireConcreteTypeTag) + val tagModule = if (requireConcreteTypeTag) ConcreteTypeTagModule else TypeTagModule + materializeTag(prefix, tpe, tagModule, c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, requireConcreteTypeTag = requireConcreteTypeTag)) } - def materializeTypeTag(prefix: Tree, tpe: Type, requireConcreteTypeTag: Boolean): Tree = { - val tagModule = if (requireConcreteTypeTag) ConcreteTypeTagModule else TypeTagModule + private def materializeTag(prefix: Tree, tpe: Type, tagModule: Symbol, materializer: => Tree): Tree = { val result = tpe match { case coreTpe if coreTags contains coreTpe => Select(Select(prefix, tagModule.name), coreTags(coreTpe)) case _ => - try c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, requireConcreteTypeTag = requireConcreteTypeTag) + try materializer catch { case ex: Throwable => // [Eugene] cannot pattern match on an abstract type, so had to do this diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala index e47bc7216e..d9293888d9 100755 --- a/src/library/scala/reflect/api/Symbols.scala +++ b/src/library/scala/reflect/api/Symbols.scala @@ -120,6 +120,11 @@ trait Symbols { self: Universe => */ def isTerm : Boolean + /** Does this symbol represent a package? + * If yes, `isTerm` is also guaranteed to be true. + */ + def isPackage : Boolean + /** Does this symbol represent the definition of method? * If yes, `isTerm` is also guaranteed to be true. */ @@ -146,6 +151,11 @@ trait Symbols { self: Universe => */ def isClass : Boolean + /** Does this symbol represent a package class? + * If yes, `isClass` is also guaranteed to be true. + */ + def isPackageClass : Boolean + /** Does this symbol represent the definition of a primitive class? * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]], * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]? diff --git a/src/library/scala/reflect/api/TreeBuildUtil.scala b/src/library/scala/reflect/api/TreeBuildUtil.scala index 32d7eefa5b..4f510337c2 100644 --- a/src/library/scala/reflect/api/TreeBuildUtil.scala +++ b/src/library/scala/reflect/api/TreeBuildUtil.scala @@ -62,20 +62,34 @@ trait TreeBuildUtil { self: Universe => * @param name the name of the free variable * @param info the type signature of the free variable * @param value the value of the free variable at runtime + * @param flags (optional) flags of the free variable * @param origin debug information that tells where this symbol comes from */ - def newFreeTerm(name: String, info: Type, value: => Any, origin: String): Symbol + def newFreeTerm(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): Symbol - /** Create a fresh free type symbol. + /** Create a fresh free non-existential type symbol. * @param name the name of the free variable * @param info the type signature of the free variable * @param value a type tag that captures the value of the free variable * is completely phantom, since the captured type cannot be propagated to the runtime * if it could be, we wouldn't be creating a free type to begin with * the only usage for it is preserving the captured symbol for compile-time analysis + * @param flags (optional) flags of the free variable * @param origin debug information that tells where this symbol comes from */ - def newFreeType(name: String, info: Type, value: => Any, origin: String): Symbol + def newFreeType(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): Symbol + + /** Create a fresh free existential type symbol. + * @param name the name of the free variable + * @param info the type signature of the free variable + * @param value a type tag that captures the value of the free variable + * is completely phantom, since the captured type cannot be propagated to the runtime + * if it could be, we wouldn't be creating a free type to begin with + * the only usage for it is preserving the captured symbol for compile-time analysis + * @param flags (optional) flags of the free variable + * @param origin (optional) debug information that tells where this symbol comes from + */ + def newFreeExistential(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): Symbol /** Create a Modiiers structure given internal flags, qualifier, annotations */ def modifiersFromInternalFlags(flags: Long, privateWithin: Name, annotations: List[Tree]): Modifiers diff --git a/src/library/scala/reflect/api/TypeTags.scala b/src/library/scala/reflect/api/TypeTags.scala index 59a7c87f44..85755cd2f2 100644 --- a/src/library/scala/reflect/api/TypeTags.scala +++ b/src/library/scala/reflect/api/TypeTags.scala @@ -7,6 +7,7 @@ package scala.reflect package api import scala.reflect.{ mirror => rm } +import java.lang.{ Class => jClass } import language.implicitConversions /** @@ -119,7 +120,7 @@ trait TypeTags { self: Universe => * @see [[scala.reflect.api.TypeTags]] */ @annotation.implicitNotFound(msg = "No ConcreteTypeTag available for ${T}") - class ConcreteTypeTag[T](tpe: Type) extends TypeTag[T](tpe) { + abstract class ConcreteTypeTag[T](tpe: Type, val erasure: jClass[_]) extends TypeTag[T](tpe) { // it's unsafe to use assert here, because we might run into deadlocks with Predef // also see comments in ClassTags.scala //assert(isConcrete, tpe) @@ -128,24 +129,24 @@ trait TypeTags { self: Universe => } object ConcreteTypeTag { - val Byte : ConcreteTypeTag[scala.Byte] = new ConcreteTypeTag[scala.Byte](ByteTpe) { private def readResolve() = ConcreteTypeTag.Byte } - val Short : ConcreteTypeTag[scala.Short] = new ConcreteTypeTag[scala.Short](ShortTpe) { private def readResolve() = ConcreteTypeTag.Short } - val Char : ConcreteTypeTag[scala.Char] = new ConcreteTypeTag[scala.Char](CharTpe) { private def readResolve() = ConcreteTypeTag.Char } - val Int : ConcreteTypeTag[scala.Int] = new ConcreteTypeTag[scala.Int](IntTpe) { private def readResolve() = ConcreteTypeTag.Int } - val Long : ConcreteTypeTag[scala.Long] = new ConcreteTypeTag[scala.Long](LongTpe) { private def readResolve() = ConcreteTypeTag.Long } - val Float : ConcreteTypeTag[scala.Float] = new ConcreteTypeTag[scala.Float](FloatTpe) { private def readResolve() = ConcreteTypeTag.Float } - val Double : ConcreteTypeTag[scala.Double] = new ConcreteTypeTag[scala.Double](DoubleTpe) { private def readResolve() = ConcreteTypeTag.Double } - val Boolean : ConcreteTypeTag[scala.Boolean] = new ConcreteTypeTag[scala.Boolean](BooleanTpe) { private def readResolve() = ConcreteTypeTag.Boolean } - val Unit : ConcreteTypeTag[scala.Unit] = new ConcreteTypeTag[scala.Unit](UnitTpe) { private def readResolve() = ConcreteTypeTag.Unit } - val Any : ConcreteTypeTag[scala.Any] = new ConcreteTypeTag[scala.Any](AnyTpe) { private def readResolve() = ConcreteTypeTag.Any } - val Object : ConcreteTypeTag[java.lang.Object] = new ConcreteTypeTag[java.lang.Object](ObjectTpe) { private def readResolve() = ConcreteTypeTag.Object } - val AnyVal : ConcreteTypeTag[scala.AnyVal] = new ConcreteTypeTag[scala.AnyVal](AnyValTpe) { private def readResolve() = ConcreteTypeTag.AnyVal } - val AnyRef : ConcreteTypeTag[scala.AnyRef] = new ConcreteTypeTag[scala.AnyRef](AnyRefTpe) { private def readResolve() = ConcreteTypeTag.AnyRef } - val Nothing : ConcreteTypeTag[scala.Nothing] = new ConcreteTypeTag[scala.Nothing](NothingTpe) { private def readResolve() = ConcreteTypeTag.Nothing } - val Null : ConcreteTypeTag[scala.Null] = new ConcreteTypeTag[scala.Null](NullTpe) { private def readResolve() = ConcreteTypeTag.Null } - val String : ConcreteTypeTag[java.lang.String] = new ConcreteTypeTag[java.lang.String](StringTpe) { private def readResolve() = ConcreteTypeTag.String } - - def apply[T](tpe: Type): ConcreteTypeTag[T] = + val Byte : ConcreteTypeTag[scala.Byte] = new ConcreteTypeTag[scala.Byte](ByteTpe, ClassTag.Byte.erasure) { private def readResolve() = ConcreteTypeTag.Byte } + val Short : ConcreteTypeTag[scala.Short] = new ConcreteTypeTag[scala.Short](ShortTpe, ClassTag.Short.erasure) { private def readResolve() = ConcreteTypeTag.Short } + val Char : ConcreteTypeTag[scala.Char] = new ConcreteTypeTag[scala.Char](CharTpe, ClassTag.Char.erasure) { private def readResolve() = ConcreteTypeTag.Char } + val Int : ConcreteTypeTag[scala.Int] = new ConcreteTypeTag[scala.Int](IntTpe, ClassTag.Int.erasure) { private def readResolve() = ConcreteTypeTag.Int } + val Long : ConcreteTypeTag[scala.Long] = new ConcreteTypeTag[scala.Long](LongTpe, ClassTag.Long.erasure) { private def readResolve() = ConcreteTypeTag.Long } + val Float : ConcreteTypeTag[scala.Float] = new ConcreteTypeTag[scala.Float](FloatTpe, ClassTag.Float.erasure) { private def readResolve() = ConcreteTypeTag.Float } + val Double : ConcreteTypeTag[scala.Double] = new ConcreteTypeTag[scala.Double](DoubleTpe, ClassTag.Double.erasure) { private def readResolve() = ConcreteTypeTag.Double } + val Boolean : ConcreteTypeTag[scala.Boolean] = new ConcreteTypeTag[scala.Boolean](BooleanTpe, ClassTag.Boolean.erasure) { private def readResolve() = ConcreteTypeTag.Boolean } + val Unit : ConcreteTypeTag[scala.Unit] = new ConcreteTypeTag[scala.Unit](UnitTpe, ClassTag.Unit.erasure) { private def readResolve() = ConcreteTypeTag.Unit } + val Any : ConcreteTypeTag[scala.Any] = new ConcreteTypeTag[scala.Any](AnyTpe, ClassTag.Any.erasure) { private def readResolve() = ConcreteTypeTag.Any } + val Object : ConcreteTypeTag[java.lang.Object] = new ConcreteTypeTag[java.lang.Object](ObjectTpe, ClassTag.Object.erasure) { private def readResolve() = ConcreteTypeTag.Object } + val AnyVal : ConcreteTypeTag[scala.AnyVal] = new ConcreteTypeTag[scala.AnyVal](AnyValTpe, ClassTag.AnyVal.erasure) { private def readResolve() = ConcreteTypeTag.AnyVal } + val AnyRef : ConcreteTypeTag[scala.AnyRef] = new ConcreteTypeTag[scala.AnyRef](AnyRefTpe, ClassTag.AnyRef.erasure) { private def readResolve() = ConcreteTypeTag.AnyRef } + val Nothing : ConcreteTypeTag[scala.Nothing] = new ConcreteTypeTag[scala.Nothing](NothingTpe, ClassTag.Nothing.erasure) { private def readResolve() = ConcreteTypeTag.Nothing } + val Null : ConcreteTypeTag[scala.Null] = new ConcreteTypeTag[scala.Null](NullTpe, ClassTag.Null.erasure) { private def readResolve() = ConcreteTypeTag.Null } + val String : ConcreteTypeTag[java.lang.String] = new ConcreteTypeTag[java.lang.String](StringTpe, ClassTag.String.erasure) { private def readResolve() = ConcreteTypeTag.String } + + def apply[T](tpe: Type, erasure: jClass[_] = null): ConcreteTypeTag[T] = tpe match { case ByteTpe => ConcreteTypeTag.Byte.asInstanceOf[ConcreteTypeTag[T]] case ShortTpe => ConcreteTypeTag.Short.asInstanceOf[ConcreteTypeTag[T]] @@ -163,12 +164,12 @@ trait TypeTags { self: Universe => case NothingTpe => ConcreteTypeTag.Nothing.asInstanceOf[ConcreteTypeTag[T]] case NullTpe => ConcreteTypeTag.Null.asInstanceOf[ConcreteTypeTag[T]] case StringTpe => ConcreteTypeTag.String.asInstanceOf[ConcreteTypeTag[T]] - case _ => new ConcreteTypeTag[T](tpe) {} + case _ => new ConcreteTypeTag[T](tpe, erasure) {} } def unapply[T](ttag: TypeTag[T]): Option[Type] = if (ttag.isConcrete) Some(ttag.tpe) else None - implicit def toClassTag[T](ttag: rm.ConcreteTypeTag[T]): ClassTag[T] = ClassTag[T](rm.typeToClass(ttag.tpe.erasure)) + implicit def toClassTag[T](ttag: rm.ConcreteTypeTag[T]): ClassTag[T] = ClassTag[T](ttag) implicit def toDeprecatedManifestApis[T](ttag: rm.ConcreteTypeTag[T]): DeprecatedManifestApis[T] = new DeprecatedManifestApis[T](ttag) diff --git a/src/library/scala/reflect/api/Types.scala b/src/library/scala/reflect/api/Types.scala index 5e1c1af2fe..4cb5609166 100755 --- a/src/library/scala/reflect/api/Types.scala +++ b/src/library/scala/reflect/api/Types.scala @@ -53,14 +53,26 @@ trait Types { self: Universe => */ def typeArguments: List[Type] + /** For a (potentially wrapped) poly type, its type parameters, + * the empty list for all other types */ + def typeParams: List[Symbol] + /** Is this type a type constructor that is missing its type arguments? */ def isHigherKinded: Boolean // !!! This should be called "isTypeConstructor", no? - /** Does this type refer to abstract types or is an abstract type? + /** Returns the corresponding type constructor (e.g. List for List[T] or List[String]) + */ + def typeConstructor: Type + + /** Does this type refer to spliceable types or is a spliceable type? */ def isConcrete: Boolean + /** Is this type an abstract type that needs to be resolved? + */ + def isSpliceable: Boolean + /** * Expands type aliases and converts higher-kinded TypeRefs to PolyTypes. * Functions on types are also implemented as PolyTypes. diff --git a/src/library/scala/reflect/makro/Reifiers.scala b/src/library/scala/reflect/makro/Reifiers.scala index d690df6aee..b9e82e0387 100644 --- a/src/library/scala/reflect/makro/Reifiers.scala +++ b/src/library/scala/reflect/makro/Reifiers.scala @@ -48,6 +48,10 @@ trait Reifiers { */ def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, requireConcreteTypeTag: Boolean = false): Tree + /** Given a type, generate a tree that when compiled and executed produces the erasure of the original type. + */ + def reifyErasure(tpe: Type): Tree + /** Undoes reification of a tree. * * This reversion doesn't simply restore the original tree (that would lose the context of reification), diff --git a/src/library/scala/reflect/makro/internal/Utils.scala b/src/library/scala/reflect/makro/internal/Utils.scala index db658fd637..604bba10b6 100644 --- a/src/library/scala/reflect/makro/internal/Utils.scala +++ b/src/library/scala/reflect/makro/internal/Utils.scala @@ -55,49 +55,22 @@ package internal { NothingClass.asType -> newTermName("Nothing"), NullClass.asType -> newTermName("Null")) - def materializeClassTag(prefix: Tree, tpe: Type): Tree = { - val typetagInScope = c.inferImplicitValue(appliedType(typeRef(prefix.tpe, ConcreteTypeTagClass, Nil), List(tpe))) - def typetagIsSynthetic(tree: Tree) = tree.isInstanceOf[Block] || (tree exists (sub => sub.symbol == TypeTagModule || sub.symbol == ConcreteTypeTagModule)) - typetagInScope match { - case success if !success.isEmpty && !typetagIsSynthetic(success) => - val factory = TypeApply(Select(Ident(ClassTagModule), newTermName("apply")), List(TypeTree(tpe))) - Apply(factory, List(Select(typetagInScope, newTermName("tpe")))) - case _ => - val result = - tpe match { - case coreTpe if coreTags contains coreTpe => - Select(Ident(ClassTagModule), coreTags(coreTpe)) - case _ => - if (tpe.typeSymbol == ArrayClass) { - val componentTpe = tpe.typeArguments(0) - val classtagInScope = c.inferImplicitValue(appliedType(typeRef(NoPrefix, ClassTagClass, Nil), List(componentTpe))) - val componentTag = classtagInScope orElse materializeClassTag(prefix, componentTpe) - Select(componentTag, newTermName("wrap")) - } else { - // [Eugene] what's the intended behavior? there's no spec on ClassManifests - // for example, should we ban Array[T] or should we tag them with Array[AnyRef]? - // if its the latter, what should be the result of tagging Array[T] where T <: Int? - if (tpe.typeSymbol.isAbstractType) fail("tpe is an abstract type") - val erasure = - if (tpe.typeSymbol.isDerivedValueClass) tpe // [Eugene to Martin] is this correct? - else tpe.erasure.normalize // necessary to deal with erasures of HK types - val factory = TypeApply(Select(Ident(ClassTagModule), newTermName("apply")), List(TypeTree(tpe))) - Apply(factory, List(TypeApply(Ident(newTermName("classOf")), List(TypeTree(erasure))))) - } - } - try c.typeCheck(result) - catch { case terr @ c.TypeError(pos, msg) => fail(terr) } - } - } + def materializeClassTag(prefix: Tree, tpe: Type): Tree = + materializeTag(prefix, tpe, ClassTagModule, c.reifyErasure(tpe)) def materializeTypeTag(prefix: Tree, tpe: Type, requireConcreteTypeTag: Boolean): Tree = { val tagModule = if (requireConcreteTypeTag) ConcreteTypeTagModule else TypeTagModule + materializeTag(prefix, tpe, tagModule, c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, requireConcreteTypeTag = requireConcreteTypeTag)) + } + + private def materializeTag(prefix: Tree, tpe: Type, tagModule: Symbol, materializer: => Tree): Tree = { val result = tpe match { case coreTpe if coreTags contains coreTpe => - Select(Select(prefix, tagModule.name), coreTags(coreTpe)) + val ref = if (tagModule.owner.isPackageClass) Ident(tagModule) else Select(prefix, tagModule.name) + Select(ref, coreTags(coreTpe)) case _ => - try c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, requireConcreteTypeTag = requireConcreteTypeTag) + try materializer catch { case ex: Throwable => // [Eugene] cannot pattern match on an abstract type, so had to do this diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala index 6d50a96dfd..93fd0bb711 100644 --- a/src/library/scala/reflect/package.scala +++ b/src/library/scala/reflect/package.scala @@ -64,7 +64,7 @@ package object reflect { @deprecated("Use `@scala.reflect.ConcreteTypeTag` instead", "2.10.0") lazy val Manifest = ConcreteTypeTag @deprecated("NoManifest is no longer supported, and using it may lead to incorrect results, Use `@scala.reflect.TypeTag` instead", "2.10.0") - object NoManifest extends OptManifest[Nothing](scala.reflect.mirror.definitions.NothingClass.asType) with Serializable + object NoManifest extends OptManifest[Nothing](scala.reflect.mirror.TypeTag.Nothing.tpe) // ClassTag class is defined separately from the mirror type TypeTag[T] = scala.reflect.mirror.TypeTag[T] diff --git a/test/files/jvm/interpreter.check b/test/files/jvm/interpreter.check index 292d2fc4cb..85ec46c5f5 100644 --- a/test/files/jvm/interpreter.check +++ b/test/files/jvm/interpreter.check @@ -1,374 +1,375 @@ -Type in expressions to have them evaluated. -Type :help for more information. - -scala> - -scala> // basics - -scala> 3+4 -res0: Int = 7 - -scala> def gcd(x: Int, y: Int): Int = { - if (x == 0) y - else if (y == 0) x - else gcd(y%x, x) -} -gcd: (x: Int, y: Int)Int - -scala> val five = gcd(15,35) -five: Int = 5 - -scala> var x = 1 -x: Int = 1 - -scala> x = 2 -x: Int = 2 - -scala> val three = x+1 -three: Int = 3 - -scala> type anotherint = Int -defined type alias anotherint - -scala> val four: anotherint = 4 -four: anotherint = 4 - -scala> val bogus: anotherint = "hello" -<console>:8: error: type mismatch; - found : String("hello") - required: anotherint - (which expands to) Int - val bogus: anotherint = "hello" - ^ - -scala> trait PointlessTrait -defined trait PointlessTrait - -scala> val (x,y) = (2,3) -x: Int = 2 -y: Int = 3 - -scala> println("hello") -hello - -scala> - -scala> // ticket #1513 - -scala> val t1513 = Array(null) -t1513: Array[Null] = Array(null) - -scala> // ambiguous toString problem from #547 - -scala> val atom = new scala.xml.Atom() -atom: scala.xml.Atom[Unit] = () - -scala> // overriding toString problem from #1404 - -scala> class S(override val toString : String) -defined class S - -scala> val fish = new S("fish") -fish: S = fish - -scala> // Test that arrays pretty print nicely. - -scala> val arr = Array("What's", "up", "doc?") -arr: Array[String] = Array(What's, up, doc?) - -scala> // Test that arrays pretty print nicely, even when we give them type Any - -scala> val arrInt : Any = Array(1,2,3) -arrInt: Any = Array(1, 2, 3) - -scala> // Test that nested arrays are pretty-printed correctly - -scala> val arrArrInt : Any = Array(Array(1, 2), Array(3, 4)) -arrArrInt: Any = Array(Array(1, 2), Array(3, 4)) - -scala> - -scala> // implicit conversions - -scala> case class Foo(n: Int) -defined class Foo - -scala> case class Bar(n: Int) -defined class Bar - -scala> implicit def foo2bar(foo: Foo) = Bar(foo.n) -warning: there were 1 feature warnings; re-run with -feature for details -foo2bar: (foo: Foo)Bar - -scala> val bar: Bar = Foo(3) -bar: Bar = Bar(3) - -scala> - -scala> // importing from a previous result - -scala> import bar._ -import bar._ - -scala> val m = n -m: Int = 3 - -scala> - -scala> // stressing the imports mechanism - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> - -scala> - -scala> val x1 = 1 -x1: Int = 1 - -scala> val x2 = 1 -x2: Int = 1 - -scala> val x3 = 1 -x3: Int = 1 - -scala> val x4 = 1 -x4: Int = 1 - -scala> val x5 = 1 -x5: Int = 1 - -scala> val x6 = 1 -x6: Int = 1 - -scala> val x7 = 1 -x7: Int = 1 - -scala> val x8 = 1 -x8: Int = 1 - -scala> val x9 = 1 -x9: Int = 1 - -scala> val x10 = 1 -x10: Int = 1 - -scala> val x11 = 1 -x11: Int = 1 - -scala> val x12 = 1 -x12: Int = 1 - -scala> val x13 = 1 -x13: Int = 1 - -scala> val x14 = 1 -x14: Int = 1 - -scala> val x15 = 1 -x15: Int = 1 - -scala> val x16 = 1 -x16: Int = 1 - -scala> val x17 = 1 -x17: Int = 1 - -scala> val x18 = 1 -x18: Int = 1 - -scala> val x19 = 1 -x19: Int = 1 - -scala> val x20 = 1 -x20: Int = 1 - -scala> - -scala> val two = one + x5 -two: Int = 2 - -scala> - -scala> // handling generic wildcard arrays (#2386) - -scala> // It's put here because type feedback is an important part of it. - -scala> val xs: Array[_] = Array(1, 2) -xs: Array[_] = Array(1, 2) - -scala> xs.size -res2: Int = 2 - -scala> xs.head -res3: Any = 1 - -scala> xs filter (_ == 2) -res4: Array[_] = Array(2) - -scala> xs map (_ => "abc") -res5: Array[String] = Array(abc, abc) - -scala> xs map (x => x) -res6: scala.collection.mutable.ArraySeq[_] = ArraySeq(1, 2) - -scala> xs map (x => (x, x)) -warning: there were 1 feature warnings; re-run with -feature for details -warning: there were 1 feature warnings; re-run with -feature for details -res7: Array[(_$1, _$1)] forSome { type _$1 } = Array((1,1), (2,2)) - -scala> - -scala> // interior syntax errors should *not* go into multi-line input mode. - -scala> // both of the following should abort immediately: - -scala> def x => y => z -<console>:1: error: '=' expected but '=>' found. - def x => y => z - ^ - -scala> [1,2,3] -<console>:1: error: illegal start of definition - [1,2,3] - ^ - -scala> - -scala> - -scala> // multi-line XML - -scala> <a> -<b - c="c" - d="dd" -/></a> -res8: scala.xml.Elem = -<a> -<b c="c" d="dd"/></a> - -scala> - -scala> - -scala> /* - /* - multi-line comment - */ -*/ - - -You typed two blank lines. Starting a new command. - -scala> // multi-line string - -scala> """ -hello -there -""" -res12: String = -" -hello -there -" - -scala> - -scala> (1 + // give up early by typing two blank lines - - -You typed two blank lines. Starting a new command. - -scala> // defining and using quoted names should work (ticket #323) - -scala> def `match` = 1 -match: Int - -scala> val x = `match` -x: Int = 1 - -scala> - -scala> // multiple classes defined on one line - -scala> sealed class Exp; class Fact extends Exp; class Term extends Exp -defined class Exp -defined class Fact -defined class Term - -scala> def f(e: Exp) = e match { // non-exhaustive warning here - case _:Fact => 3 -} -<console>:18: warning: match is not exhaustive! -missing combination Exp -missing combination Term - - def f(e: Exp) = e match { // non-exhaustive warning here - ^ -f: (e: Exp)Int - -scala> - -scala> +Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> // basics
+
+scala> 3+4
+res0: Int = 7
+
+scala> def gcd(x: Int, y: Int): Int = {
+ if (x == 0) y
+ else if (y == 0) x
+ else gcd(y%x, x)
+}
+gcd: (x: Int, y: Int)Int
+
+scala> val five = gcd(15,35)
+five: Int = 5
+
+scala> var x = 1
+x: Int = 1
+
+scala> x = 2
+x: Int = 2
+
+scala> val three = x+1
+three: Int = 3
+
+scala> type anotherint = Int
+defined type alias anotherint
+
+scala> val four: anotherint = 4
+four: anotherint = 4
+
+scala> val bogus: anotherint = "hello"
+<console>:8: error: type mismatch;
+ found : String("hello")
+ required: anotherint
+ (which expands to) Int
+ val bogus: anotherint = "hello"
+ ^
+
+scala> trait PointlessTrait
+defined trait PointlessTrait
+
+scala> val (x,y) = (2,3)
+x: Int = 2
+y: Int = 3
+
+scala> println("hello")
+hello
+
+scala>
+
+scala> // ticket #1513
+
+scala> val t1513 = Array(null)
+t1513: Array[Null] = Array(null)
+
+scala> // ambiguous toString problem from #547
+
+scala> val atom = new scala.xml.Atom()
+atom: scala.xml.Atom[Unit] = ()
+
+scala> // overriding toString problem from #1404
+
+scala> class S(override val toString : String)
+defined class S
+
+scala> val fish = new S("fish")
+fish: S = fish
+
+scala> // Test that arrays pretty print nicely.
+
+scala> val arr = Array("What's", "up", "doc?")
+arr: Array[String] = Array(What's, up, doc?)
+
+scala> // Test that arrays pretty print nicely, even when we give them type Any
+
+scala> val arrInt : Any = Array(1,2,3)
+arrInt: Any = Array(1, 2, 3)
+
+scala> // Test that nested arrays are pretty-printed correctly
+
+scala> val arrArrInt : Any = Array(Array(1, 2), Array(3, 4))
+arrArrInt: Any = Array(Array(1, 2), Array(3, 4))
+
+scala>
+
+scala> // implicit conversions
+
+scala> case class Foo(n: Int)
+defined class Foo
+
+scala> case class Bar(n: Int)
+defined class Bar
+
+scala> implicit def foo2bar(foo: Foo) = Bar(foo.n)
+warning: there were 1 feature warnings; re-run with -feature for details
+foo2bar: (foo: Foo)Bar
+
+scala> val bar: Bar = Foo(3)
+bar: Bar = Bar(3)
+
+scala>
+
+scala> // importing from a previous result
+
+scala> import bar._
+import bar._
+
+scala> val m = n
+m: Int = 3
+
+scala>
+
+scala> // stressing the imports mechanism
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala>
+
+scala>
+
+scala> val x1 = 1
+x1: Int = 1
+
+scala> val x2 = 1
+x2: Int = 1
+
+scala> val x3 = 1
+x3: Int = 1
+
+scala> val x4 = 1
+x4: Int = 1
+
+scala> val x5 = 1
+x5: Int = 1
+
+scala> val x6 = 1
+x6: Int = 1
+
+scala> val x7 = 1
+x7: Int = 1
+
+scala> val x8 = 1
+x8: Int = 1
+
+scala> val x9 = 1
+x9: Int = 1
+
+scala> val x10 = 1
+x10: Int = 1
+
+scala> val x11 = 1
+x11: Int = 1
+
+scala> val x12 = 1
+x12: Int = 1
+
+scala> val x13 = 1
+x13: Int = 1
+
+scala> val x14 = 1
+x14: Int = 1
+
+scala> val x15 = 1
+x15: Int = 1
+
+scala> val x16 = 1
+x16: Int = 1
+
+scala> val x17 = 1
+x17: Int = 1
+
+scala> val x18 = 1
+x18: Int = 1
+
+scala> val x19 = 1
+x19: Int = 1
+
+scala> val x20 = 1
+x20: Int = 1
+
+scala>
+
+scala> val two = one + x5
+two: Int = 2
+
+scala>
+
+scala> // handling generic wildcard arrays (#2386)
+
+scala> // It's put here because type feedback is an important part of it.
+
+scala> val xs: Array[_] = Array(1, 2)
+xs: Array[_] = Array(1, 2)
+
+scala> xs.size
+res2: Int = 2
+
+scala> xs.head
+res3: Any = 1
+
+scala> xs filter (_ == 2)
+res4: Array[_] = Array(2)
+
+scala> xs map (_ => "abc")
+res5: Array[String] = Array(abc, abc)
+
+scala> xs map (x => x)
+res6: Array[_] = Array(1, 2)
+
+scala> xs map (x => (x, x))
+warning: there were 1 feature warnings; re-run with -feature for details
+warning: there were 1 feature warnings; re-run with -feature for details
+res7: Array[(_$1, _$1)] forSome { type _$1 } = Array((1,1), (2,2))
+
+scala>
+
+scala> // interior syntax errors should *not* go into multi-line input mode.
+
+scala> // both of the following should abort immediately:
+
+scala> def x => y => z
+<console>:1: error: '=' expected but '=>' found.
+ def x => y => z
+ ^
+
+scala> [1,2,3]
+<console>:1: error: illegal start of definition
+ [1,2,3]
+ ^
+
+scala>
+
+scala>
+
+scala> // multi-line XML
+
+scala> <a>
+<b
+ c="c"
+ d="dd"
+/></a>
+res8: scala.xml.Elem =
+<a>
+<b c="c" d="dd"/></a>
+
+scala>
+
+scala>
+
+scala> /*
+ /*
+ multi-line comment
+ */
+*/
+
+scala>
+
+scala>
+
+scala> // multi-line string
+
+scala> """
+hello
+there
+"""
+res9: String =
+"
+hello
+there
+"
+
+scala>
+
+scala> (1 + // give up early by typing two blank lines
+
+
+You typed two blank lines. Starting a new command.
+
+scala> // defining and using quoted names should work (ticket #323)
+
+scala> def `match` = 1
+match: Int
+
+scala> val x = `match`
+x: Int = 1
+
+scala>
+
+scala> // multiple classes defined on one line
+
+scala> sealed class Exp; class Fact extends Exp; class Term extends Exp
+defined class Exp
+defined class Fact
+defined class Term
+
+scala> def f(e: Exp) = e match { // non-exhaustive warning here
+ case _:Fact => 3
+}
+<console>:18: warning: match is not exhaustive!
+missing combination Exp
+missing combination Term
+
+ def f(e: Exp) = e match { // non-exhaustive warning here
+ ^
+f: (e: Exp)Int
+
+scala>
+
+scala>
plusOne: (x: Int)Int res0: Int = 6 res0: String = after reset diff --git a/test/files/run/existentials3.check b/test/files/run/existentials3.check index 8227d77909..85bc430a21 100644 --- a/test/files/run/existentials3.check +++ b/test/files/run/existentials3.check @@ -7,7 +7,7 @@ ConcreteTypeTag[() => Test.ToS], t=TypeRef, s=class Function0 ConcreteTypeTag[() => Test.ToS], t=TypeRef, s=class Function0
ConcreteTypeTag[$anon], t=TypeRef, s= <: B with Test.ToS
ConcreteTypeTag[$anon], t=TypeRef, s= <: B with A with Test.ToS
-ConcreteTypeTag[List[Object{type T1}#T1]], t=TypeRef, s=class List
+TypeTag[List[Object{type T1}#T1]], t=TypeRef, s=class List
ConcreteTypeTag[List[Seq[Int]]], t=TypeRef, s=class List
ConcreteTypeTag[List[Seq[U forSome { type U <: Int }]]], t=TypeRef, s=class List
ConcreteTypeTag[Bar.type], t=TypeRef, s= <: scala.runtime.AbstractFunction0[Bar] with Serializable{case def unapply(x$0: Bar): Boolean} with Singleton
@@ -19,6 +19,6 @@ ConcreteTypeTag[() => Test.ToS], t=TypeRef, s=class Function0 ConcreteTypeTag[() => Test.ToS], t=TypeRef, s=class Function0
ConcreteTypeTag[$anon], t=TypeRef, s= <: B with Test.ToS
ConcreteTypeTag[$anon], t=TypeRef, s= <: B with A with Test.ToS
-ConcreteTypeTag[List[Object{type T1}#T1]], t=TypeRef, s=class List
+TypeTag[List[Object{type T1}#T1]], t=TypeRef, s=class List
ConcreteTypeTag[List[Seq[Int]]], t=TypeRef, s=class List
ConcreteTypeTag[List[Seq[U forSome { type U <: Int }]]], t=TypeRef, s=class List
diff --git a/test/files/run/macro-reify-typetag-typeparams-notags.check b/test/files/run/macro-reify-typetag-typeparams-notags.check index af4877e205..11d78ece41 100644 --- a/test/files/run/macro-reify-typetag-typeparams-notags.check +++ b/test/files/run/macro-reify-typetag-typeparams-notags.check @@ -1,2 +1,2 @@ -ConcreteTypeTag[T]
-ConcreteTypeTag[List[T]]
+TypeTag[T]
+TypeTag[List[T]]
diff --git a/test/files/run/macro-reify-typetag-typeparams-tags.check b/test/files/run/macro-reify-typetag-typeparams-tags.check index d75b3c72b2..458593c449 100644 --- a/test/files/run/macro-reify-typetag-typeparams-tags.check +++ b/test/files/run/macro-reify-typetag-typeparams-tags.check @@ -1,2 +1,2 @@ ConcreteTypeTag[Int]
-ConcreteTypeTag[List[Int]]
+*ConcreteTypeTag[List[Int]]
diff --git a/test/files/run/macro-reify-typetag-usegroundtypetag.check b/test/files/run/macro-reify-typetag-usegroundtypetag.check index d75b3c72b2..458593c449 100644 --- a/test/files/run/macro-reify-typetag-usegroundtypetag.check +++ b/test/files/run/macro-reify-typetag-usegroundtypetag.check @@ -1,2 +1,2 @@ ConcreteTypeTag[Int]
-ConcreteTypeTag[List[Int]]
+*ConcreteTypeTag[List[Int]]
diff --git a/test/files/run/macro-typecheck-macrosdisabled.check b/test/files/run/macro-typecheck-macrosdisabled.check index b432a539fc..3e1057520b 100644 --- a/test/files/run/macro-typecheck-macrosdisabled.check +++ b/test/files/run/macro-typecheck-macrosdisabled.check @@ -1,5 +1,5 @@ {
val $mr: reflect.mirror.type = scala.reflect.`package`.mirror;
- $mr.Expr.apply[Int(2)]($mr.Literal.apply($mr.Constant.apply(2)))($mr.ConcreteTypeTag.apply[Int(2)]($mr.ConstantType.apply($mr.Constant.apply(2))))
+ $mr.Expr.apply[Int(2)]($mr.Literal.apply($mr.Constant.apply(2)))($mr.ConcreteTypeTag.apply[Int(2)]($mr.ConstantType.apply($mr.Constant.apply(2)), classOf[scala.Int]))
}
mr.reify[Int](2)
diff --git a/test/files/run/macro-typecheck-macrosdisabled/Impls_Macros_1.scala b/test/files/run/macro-typecheck-macrosdisabled/Impls_Macros_1.scala index c253f0b1fb..a1f124f790 100644 --- a/test/files/run/macro-typecheck-macrosdisabled/Impls_Macros_1.scala +++ b/test/files/run/macro-typecheck-macrosdisabled/Impls_Macros_1.scala @@ -8,7 +8,7 @@ object Macros { //val mrPkg = staticModule("scala.reflect.package") //val mrSym = selectTerm(mrPkg, "mirror") //val NullaryMethodType(mrTpe) = mrSym.typeSignature - //val mr = newFreeTerm("mr", mrTpe, scala.reflect.mirror, null) + //val mr = newFreeTerm("mr", mrTpe, scala.reflect.mirror) //val tree1 = Apply(Select(Ident(mr), newTermName("reify")), List(Literal(Constant(2)))) val mr = Select(Select(Select(Ident(newTermName("scala")), newTermName("reflect")), newTermName("package")), newTermName("mirror")) @@ -25,7 +25,7 @@ object Macros { val mrPkg = staticModule("scala.reflect.package") val mrSym = selectTerm(mrPkg, "mirror") val NullaryMethodType(mrTpe) = mrSym.typeSignature - val mr = newFreeTerm("mr", mrTpe, scala.reflect.mirror, null) + val mr = newFreeTerm("mr", mrTpe, scala.reflect.mirror) val tree2 = Apply(Select(Ident(mr), newTermName("reify")), List(Literal(Constant(2)))) val ttree2 = c.typeCheck(tree2, withMacrosDisabled = true) diff --git a/test/files/run/reify_newimpl_26.check b/test/files/run/reify_newimpl_26.check index bfbf1d653d..d92b3bd817 100644 --- a/test/files/run/reify_newimpl_26.check +++ b/test/files/run/reify_newimpl_26.check @@ -16,7 +16,7 @@ scala> def foo[T]{ foo: [T]=> Unit
scala> foo[Int]
-ConcreteTypeTag[List[T]]
+TypeTag[List[T]]
scala>
diff --git a/test/files/run/t3507.check b/test/files/run/t3507.check index 50ab029592..6e4fa4170e 100644 --- a/test/files/run/t3507.check +++ b/test/files/run/t3507.check @@ -1 +1 @@ -ConcreteTypeTag[_1.type#b.c.type]
+ConcreteTypeTag[_1.b.c.type]
diff --git a/test/files/run/toolbox_typecheck_macrosdisabled.check b/test/files/run/toolbox_typecheck_macrosdisabled.check index cf2420bc17..c4af175812 100644 --- a/test/files/run/toolbox_typecheck_macrosdisabled.check +++ b/test/files/run/toolbox_typecheck_macrosdisabled.check @@ -1,5 +1,5 @@ {
val $mr: mr.type = mr;
- $mr.Expr.apply[Int(2)]($mr.Literal.apply($mr.Constant.apply(2)))($mr.ConcreteTypeTag.apply[Int(2)]($mr.ConstantType.apply($mr.Constant.apply(2))))
+ $mr.Expr.apply[Int(2)]($mr.Literal.apply($mr.Constant.apply(2)))($mr.ConcreteTypeTag.apply[Int(2)]($mr.ConstantType.apply($mr.Constant.apply(2)), classOf[scala.Int]))
}
mr.reify[Int](2)
diff --git a/test/files/run/toolbox_typecheck_macrosdisabled.scala b/test/files/run/toolbox_typecheck_macrosdisabled.scala index 7d2707d5e1..afbbce1736 100644 --- a/test/files/run/toolbox_typecheck_macrosdisabled.scala +++ b/test/files/run/toolbox_typecheck_macrosdisabled.scala @@ -5,7 +5,7 @@ object Test extends App { val mrPkg = staticModule("scala.reflect.package") val mrSym = selectTerm(mrPkg, "mirror") val NullaryMethodType(mrTpe) = mrSym.typeSignature - val mr = newFreeTerm("mr", mrTpe, scala.reflect.mirror, null) + val mr = newFreeTerm("mr", mrTpe, scala.reflect.mirror) val tree1 = Apply(Select(Ident(mr), newTermName("reify")), List(Literal(Constant(2)))) val ttree1 = toolbox.typeCheck(tree1, withMacrosDisabled = false) |