diff options
Diffstat (limited to 'src')
28 files changed, 849 insertions, 472 deletions
diff --git a/src/compiler/scala/tools/nsc/plugins/Plugin.scala b/src/compiler/scala/tools/nsc/plugins/Plugin.scala index d194c095f8..183752d4a2 100644 --- a/src/compiler/scala/tools/nsc/plugins/Plugin.scala +++ b/src/compiler/scala/tools/nsc/plugins/Plugin.scala @@ -12,7 +12,8 @@ import scala.reflect.io.{ Directory, File, Path } import java.io.InputStream import java.util.zip.ZipException -import scala.collection.mutable.ListBuffer +import scala.collection.mutable +import mutable.ListBuffer import scala.util.{ Try, Success, Failure } /** Information about a plugin loaded from a jar file. @@ -99,7 +100,7 @@ object Plugin { private def loadDescriptionFromJar(jarp: Path): Try[PluginDescription] = { // XXX Return to this once we have more ARM support def read(is: Option[InputStream]) = is match { - case None => throw new RuntimeException(s"Missing $PluginXML in $jarp") + case None => throw new PluginLoadException(jarp.path, s"Missing $PluginXML in $jarp") case Some(is) => PluginDescription.fromXML(is) } Try(new Jar(jarp.jfile).withEntryStream(PluginXML)(read)) @@ -113,11 +114,14 @@ object Plugin { /** Use a class loader to load the plugin class. */ def load(classname: String, loader: ClassLoader): Try[AnyClass] = { - Try[AnyClass] { - loader loadClass classname - } recoverWith { - case _: Exception => - Failure(new RuntimeException(s"Warning: class not found: ${classname}")) + import scala.util.control.NonFatal + try { + Success[AnyClass](loader loadClass classname) + } catch { + case NonFatal(e) => + Failure(new PluginLoadException(classname, s"Error: unable to load class: $classname")) + case e: NoClassDefFoundError => + Failure(new PluginLoadException(classname, s"Error: class not found: ${e.getMessage} required by $classname")) } } @@ -128,33 +132,54 @@ object Plugin { * A single classloader is created and used to load all of them. */ def loadAllFrom( - jars: List[Path], + paths: List[List[Path]], dirs: List[Path], ignoring: List[String]): List[Try[AnyClass]] = { - // List[(jar, Success(descriptor))] in dir - def scan(d: Directory) = for { - f <- d.files.toList sortBy (_.name) - if Jar isJarOrZip f - pd = loadDescriptionFromJar(f) - if pd.isSuccess - } yield (f, pd) - // (dir, Try(descriptor)) - def explode(d: Directory) = d -> loadDescriptionFromFile(d / PluginXML) - // (j, Try(descriptor)) - def required(j: Path) = j -> loadDescriptionFromJar(j) - - type Paired = Tuple2[Path, Try[PluginDescription]] - val included: List[Paired] = (dirs flatMap (_ ifDirectory scan)).flatten - val exploded: List[Paired] = jars flatMap (_ ifDirectory explode) - val explicit: List[Paired] = jars flatMap (_ ifFile required) - def ignored(p: Paired) = p match { - case (path, Success(pd)) => ignoring contains pd.name - case _ => false + // List[(jar, Try(descriptor))] in dir + def scan(d: Directory) = + d.files.toList sortBy (_.name) filter (Jar isJarOrZip _) map (j => (j, loadDescriptionFromJar(j))) + + type PDResults = List[Try[(PluginDescription, ScalaClassLoader)]] + + // scan plugin dirs for jars containing plugins, ignoring dirs with none and other jars + val fromDirs: PDResults = dirs filter (_.isDirectory) flatMap { d => + scan(d.toDirectory) collect { + case (j, Success(pd)) => Success((pd, loaderFor(Seq(j)))) + } + } + + // scan jar paths for plugins, taking the first plugin you find. + // a path element can be either a plugin.jar or an exploded dir. + def findDescriptor(ps: List[Path]) = { + def loop(qs: List[Path]): Try[PluginDescription] = qs match { + case Nil => Failure(new MissingPluginException(ps)) + case p :: rest => + if (p.isDirectory) loadDescriptionFromFile(p.toDirectory / PluginXML) + else if (p.isFile) loadDescriptionFromJar(p.toFile) + else loop(rest) + } + loop(ps) + } + val fromPaths: PDResults = paths map (p => (p, findDescriptor(p))) map { + case (p, Success(pd)) => Success((pd, loaderFor(p))) + case (_, Failure(e)) => Failure(e) } - val (locs, pds) = ((explicit ::: exploded ::: included) filterNot ignored).unzip - val loader = loaderFor(locs.distinct) - (pds filter (_.isSuccess) map (_.get.classname)).distinct map (Plugin load (_, loader)) + + val seen = mutable.HashSet[String]() + val enabled = (fromPaths ::: fromDirs) map { + case Success((pd, loader)) if seen(pd.classname) => + // a nod to SI-7494, take the plugin classes distinctly + Failure(new PluginLoadException(pd.name, s"Ignoring duplicate plugin ${pd.name} (${pd.classname})")) + case Success((pd, loader)) if ignoring contains pd.name => + Failure(new PluginLoadException(pd.name, s"Disabling plugin ${pd.name}")) + case Success((pd, loader)) => + seen += pd.classname + Plugin.load(pd.classname, loader) + case Failure(e) => + Failure(e) + } + enabled // distinct and not disabled } /** Instantiate a plugin class, given the class and @@ -164,3 +189,11 @@ object Plugin { (clazz getConstructor classOf[Global] newInstance global).asInstanceOf[Plugin] } } + +class PluginLoadException(val path: String, message: String, cause: Exception) extends Exception(message, cause) { + def this(path: String, message: String) = this(path, message, null) +} + +class MissingPluginException(path: String) extends PluginLoadException(path, s"No plugin in path $path") { + def this(paths: List[Path]) = this(paths mkString File.pathSeparator) +} diff --git a/src/compiler/scala/tools/nsc/plugins/PluginLoadException.scala b/src/compiler/scala/tools/nsc/plugins/PluginLoadException.scala deleted file mode 100644 index c5da24993e..0000000000 --- a/src/compiler/scala/tools/nsc/plugins/PluginLoadException.scala +++ /dev/null @@ -1,15 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2007-2013 LAMP/EPFL - * @author Lex Spoon - */ - -package scala.tools.nsc -package plugins - -/** ... - * - * @author Lex Spoon - * @version 1.0, 2007-5-21 - */ -class PluginLoadException(filename: String, cause: Exception) -extends Exception(cause) diff --git a/src/compiler/scala/tools/nsc/plugins/Plugins.scala b/src/compiler/scala/tools/nsc/plugins/Plugins.scala index 4769705404..12f9aeba27 100644 --- a/src/compiler/scala/tools/nsc/plugins/Plugins.scala +++ b/src/compiler/scala/tools/nsc/plugins/Plugins.scala @@ -8,6 +8,7 @@ package scala.tools.nsc package plugins import scala.reflect.io.{ File, Path } +import scala.tools.nsc.util.ClassPath import scala.tools.util.PathResolver.Defaults /** Support for run-time loading of compiler plugins. @@ -16,8 +17,7 @@ import scala.tools.util.PathResolver.Defaults * @version 1.1, 2009/1/2 * Updated 2009/1/2 by Anders Bach Nielsen: Added features to implement SIP 00002 */ -trait Plugins { - self: Global => +trait Plugins { global: Global => /** Load a rough list of the plugins. For speed, it * does not instantiate a compiler run. Therefore it cannot @@ -25,13 +25,20 @@ trait Plugins { * filtered from the final list of plugins. */ protected def loadRoughPluginsList(): List[Plugin] = { - val jars = settings.plugin.value map Path.apply - def injectDefault(s: String) = if (s.isEmpty) Defaults.scalaPluginPath else s - val dirs = (settings.pluginsDir.value split File.pathSeparator).toList map injectDefault map Path.apply - val maybes = Plugin.loadAllFrom(jars, dirs, settings.disable.value) + def asPath(p: String) = ClassPath split p + val paths = settings.plugin.value filter (_ != "") map (s => asPath(s) map Path.apply) + val dirs = { + def injectDefault(s: String) = if (s.isEmpty) Defaults.scalaPluginPath else s + asPath(settings.pluginsDir.value) map injectDefault map Path.apply + } + val maybes = Plugin.loadAllFrom(paths, dirs, settings.disable.value) val (goods, errors) = maybes partition (_.isSuccess) // Explicit parameterization of recover to suppress -Xlint warning about inferred Any - errors foreach (_.recover[Any] { case e: Exception => inform(e.getMessage) }) + errors foreach (_.recover[Any] { + // legacy behavior ignores altogether, so at least warn devs + case e: MissingPluginException => if (global.isDeveloper) warning(e.getMessage) + case e: Exception => inform(e.getMessage) + }) val classes = goods map (_.get) // flatten // Each plugin must only be instantiated once. A common pattern diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 6fe0f34105..6732900ef2 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -714,11 +714,24 @@ abstract class Erasure extends AddInterfaces /** TODO - adapt SymbolPairs so it can be used here. */ private def checkNoDeclaredDoubleDefs(base: Symbol) { val decls = base.info.decls + + // SI-8010 force infos, otherwise makeNotPrivate in ExplicitOuter info transformer can trigger + // a scope rehash while were iterating and we can see the same entry twice! + // Inspection of SymbolPairs (the basis of OverridingPairs), suggests that it is immune + // from this sort of bug as it copies the symbols into a temporary scope *before* any calls to `.info`, + // ie, no variant of it calls `info` or `tpe` in `SymbolPair#exclude`. + // + // Why not just create a temporary scope here? We need to force the name changes in any case before + // we do these checks, so that we're comparing same-named methods based on the expanded names that actually + // end up in the bytecode. + exitingPostErasure(decls.foreach(_.info)) + var e = decls.elems while (e ne null) { if (e.sym.isTerm) { var e1 = decls lookupNextEntry e while (e1 ne null) { + assert(e.sym ne e1.sym, s"Internal error: encountered ${e.sym.debugLocationString} twice during scope traversal. This might be related to SI-8010.") if (sameTypeAfterErasure(e.sym, e1.sym)) doubleDefError(new SymbolPair(base, e.sym, e1.sym)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 2be6d92ed0..53bc9a2772 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -773,7 +773,7 @@ trait Contexts { self: Analyzer => // Implicit collection // - private var implicitsCache: List[List[ImplicitInfo]] = null + private var implicitsCache: List[ImplicitInfo] = null private var implicitsRunId = NoRunId def resetCache() { @@ -832,35 +832,53 @@ trait Contexts { self: Analyzer => * filtered out later by `eligibleInfos` (SI-4270 / 9129cfe9), as they don't type-check. */ def implicitss: List[List[ImplicitInfo]] = { - val imports = this.imports val nextOuter = this.nextOuter - if (implicitsRunId != currentRunId) { - implicitsRunId = currentRunId - implicitsCache = List() - val newImplicits: List[ImplicitInfo] = - if (owner != nextOuter.owner && owner.isClass && !owner.isPackageClass && !inSelfSuperCall) { - if (!owner.isInitialized) return nextOuter.implicitss - // debuglog("collect member implicits " + owner + ", implicit members = " + owner.thisType.implicitMembers)//DEBUG - savingEnclClass(this) { - // !!! In the body of `class C(implicit a: A) { }`, `implicitss` returns `List(List(a), List(a), List(<predef..)))` - // it handled correctly by implicit search, which considers the second `a` to be shadowed, but should be - // remedied nonetheless. - collectImplicits(owner.thisType.implicitMembers, owner.thisType) - } - } else if (scope != nextOuter.scope && !owner.isPackageClass) { - debuglog("collect local implicits " + scope.toList)//DEBUG - collectImplicits(scope, NoPrefix) - } else if (firstImport != nextOuter.firstImport) { - assert(imports.tail.headOption == nextOuter.firstImport, (imports, nextOuter.imports)) - collectImplicitImports(imports.head) - } else if (owner.isPackageClass) { - // the corresponding package object may contain implicit members. - collectImplicits(owner.tpe.implicitMembers, owner.tpe) - } else List() - implicitsCache = if (newImplicits.isEmpty) nextOuter.implicitss - else newImplicits :: nextOuter.implicitss + def withOuter(is: List[ImplicitInfo]): List[List[ImplicitInfo]] = + is match { + case Nil => nextOuter.implicitss + case _ => is :: nextOuter.implicitss + } + + val CycleMarker = NoRunId - 1 + if (implicitsRunId == CycleMarker) { + debuglog(s"cycle while collecting implicits at owner ${owner}, probably due to an implicit without an explicit return type. Continuing with implicits from enclosing contexts.") + withOuter(Nil) + } else if (implicitsRunId != currentRunId) { + implicitsRunId = CycleMarker + implicits(nextOuter) match { + case None => + implicitsRunId = NoRunId + withOuter(Nil) + case Some(is) => + implicitsRunId = currentRunId + implicitsCache = is + withOuter(is) + } } - implicitsCache + else withOuter(implicitsCache) + } + + /** @return None if a cycle is detected, or Some(infos) containing the in-scope implicits at this context */ + private def implicits(nextOuter: Context): Option[List[ImplicitInfo]] = { + val imports = this.imports + if (owner != nextOuter.owner && owner.isClass && !owner.isPackageClass && !inSelfSuperCall) { + if (!owner.isInitialized) None + else savingEnclClass(this) { + // !!! In the body of `class C(implicit a: A) { }`, `implicitss` returns `List(List(a), List(a), List(<predef..)))` + // it handled correctly by implicit search, which considers the second `a` to be shadowed, but should be + // remedied nonetheless. + Some(collectImplicits(owner.thisType.implicitMembers, owner.thisType)) + } + } else if (scope != nextOuter.scope && !owner.isPackageClass) { + debuglog("collect local implicits " + scope.toList)//DEBUG + Some(collectImplicits(scope, NoPrefix)) + } else if (firstImport != nextOuter.firstImport) { + assert(imports.tail.headOption == nextOuter.firstImport, (imports, nextOuter.imports)) + Some(collectImplicitImports(imports.head)) + } else if (owner.isPackageClass) { + // the corresponding package object may contain implicit members. + Some(collectImplicits(owner.tpe.implicitMembers, owner.tpe)) + } else Some(Nil) } // @@ -1108,7 +1126,7 @@ trait Contexts { self: Analyzer => impSym = NoSymbol // Otherwise they are irreconcilably ambiguous else - return ambiguousDefnAndImport(defSym.owner, imp1) + return ambiguousDefnAndImport(defSym.alternatives.head.owner, imp1) } // At this point only one or the other of defSym and impSym might be set. diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala index ba135d7d25..069d6d5fb2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala @@ -391,8 +391,10 @@ trait PatternTypers { else freshUnapplyArgType() ) ) + val unapplyArgTree = Ident(unapplyArg) updateAttachment SubpatternsAttachment(args) + // clearing the type is necessary so that ref will be stabilized; see bug 881 - val fun1 = typedPos(fun.pos)(Apply(Select(fun.clearType(), unapplyMethod), Ident(unapplyArg) :: Nil)) + val fun1 = typedPos(fun.pos)(Apply(Select(fun.clearType(), unapplyMethod), unapplyArgTree :: Nil)) def makeTypedUnApply() = { // the union of the expected type and the inferred type of the argument to unapply diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 520b55400c..5e89440bc0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3746,7 +3746,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val dealiasLocals = new TypeMap { def apply(tp: Type): Type = tp match { case TypeRef(pre, sym, args) => - if (sym.isAliasType && containsLocal(tp)) apply(tp.dealias) + if (sym.isAliasType && containsLocal(tp) && (tp.dealias ne tp)) apply(tp.dealias) else { if (pre.isVolatile) InferTypeWithVolatileTypeSelectionError(tree, pre) diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala index f92c9aa845..f5bcaf68e0 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala @@ -3,6 +3,7 @@ package quasiquotes import scala.collection.{immutable, mutable} import scala.reflect.internal.Flags._ +import scala.reflect.macros.TypecheckException class Cardinality private[Cardinality](val value: Int) extends AnyVal { def pred = { assert(value - 1 >= 0); new Cardinality(value - 1) } @@ -30,158 +31,173 @@ trait Holes { self: Quasiquotes => import definitions._ import universeTypes._ - /** Location characterizes a kind of a non-terminal in Scala syntax where something is going to be spliced. - * A location is typically associated with a type of the things that can be spliced there. - * Associated type might be different from an actual tpe of a splicee due to lifting. - * This is the first pillar of modularity in the quasiquote reifier. - */ - sealed abstract class Location(val tpe: Type) - case object UnknownLocation extends Location(NoType) - case class TreeLocation(override val tpe: Type) extends Location(tpe) - case object NameLocation extends Location(nameType) - case object ModsLocation extends Location(modsType) - case object FlagsLocation extends Location(flagsType) - case object SymbolLocation extends Location(symbolType) - case class IterableLocation(card: Cardinality, sublocation: TreeLocation) extends Location(NoType) { - override val tpe = { - def loop(n: Cardinality, tpe: Type): Type = - if (n == NoDot) tpe - else appliedType(IterableClass.toType, List(loop(n.pred, tpe))) - loop(card, sublocation.tpe) + protected lazy val IterableTParam = IterableClass.typeParams(0).asType.toType + protected def inferParamImplicit(tfun: Type, targ: Type) = c.inferImplicitValue(appliedType(tfun, List(targ)), silent = true) + protected def inferLiftable(tpe: Type): Tree = inferParamImplicit(liftableType, tpe) + protected def inferUnliftable(tpe: Type): Tree = inferParamImplicit(unliftableType, tpe) + protected def isLiftableType(tpe: Type) = inferLiftable(tpe) != EmptyTree + protected def isNativeType(tpe: Type) = + (tpe <:< treeType) || (tpe <:< nameType) || (tpe <:< modsType) || + (tpe <:< flagsType) || (tpe <:< symbolType) + protected def isBottomType(tpe: Type) = + tpe <:< NothingClass.tpe || tpe <:< NullClass.tpe + protected def stripIterable(tpe: Type, limit: Option[Cardinality] = None): (Cardinality, Type) = + if (limit.map { _ == NoDot }.getOrElse { false }) (NoDot, tpe) + else if (tpe != null && !isIterableType(tpe)) (NoDot, tpe) + else if (isBottomType(tpe)) (NoDot, tpe) + else { + val targ = IterableTParam.asSeenFrom(tpe, IterableClass) + val (card, innerTpe) = stripIterable(targ, limit.map { _.pred }) + (card.succ, innerTpe) } + protected def iterableTypeFromCard(n: Cardinality, tpe: Type): Type = { + if (n == NoDot) tpe + else appliedType(IterableClass.toType, List(iterableTypeFromCard(n.pred, tpe))) } - /** Hole type describes location, cardinality and a pre-reification routine associated with a hole. - * An interesting thing about HoleType is that it can be completely inferred from the type of the splicee. - * This is the second pillar of modularity in the quasiquote reifier. + /** Hole encapsulates information about splices in quasiquotes. + * It packs together a cardinality of a splice, pre-reified tree + * representation (possibly preprocessed) and position. */ - case class HoleType(preprocessor: Tree => Tree, location: Location, cardinality: Cardinality) { - def makeHole(tree: Tree) = Hole(preprocessor(tree), location, cardinality) + abstract class Hole { + val tree: Tree + val pos: Position + val cardinality: Cardinality } - object HoleType { - def unapply(tpe: Type): Option[HoleType] = tpe match { - case NativeType(holeTpe) => Some(holeTpe) - case LiftableType(holeTpe) => Some(holeTpe) - case IterableTreeType(holeTpe) => Some(holeTpe) - case IterableLiftableType(holeTpe) => Some(holeTpe) - case _ => None - } - trait HoleTypeExtractor { - def unapply(tpe: Type): Option[HoleType] = { - for { - preprocessor <- this.preprocessor(tpe) - location <- this.location(tpe) - cardinality <- Some(this.cardinality(tpe)) - } yield HoleType(preprocessor, location, cardinality) - } - def preprocessor(tpe: Type): Option[Tree => Tree] - def location(tpe: Type): Option[Location] - def cardinality(tpe: Type): Cardinality = parseCardinality(tpe)._1 - - def lifter(tpe: Type): Option[Tree => Tree] = { - val lifterTpe = appliedType(LiftableClass.toType, List(tpe)) - val lifter = c.inferImplicitValue(lifterTpe, silent = true) - if (lifter != EmptyTree) Some(tree => { - val lifted = Apply(lifter, List(u, tree)) - val targetType = Select(u, tpnme.Tree) - atPos(tree.pos)(TypeApply(Select(lifted, nme.asInstanceOf_), List(targetType))) - }) else None - } + object Hole { + def apply(card: Cardinality, tree: Tree): Hole = + if (method != nme.unapply) new ApplyHole(card, tree) + else new UnapplyHole(card, tree) + def unapply(hole: Hole): Some[(Tree, Cardinality)] = Some((hole.tree, hole.cardinality)) + } - def iterator(tpe: Type)(elementTransform: Tree => Tree): Option[Tree => Tree] = { - def reifyIterable(tree: Tree, n: Cardinality): Tree = { - def loop(tree: Tree, n: Cardinality) = - if (n == NoDot) elementTransform(tree) - else { - val x: TermName = c.freshName() - val wrapped = reifyIterable(Ident(x), n.pred) - val xToWrapped = Function(List(ValDef(Modifiers(PARAM), x, TypeTree(), EmptyTree)), wrapped) - Select(Apply(Select(tree, nme.map), List(xToWrapped)), nme.toList) - } - if (tree.tpe != null && (tree.tpe <:< listTreeType || tree.tpe <:< listListTreeType)) tree - else atPos(tree.pos)(loop(tree, n)) - } - val card = parseCardinality(tpe)._1 - if (card != NoDot) Some(reifyIterable(_, card)) else None - } + class ApplyHole(card: Cardinality, splicee: Tree) extends Hole { + val (strippedTpe, tpe): (Type, Type) = { + if (stripIterable(splicee.tpe)._1.value < card.value) cantSplice() + val (_, strippedTpe) = stripIterable(splicee.tpe, limit = Some(card)) + if (isBottomType(strippedTpe)) cantSplice() + else if (isNativeType(strippedTpe)) (strippedTpe, iterableTypeFromCard(card, strippedTpe)) + else if (isLiftableType(strippedTpe)) (strippedTpe, iterableTypeFromCard(card, treeType)) + else cantSplice() } - object NativeType extends HoleTypeExtractor { - def preprocessor(tpe: Type) = Some(identity) - def location(tpe: Type) = { - if (tpe <:< treeType) Some(TreeLocation(tpe)) - else if (tpe <:< nameType) Some(NameLocation) - else if (tpe <:< modsType) Some(ModsLocation) - else if (tpe <:< flagsType) Some(FlagsLocation) - else if (tpe <:< symbolType) Some(SymbolLocation) - else None - } + val tree = { + def inner(itpe: Type)(tree: Tree) = + if (isNativeType(itpe)) tree + else if (isLiftableType(itpe)) lifted(itpe)(tree) + else global.abort("unreachable") + if (card == NoDot) inner(strippedTpe)(splicee) + else iterated(card, strippedTpe, inner(strippedTpe))(splicee) } - object LiftableType extends HoleTypeExtractor { - def preprocessor(tpe: Type) = lifter(tpe) - def location(tpe: Type) = Some(TreeLocation(treeType)) + val pos = splicee.pos + + val cardinality = stripIterable(tpe)._1 + + protected def cantSplice(): Nothing = { + val (iterableCard, iterableType) = stripIterable(splicee.tpe) + val holeCardMsg = if (card != NoDot) s" with $card" else "" + val action = "splice " + splicee.tpe + holeCardMsg + val suggestCard = card != iterableCard || card != NoDot + val spliceeCardMsg = if (card != iterableCard && iterableCard != NoDot) s"using $iterableCard" else "omitting the dots" + val cardSuggestion = if (suggestCard) spliceeCardMsg else "" + val suggestLifting = (card == NoDot || iterableCard != NoDot) && !(iterableType <:< treeType) && !isLiftableType(iterableType) + val liftedTpe = if (card != NoDot) iterableType else splicee.tpe + val liftSuggestion = if (suggestLifting) s"providing an implicit instance of Liftable[$liftedTpe]" else "" + val advice = + if (isBottomType(iterableType)) "bottom type values often indicate programmer mistake" + else "consider " + List(cardSuggestion, liftSuggestion).filter(_ != "").mkString(" or ") + c.abort(splicee.pos, s"Can't $action, $advice") } - object IterableTreeType extends HoleTypeExtractor { - def preprocessor(tpe: Type) = iterator(tpe)(identity) - def location(tpe: Type) = { - val (card, elementTpe) = parseCardinality(tpe) - if (card != NoDot && elementTpe <:< treeType) Some(IterableLocation(card, TreeLocation(elementTpe))) - else None - } + protected def lifted(tpe: Type)(tree: Tree): Tree = { + val lifter = inferLiftable(tpe) + assert(lifter != EmptyTree, s"couldnt find a liftable for $tpe") + val lifted = Apply(lifter, List(tree)) + val targetType = Select(u, tpnme.Tree) + atPos(tree.pos)(TypeApply(Select(lifted, nme.asInstanceOf_), List(targetType))) } - object IterableLiftableType extends HoleTypeExtractor { - def preprocessor(tpe: Type) = { - val (_, elementTpe) = parseCardinality(tpe) - for { - lifter <- this.lifter(elementTpe) - iterator <- this.iterator(tpe)(lifter) - } yield iterator + protected def iterated(card: Cardinality, tpe: Type, elementTransform: Tree => Tree = identity)(tree: Tree): Tree = { + assert(card != NoDot) + def reifyIterable(tree: Tree, n: Cardinality): Tree = { + def loop(tree: Tree, n: Cardinality): Tree = + if (n == NoDot) elementTransform(tree) + else { + val x: TermName = c.freshName() + val wrapped = reifyIterable(Ident(x), n.pred) + val xToWrapped = Function(List(ValDef(Modifiers(PARAM), x, TypeTree(), EmptyTree)), wrapped) + Select(Apply(Select(tree, nme.map), List(xToWrapped)), nme.toList) + } + if (tree.tpe != null && (tree.tpe <:< listTreeType || tree.tpe <:< listListTreeType)) tree + else atPos(tree.pos)(loop(tree, n)) } - def location(tpe: Type) = Some(IterableLocation(cardinality(tpe), TreeLocation(treeType))) + reifyIterable(tree, card) } } - /** Hole encapsulates information about splices in quasiquotes. - * It packs together a cardinality of a splice, a splicee (possibly preprocessed) - * and the description of the location in Scala syntax where the splicee can be spliced. - * This is the third pillar of modularity in the quasiquote reifier. - */ - case class Hole(tree: Tree, location: Location, cardinality: Cardinality) - - object Hole { - def apply(splicee: Tree, holeCard: Cardinality): Hole = { - if (method == nme.unapply) return new Hole(splicee, UnknownLocation, holeCard) - val (spliceeCard, elementTpe) = parseCardinality(splicee.tpe) - def cantSplice() = { - val holeCardMsg = if (holeCard != NoDot) s" with $holeCard" else "" - val action = "splice " + splicee.tpe + holeCardMsg - val suggestCard = holeCard != spliceeCard || holeCard != NoDot - val spliceeCardMsg = if (holeCard != spliceeCard && spliceeCard != NoDot) s"using $spliceeCard" else "omitting the dots" - val cardSuggestion = if (suggestCard) spliceeCardMsg else "" - def canBeLifted(tpe: Type) = HoleType.LiftableType.unapply(tpe).nonEmpty - val suggestLifting = (holeCard == NoDot || spliceeCard != NoDot) && !(elementTpe <:< treeType) && !canBeLifted(elementTpe) - val liftedTpe = if (holeCard != NoDot) elementTpe else splicee.tpe - val liftSuggestion = if (suggestLifting) s"providing an implicit instance of Liftable[$liftedTpe]" else "" - val advice = List(cardSuggestion, liftSuggestion).filter(_ != "").mkString(" or ") - c.abort(splicee.pos, s"Can't $action, consider $advice") - } - val holeTpe = splicee.tpe match { - case _ if holeCard != spliceeCard => cantSplice() - case HoleType(holeTpe) => holeTpe - case _ => cantSplice() - } - holeTpe.makeHole(splicee) + class UnapplyHole(val cardinality: Cardinality, pat: Tree) extends Hole { + val (placeholderName, pos, tptopt) = pat match { + case Bind(pname, inner @ Bind(_, Typed(Ident(nme.WILDCARD), tpt))) => (pname, inner.pos, Some(tpt)) + case Bind(pname, inner @ Typed(Ident(nme.WILDCARD), tpt)) => (pname, inner.pos, Some(tpt)) + case Bind(pname, inner) => (pname, inner.pos, None) } + val treeNoUnlift = Bind(placeholderName, Ident(nme.WILDCARD)) + lazy val tree = + tptopt.map { tpt => + val TypeDef(_, _, _, typedTpt) = + try c.typeCheck(TypeDef(NoMods, TypeName("T"), Nil, tpt)) + catch { case TypecheckException(pos, msg) => c.abort(pos.asInstanceOf[c.Position], msg) } + val tpe = typedTpt.tpe + val (iterableCard, _) = stripIterable(tpe) + if (iterableCard.value < cardinality.value) + c.abort(pat.pos, s"Can't extract $tpe with $cardinality, consider using $iterableCard") + val (_, strippedTpe) = stripIterable(tpe, limit = Some(cardinality)) + if (strippedTpe <:< treeType) treeNoUnlift + else + unlifters.spawn(strippedTpe, cardinality).map { + Apply(_, treeNoUnlift :: Nil) + }.getOrElse { + c.abort(pat.pos, s"Can't find $unliftableType[$strippedTpe], consider providing it") + } + }.getOrElse { treeNoUnlift } } - def parseCardinality(tpe: Type): (Cardinality, Type) = { - if (tpe != null && isIterableType(tpe)) { - val (card, innerTpe) = parseCardinality(tpe.typeArguments.head) - (card.succ, innerTpe) - } else (NoDot, tpe) + /** Full support for unliftable implies that it's possible to interleave + * deconstruction with higher cardinality and unlifting of the values. + * In particular extraction of List[Tree] as List[T: Unliftable] requires + * helper extractors that would do the job: UnliftHelper1[T]. Similarly + * List[List[Tree]] needs UnliftHelper2[T]. + * + * See also "unlift list" tests in UnapplyProps.scala + */ + object unlifters { + private var records = List.empty[(Type, Cardinality)] + // Request an UnliftHelperN[T] where n == card and T == tpe. + // If card == 0 then helper is not needed and plain instance + // of unliftable is returned. + def spawn(tpe: Type, card: Cardinality): Option[Tree] = { + val unlifter = inferUnliftable(tpe) + if (unlifter == EmptyTree) None + else if (card == NoDot) Some(unlifter) + else { + val idx = records.indexWhere { p => p._1 =:= tpe && p._2 == card } + val resIdx = if (idx != -1) idx else { records +:= (tpe, card); records.length - 1} + Some(Ident(TermName(nme.QUASIQUOTE_UNLIFT_HELPER + resIdx))) + } + } + // Returns a list of vals that will defined required unlifters + def preamble(): List[Tree] = + records.zipWithIndex.map { case ((tpe, card), idx) => + val name = TermName(nme.QUASIQUOTE_UNLIFT_HELPER + idx) + val helperName = card match { case DotDot => nme.UnliftHelper1 case DotDotDot => nme.UnliftHelper2 } + val lifter = inferUnliftable(tpe) + assert(helperName.isTermName) + // q"val $name: $u.build.${helperName.toTypeName} = $u.build.$helperName($lifter)" + ValDef(NoMods, name, + AppliedTypeTree(Select(Select(u, nme.build), helperName.toTypeName), List(TypeTree(tpe))), + Apply(Select(Select(u, nme.build), helperName), lifter :: Nil)) + } } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala index 126c14ac81..6e6b617e5c 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala @@ -161,7 +161,12 @@ trait Parsers { self: Quasiquotes => } object TermParser extends Parser { - def entryPoint = { parser => gen.mkTreeOrBlock(parser.templateOrTopStatSeq()) } + def entryPoint = { parser => + parser.templateOrTopStatSeq() match { + case head :: Nil => Block(Nil, head) + case lst => gen.mkTreeOrBlock(lst) + } + } } object TypeParser extends Parser { diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala index 54be9123c7..bdb44ad9a2 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala @@ -13,6 +13,7 @@ import scala.collection.{immutable, mutable} trait Placeholders { self: Quasiquotes => import global._ import Cardinality._ + import universeTypes._ // Step 1: Transform Scala source with holes into vanilla Scala source @@ -32,13 +33,17 @@ trait Placeholders { self: Quasiquotes => def appendHole(tree: Tree, cardinality: Cardinality) = { val placeholderName = c.freshName(TermName(nme.QUASIQUOTE_PREFIX + sessionSuffix)) sb.append(placeholderName) - val holeTree = if (method == nme.unapply) Bind(placeholderName, Ident(nme.WILDCARD)) else tree - holeMap(placeholderName) = Hole(holeTree, cardinality) + val holeTree = + if (method != nme.unapply) tree + else Bind(placeholderName, tree) + holeMap(placeholderName) = Hole(cardinality, holeTree) } val iargs = method match { case nme.apply => args - case nme.unapply => List.fill(parts.length - 1)(EmptyTree) + case nme.unapply => + val (dummy @ Ident(nme.SELECTOR_DUMMY)) :: Nil = args + dummy.attachments.get[SubpatternsAttachment].get.patterns case _ => global.abort("unreachable") } @@ -78,9 +83,9 @@ trait Placeholders { self: Quasiquotes => trait HolePlaceholder { def matching: PartialFunction[Any, Name] - def unapply(scrutinee: Any): Option[(Tree, Location, Cardinality)] = { + def unapply(scrutinee: Any): Option[Hole] = { val name = matching.lift(scrutinee) - name.flatMap { holeMap.get(_).map { case Hole(repr, loc, card) => (repr, loc, card) } } + name.flatMap { holeMap.get(_) } } } @@ -128,44 +133,44 @@ trait Placeholders { self: Quasiquotes => } object SymbolPlaceholder { - def unapply(scrutinee: Any): Option[Tree] = scrutinee match { - case Placeholder(tree, SymbolLocation, _) => Some(tree) + def unapply(scrutinee: Any): Option[Hole] = scrutinee match { + case Placeholder(hole: ApplyHole) if hole.tpe <:< symbolType => Some(hole) case _ => None } } object CasePlaceholder { - def unapply(tree: Tree): Option[(Tree, Location, Cardinality)] = tree match { - case CaseDef(Apply(Ident(nme.QUASIQUOTE_CASE), List(Placeholder(tree, location, card))), EmptyTree, EmptyTree) => Some((tree, location, card)) + def unapply(tree: Tree): Option[Hole] = tree match { + case CaseDef(Apply(Ident(nme.QUASIQUOTE_CASE), List(Placeholder(hole))), EmptyTree, EmptyTree) => Some(hole) case _ => None } } object RefineStatPlaceholder { - def unapply(tree: Tree): Option[(Tree, Location, Cardinality)] = tree match { - case ValDef(_, Placeholder(tree, location, card), Ident(tpnme.QUASIQUOTE_REFINE_STAT), _) => Some((tree, location, card)) + def unapply(tree: Tree): Option[Hole] = tree match { + case ValDef(_, Placeholder(hole), Ident(tpnme.QUASIQUOTE_REFINE_STAT), _) => Some(hole) case _ => None } } object EarlyDefPlaceholder { - def unapply(tree: Tree): Option[(Tree, Location, Cardinality)] = tree match { - case ValDef(_, Placeholder(tree, location, card), Ident(tpnme.QUASIQUOTE_EARLY_DEF), _) => Some((tree, location, card)) + def unapply(tree: Tree): Option[Hole] = tree match { + case ValDef(_, Placeholder(hole), Ident(tpnme.QUASIQUOTE_EARLY_DEF), _) => Some(hole) case _ => None } } object PackageStatPlaceholder { - def unapply(tree: Tree): Option[(Tree, Location, Cardinality)] = tree match { - case ValDef(NoMods, Placeholder(tree, location, card), Ident(tpnme.QUASIQUOTE_PACKAGE_STAT), EmptyTree) => Some((tree, location, card)) + def unapply(tree: Tree): Option[Hole] = tree match { + case ValDef(NoMods, Placeholder(hole), Ident(tpnme.QUASIQUOTE_PACKAGE_STAT), EmptyTree) => Some(hole) case _ => None } } object ForEnumPlaceholder { - def unapply(tree: Tree): Option[(Tree, Location, Cardinality)] = tree match { - case build.SyntacticValFrom(Bind(Placeholder(tree, location, card), Ident(nme.WILDCARD)), Ident(nme.QUASIQUOTE_FOR_ENUM)) => - Some((tree, location, card)) + def unapply(tree: Tree): Option[Hole] = tree match { + case build.SyntacticValFrom(Bind(Placeholder(hole), Ident(nme.WILDCARD)), Ident(nme.QUASIQUOTE_FOR_ENUM)) => + Some(hole) case _ => None } } diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala index b28c85cfc2..6d7aafe266 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala @@ -13,7 +13,7 @@ trait Reifiers { self: Quasiquotes => import Cardinality._ import universeTypes._ - abstract class Reifier extends { + abstract class Reifier(val isReifyingExpressions: Boolean) extends { val global: self.global.type = self.global val universe = self.universe val reifee = EmptyTree @@ -22,7 +22,6 @@ trait Reifiers { self: Quasiquotes => } with ReflectReifier { lazy val typer = throw new UnsupportedOperationException - def isReifyingExpressions: Boolean def isReifyingPatterns: Boolean = !isReifyingExpressions def action = if (isReifyingExpressions) "splice" else "extract" def holesHaveTypes = isReifyingExpressions @@ -94,12 +93,12 @@ trait Reifiers { self: Quasiquotes => // cq"$tree if $guard => $succ" :: cq"_ => $fail" :: Nil CaseDef(tree, guard, succ) :: CaseDef(Ident(nme.WILDCARD), EmptyTree, fail) :: Nil } - // q"new { def unapply(tree: $AnyClass) = tree match { case ..$cases } }.unapply(..$args)" + // q"new { def unapply(tree: $AnyClass) = { ..${unlifters.preamble()}; tree match { case ..$cases } } }.unapply(..$args)" Apply( Select( SyntacticNew(Nil, Nil, noSelfType, List( DefDef(NoMods, nme.unapply, Nil, List(List(ValDef(NoMods, nme.tree, TypeTree(AnyClass.toType), EmptyTree))), TypeTree(), - Match(Ident(nme.tree), cases)))), + SyntacticBlock(unlifters.preamble() :+ Match(Ident(nme.tree), cases))))), nme.unapply), args) } @@ -107,7 +106,7 @@ trait Reifiers { self: Quasiquotes => def reifyFillingHoles(tree: Tree): Tree = { val reified = reifyTree(tree) holeMap.unused.foreach { hole => - c.abort(holeMap(hole).tree.pos, s"Don't know how to $action here") + c.abort(holeMap(hole).pos, s"Don't know how to $action here") } wrap(reified) } @@ -117,21 +116,27 @@ trait Reifiers { self: Quasiquotes => reifyTreeSyntactically(tree) def reifyTreePlaceholder(tree: Tree): Tree = tree match { - case Placeholder(tree, TreeLocation(_), _) if isReifyingExpressions => tree - case Placeholder(tree, _, NoDot) if isReifyingPatterns => tree - case Placeholder(tree, _, card @ Dot()) => c.abort(tree.pos, s"Can't $action with $card here") + case Placeholder(hole: ApplyHole) if hole.tpe <:< treeType => hole.tree + case Placeholder(Hole(tree, NoDot)) if isReifyingPatterns => tree + case Placeholder(hole @ Hole(_, card @ Dot())) => c.abort(hole.pos, s"Can't $action with $card here") case TuplePlaceholder(args) => reifyTuple(args) case TupleTypePlaceholder(args) => reifyTupleType(args) case FunctionTypePlaceholder(argtpes, restpe) => reifyFunctionType(argtpes, restpe) - case CasePlaceholder(tree, location, _) => reifyCase(tree, location) - case RefineStatPlaceholder(tree, _, _) => reifyRefineStat(tree) - case EarlyDefPlaceholder(tree, _, _) => reifyEarlyDef(tree) - case PackageStatPlaceholder(tree, _, _) => reifyPackageStat(tree) - case ForEnumPlaceholder(tree, _, _) => tree + case CasePlaceholder(hole) => hole.tree + case RefineStatPlaceholder(hole) => reifyRefineStat(hole) + case EarlyDefPlaceholder(hole) => reifyEarlyDef(hole) + case PackageStatPlaceholder(hole) => reifyPackageStat(hole) + // for enumerators are checked not during splicing but during + // desugaring of the for loop in SyntacticFor & SyntacticForYield + case ForEnumPlaceholder(hole) => hole.tree case _ => EmptyTree } override def reifyTreeSyntactically(tree: Tree) = tree match { + case RefTree(qual, SymbolPlaceholder(Hole(tree, _))) if isReifyingExpressions => + mirrorBuildCall(nme.RefTree, reify(qual), tree) + case This(SymbolPlaceholder(Hole(tree, _))) if isReifyingExpressions => + mirrorCall(nme.This, tree) case SyntacticTraitDef(mods, name, tparams, earlyDefs, parents, selfdef, body) => reifyBuildCall(nme.SyntacticTraitDef, mods, name, tparams, earlyDefs, parents, selfdef, body) case SyntacticClassDef(mods, name, tparams, constrmods, vparamss, earlyDefs, parents, selfdef, body) => @@ -161,17 +166,24 @@ trait Reifiers { self: Quasiquotes => reifyBuildCall(nme.SyntacticForYield, enums, body) case SyntacticAssign(lhs, rhs) => reifyBuildCall(nme.SyntacticAssign, lhs, rhs) - case SyntacticApplied(fun, List(args)) - if args.forall { case Placeholder(_, _, DotDotDot) => false case _ => true } => - reifyBuildCall(nme.SyntacticApply, fun, args) case SyntacticApplied(fun, argss) if argss.nonEmpty => reifyBuildCall(nme.SyntacticApplied, fun, argss) case SyntacticTypeApplied(fun, targs) if targs.nonEmpty => reifyBuildCall(nme.SyntacticTypeApplied, fun, targs) case SyntacticFunction(args, body) => reifyBuildCall(nme.SyntacticFunction, args, body) + case SyntacticIdent(name, isBackquoted) => + reifyBuildCall(nme.SyntacticIdent, name, isBackquoted) + case Block(Nil, Placeholder(Hole(tree, DotDot))) => + mirrorBuildCall(nme.SyntacticBlock, tree) + case Block(Nil, other) => + reifyTree(other) case Block(stats, last) => reifyBuildCall(nme.SyntacticBlock, stats :+ last) + case Try(block, catches, finalizer) => + reifyBuildCall(nme.SyntacticTry, block, catches, finalizer) + case Match(selector, cases) => + reifyBuildCall(nme.SyntacticMatch, selector, cases) // parser emits trees with scala package symbol to ensure // that some names hygienically point to various scala package // members; we need to preserve this symbol to preserve @@ -183,9 +195,10 @@ trait Reifiers { self: Quasiquotes => } override def reifyName(name: Name): Tree = name match { - case Placeholder(tree, location, _) => - if (holesHaveTypes && !(location.tpe <:< nameType)) c.abort(tree.pos, s"$nameType expected but ${location.tpe} found") - tree + case Placeholder(hole: ApplyHole) => + if (!(hole.tpe <:< nameType)) c.abort(hole.pos, s"$nameType expected but ${hole.tpe} found") + hole.tree + case Placeholder(hole: UnapplyHole) => hole.treeNoUnlift case FreshName(prefix) if prefix != nme.QUASIQUOTE_NAME_PREFIX => def fresh() = c.freshName[TermName](nme.QUASIQUOTE_NAME_PREFIX) def introduceName() = { val n = fresh(); nameMap(name) += n; n} @@ -196,15 +209,10 @@ trait Reifiers { self: Quasiquotes => super.reifyName(name) } - def reifyCase(tree: Tree, location: Location) = { - if (holesHaveTypes && !(location.tpe <:< caseDefType)) c.abort(tree.pos, s"$caseDefType expected but ${location.tpe} found") - tree - } - def reifyTuple(args: List[Tree]) = args match { case Nil => reify(Literal(Constant(()))) - case List(hole @ Placeholder(_, _, NoDot)) => reify(hole) - case List(Placeholder(_, _, _)) => reifyBuildCall(nme.SyntacticTuple, args) + case List(hole @ Placeholder(Hole(_, NoDot))) => reify(hole) + case List(Placeholder(_)) => reifyBuildCall(nme.SyntacticTuple, args) // in a case we only have one element tuple without // any cardinality annotations this means that this is // just an expression wrapped in parentheses @@ -214,8 +222,8 @@ trait Reifiers { self: Quasiquotes => def reifyTupleType(args: List[Tree]) = args match { case Nil => reify(Select(Ident(nme.scala_), tpnme.Unit)) - case List(hole @ Placeholder(_, _, NoDot)) => reify(hole) - case List(Placeholder(_, _, _)) => reifyBuildCall(nme.SyntacticTupleType, args) + case List(hole @ Placeholder(Hole(_, NoDot))) => reify(hole) + case List(Placeholder(_)) => reifyBuildCall(nme.SyntacticTupleType, args) case List(other) => reify(other) case _ => reifyBuildCall(nme.SyntacticTupleType, args) } @@ -223,13 +231,18 @@ trait Reifiers { self: Quasiquotes => def reifyFunctionType(argtpes: List[Tree], restpe: Tree) = reifyBuildCall(nme.SyntacticFunctionType, argtpes, restpe) - def reifyRefineStat(tree: Tree) = tree + def reifyConstructionCheck(name: TermName, hole: Hole) = hole match { + case _: UnapplyHole => hole.tree + case _: ApplyHole => mirrorBuildCall(name, hole.tree) + } + + def reifyRefineStat(hole: Hole) = reifyConstructionCheck(nme.mkRefineStat, hole) - def reifyEarlyDef(tree: Tree) = tree + def reifyEarlyDef(hole: Hole) = reifyConstructionCheck(nme.mkEarlyDef, hole) - def reifyAnnotation(tree: Tree) = tree + def reifyAnnotation(hole: Hole) = reifyConstructionCheck(nme.mkAnnotation, hole) - def reifyPackageStat(tree: Tree) = tree + def reifyPackageStat(hole: Hole) = reifyConstructionCheck(nme.mkPackageStat, hole) /** Splits list into a list of groups where subsequent elements are considered * similar by the corresponding function. @@ -262,7 +275,7 @@ trait Reifiers { self: Quasiquotes => * * reifyMultiCardinalityList(lst) { * // first we define patterns that extract high-cardinality holeMap (currently ..) - * case Placeholder(CorrespondsTo(tree, tpe)) if tpe <:< iterableTreeType => tree + * case Placeholder(IterableType(_, _)) => tree * } { * // in the end we define how single elements are reified, typically with default reify call * reify(_) @@ -281,21 +294,22 @@ trait Reifiers { self: Quasiquotes => * elements. */ override def reifyList(xs: List[Any]): Tree = reifyMultiCardinalityList(xs) { - case Placeholder(tree, _, DotDot) => tree - case CasePlaceholder(tree, _, DotDot) => tree - case RefineStatPlaceholder(tree, _, DotDot) => reifyRefineStat(tree) - case EarlyDefPlaceholder(tree, _, DotDot) => reifyEarlyDef(tree) - case PackageStatPlaceholder(tree, _, DotDot) => reifyPackageStat(tree) - case ForEnumPlaceholder(tree, _, DotDot) => tree - case List(Placeholder(tree, _, DotDotDot)) => tree + case Placeholder(Hole(tree, DotDot)) => tree + case CasePlaceholder(Hole(tree, DotDot)) => tree + case RefineStatPlaceholder(h @ Hole(_, DotDot)) => reifyRefineStat(h) + case EarlyDefPlaceholder(h @ Hole(_, DotDot)) => reifyEarlyDef(h) + case PackageStatPlaceholder(h @ Hole(_, DotDot)) => reifyPackageStat(h) + case ForEnumPlaceholder(Hole(tree, DotDot)) => tree + case List(Placeholder(Hole(tree, DotDotDot))) => tree } { reify(_) } def reifyAnnotList(annots: List[Tree]): Tree = reifyMultiCardinalityList(annots) { - case AnnotPlaceholder(tree, _, DotDot) => reifyAnnotation(tree) + case AnnotPlaceholder(h @ Hole(_, DotDot)) => reifyAnnotation(h) } { - case AnnotPlaceholder(tree, UnknownLocation | TreeLocation(_), NoDot) => reifyAnnotation(tree) + case AnnotPlaceholder(h: ApplyHole) if h.tpe <:< treeType => reifyAnnotation(h) + case AnnotPlaceholder(h: UnapplyHole) if h.cardinality == NoDot => reifyAnnotation(h) case other => reify(other) } @@ -321,78 +335,55 @@ trait Reifiers { self: Quasiquotes => override def mirrorBuildCall(name: TermName, args: Tree*): Tree = Apply(Select(Select(universe, nme.build), name), args.toList) - } - - class ApplyReifier extends Reifier { - def isReifyingExpressions = true - override def reifyTreeSyntactically(tree: Tree): Tree = tree match { - case RefTree(qual, SymbolPlaceholder(tree)) => - mirrorBuildCall(nme.RefTree, reify(qual), tree) - case This(SymbolPlaceholder(tree)) => - mirrorCall(nme.This, tree) - case _ => - super.reifyTreeSyntactically(tree) - } + override def scalaFactoryCall(name: String, args: Tree*): Tree = + call("scala." + name, args: _*) + } - override def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree): Tree = xs match { - case Nil => mkList(Nil) - case _ => + class ApplyReifier extends Reifier(isReifyingExpressions = true) { + def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree): Tree = + if (xs.isEmpty) mkList(Nil) + else { def reifyGroup(group: List[T]): Tree = group match { case List(elem) if fill.isDefinedAt(elem) => fill(elem) case elems => mkList(elems.map(fallback)) } val head :: tail = group(xs) { (a, b) => !fill.isDefinedAt(a) && !fill.isDefinedAt(b) } tail.foldLeft[Tree](reifyGroup(head)) { (tree, lst) => Apply(Select(tree, nme.PLUSPLUS), List(reifyGroup(lst))) } - } + } override def reifyModifiers(m: Modifiers) = if (m == NoMods) super.reifyModifiers(m) else { val (modsPlaceholders, annots) = m.annotations.partition { - case ModsPlaceholder(_, _, _) => true + case ModsPlaceholder(_) => true case _ => false } val (mods, flags) = modsPlaceholders.map { - case ModsPlaceholder(tree, location, card) => (tree, location) - }.partition { case (tree, location) => - location match { - case ModsLocation => true - case FlagsLocation => false - case _ => c.abort(tree.pos, s"$flagsType or $modsType expected but ${tree.tpe} found") - } + case ModsPlaceholder(hole: ApplyHole) => hole + }.partition { hole => + if (hole.tpe <:< modsType) true + else if (hole.tpe <:< flagsType) false + else c.abort(hole.pos, s"$flagsType or $modsType expected but ${hole.tpe} found") } mods match { - case (tree, _) :: Nil => - if (flags.nonEmpty) c.abort(flags(0)._1.pos, "Can't splice flags together with modifiers, consider merging flags into modifiers") - if (annots.nonEmpty) c.abort(tree.pos, "Can't splice modifiers together with annotations, consider merging annotations into modifiers") - ensureNoExplicitFlags(m, tree.pos) - tree - case _ :: (second, _) :: Nil => - c.abort(second.pos, "Can't splice multiple modifiers, consider merging them into a single modifiers instance") + case hole :: Nil => + if (flags.nonEmpty) c.abort(flags(0).pos, "Can't splice flags together with modifiers, consider merging flags into modifiers") + if (annots.nonEmpty) c.abort(hole.pos, "Can't splice modifiers together with annotations, consider merging annotations into modifiers") + ensureNoExplicitFlags(m, hole.pos) + hole.tree + case _ :: hole :: Nil => + c.abort(hole.pos, "Can't splice multiple modifiers, consider merging them into a single modifiers instance") case _ => val baseFlags = reifyFlags(m.flags) - val reifiedFlags = flags.foldLeft[Tree](baseFlags) { case (flag, (tree, _)) => Apply(Select(flag, nme.OR), List(tree)) } + val reifiedFlags = flags.foldLeft[Tree](baseFlags) { case (flag, hole) => Apply(Select(flag, nme.OR), List(hole.tree)) } mirrorFactoryCall(nme.Modifiers, reifiedFlags, reify(m.privateWithin), reifyAnnotList(annots)) } } - override def reifyRefineStat(tree: Tree) = mirrorBuildCall(nme.mkRefineStat, tree) - - override def reifyEarlyDef(tree: Tree) = mirrorBuildCall(nme.mkEarlyDef, tree) - - override def reifyAnnotation(tree: Tree) = mirrorBuildCall(nme.mkAnnotation, tree) - - override def reifyPackageStat(tree: Tree) = mirrorBuildCall(nme.mkPackageStat, tree) } - - class UnapplyReifier extends Reifier { - def isReifyingExpressions = false - - override def scalaFactoryCall(name: String, args: Tree*): Tree = - call("scala." + name, args: _*) - - override def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree) = xs match { + class UnapplyReifier extends Reifier(isReifyingExpressions = false) { + def reifyMultiCardinalityList[T](xs: List[T])(fill: PartialFunction[T, Tree])(fallback: T => Tree): Tree = xs match { case init :+ last if fill.isDefinedAt(last) => init.foldRight[Tree](fill(last)) { (el, rest) => val cons = Select(Select(Select(Ident(nme.scala_), nme.collection), nme.immutable), nme.CONS) @@ -405,14 +396,14 @@ trait Reifiers { self: Quasiquotes => override def reifyModifiers(m: Modifiers) = if (m == NoMods) super.reifyModifiers(m) else { - val mods = m.annotations.collect { case ModsPlaceholder(tree, _, _) => tree } + val mods = m.annotations.collect { case ModsPlaceholder(hole: UnapplyHole) => hole } mods match { - case tree :: Nil => - if (m.annotations.length != 1) c.abort(tree.pos, "Can't extract modifiers together with annotations, consider extracting just modifiers") - ensureNoExplicitFlags(m, tree.pos) - tree - case _ :: second :: rest => - c.abort(second.pos, "Can't extract multiple modifiers together, consider extracting a single modifiers instance") + case hole :: Nil => + if (m.annotations.length != 1) c.abort(hole.pos, "Can't extract modifiers together with annotations, consider extracting just modifiers") + ensureNoExplicitFlags(m, hole.pos) + hole.treeNoUnlift + case _ :: hole :: _ => + c.abort(hole.pos, "Can't extract multiple modifiers together, consider extracting a single modifiers instance") case Nil => mirrorFactoryCall(nme.Modifiers, reifyFlags(m.flags), reify(m.privateWithin), reifyAnnotList(m.annotations)) } diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala index cab5137a87..27f10ff00a 100644 --- a/src/interactive/scala/tools/nsc/interactive/Global.scala +++ b/src/interactive/scala/tools/nsc/interactive/Global.scala @@ -1018,7 +1018,11 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") val enclosing = new Members[ScopeMember] def addScopeMember(sym: Symbol, pre: Type, viaImport: Tree) = locals.add(sym, pre, implicitlyAdded = false) { (s, st) => - new ScopeMember(s, st, context.isAccessible(s, pre, superAccess = false), viaImport) + // imported val and var are always marked as inaccessible, but they could be accessed through their getters. SI-7995 + if (s.hasGetter) + new ScopeMember(s, st, context.isAccessible(s.getter, pre, superAccess = false), viaImport) + else + new ScopeMember(s, st, context.isAccessible(s, pre, superAccess = false), viaImport) } def localsToEnclosing() = { enclosing.addNonShadowed(locals) diff --git a/src/library/scala/MatchError.scala b/src/library/scala/MatchError.scala index 6ba7e833d3..9965bb19b5 100644 --- a/src/library/scala/MatchError.scala +++ b/src/library/scala/MatchError.scala @@ -23,9 +23,15 @@ final class MatchError(obj: Any) extends RuntimeException { /** There's no reason we need to call toString eagerly, * so defer it until getMessage is called. */ - private lazy val objString = + private lazy val objString = { + def ofClass = "of class " + obj.getClass.getName if (obj == null) "null" - else obj.toString() + " (of class " + obj.getClass.getName + ")" + else try { + obj.toString() + " (" + ofClass + ")" + } catch { + case _: Throwable => "an instance " + ofClass + } + } override def getMessage() = objString } diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala index df1484c4ab..264304db68 100644 --- a/src/library/scala/collection/immutable/Queue.scala +++ b/src/library/scala/collection/immutable/Queue.scala @@ -89,6 +89,16 @@ class Queue[+A] protected(protected val in: List[A], protected val out: List[A]) */ override def length = in.length + out.length + override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Queue[A], B, That]): That = bf match { + case _: Queue.GenericCanBuildFrom[_] => new Queue(in, elem :: out).asInstanceOf[That] + case _ => super.+:(elem)(bf) + } + + override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Queue[A], B, That]): That = bf match { + case _: Queue.GenericCanBuildFrom[_] => enqueue(elem).asInstanceOf[That] + case _ => super.:+(elem)(bf) + } + /** Creates a new queue with element added at the end * of the old queue. * @@ -118,7 +128,7 @@ class Queue[+A] protected(protected val in: List[A], protected val out: List[A]) case x :: xs => (x, new Queue(in, xs)) case _ => throw new NoSuchElementException("dequeue on empty queue") } - + /** Optionally retrieves the first element and a queue of the remaining elements. * * @return A tuple of the first element of the queue, and a new queue with this element removed. diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala index cf05aefe72..9baf3ec179 100644 --- a/src/reflect/scala/reflect/api/BuildUtils.scala +++ b/src/reflect/scala/reflect/api/BuildUtils.scala @@ -122,19 +122,12 @@ private[reflect] trait BuildUtils { self: Universe => def unapply(tree: Tree): Some[(Tree, List[List[Tree]])] } - val SyntacticApply: SyntacticApplyExtractor - - trait SyntacticApplyExtractor { - def apply(tree: Tree, args: List[Tree]): Tree - def unapply(tree: Tree): Some[(Tree, List[Tree])] - } - val SyntacticClassDef: SyntacticClassDefExtractor trait SyntacticClassDefExtractor { - def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], - constrMods: Modifiers, vparamss: List[List[ValDef]], earlyDefs: List[Tree], - parents: List[Tree], selfType: ValDef, body: List[Tree]): ClassDef + def apply(mods: Modifiers, name: TypeName, tparams: List[Tree], + constrMods: Modifiers, vparamss: List[List[Tree]], earlyDefs: List[Tree], + parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef def unapply(tree: Tree): Option[(Modifiers, TypeName, List[TypeDef], Modifiers, List[List[ValDef]], List[Tree], List[Tree], ValDef, List[Tree])] } @@ -142,8 +135,8 @@ private[reflect] trait BuildUtils { self: Universe => val SyntacticTraitDef: SyntacticTraitDefExtractor trait SyntacticTraitDefExtractor { - def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], - earlyDefs: List[Tree], parents: List[Tree], selfType: ValDef, body: List[Tree]): ClassDef + def apply(mods: Modifiers, name: TypeName, tparams: List[Tree], + earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef def unapply(tree: Tree): Option[(Modifiers, TypeName, List[TypeDef], List[Tree], List[Tree], ValDef, List[Tree])] } @@ -152,7 +145,7 @@ private[reflect] trait BuildUtils { self: Universe => trait SyntacticObjectDefExtractor { def apply(mods: Modifiers, name: TermName, earlyDefs: List[Tree], - parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree + parents: List[Tree], selfType: Tree, body: List[Tree]): Tree def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[Tree], ValDef, List[Tree])] } @@ -160,7 +153,7 @@ private[reflect] trait BuildUtils { self: Universe => trait SyntacticPackageObjectDefExtractor { def apply(name: TermName, earlyDefs: List[Tree], - parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree + parents: List[Tree], selfType: Tree, body: List[Tree]): Tree def unapply(tree: Tree): Option[(TermName, List[Tree], List[Tree], ValDef, List[Tree])] } @@ -182,7 +175,7 @@ private[reflect] trait BuildUtils { self: Universe => val SyntacticNew: SyntacticNewExtractor trait SyntacticNewExtractor { - def apply(earlyDefs: List[Tree], parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree + def apply(earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): Tree def unapply(tree: Tree): Option[(List[Tree], List[Tree], ValDef, List[Tree])] } @@ -196,7 +189,7 @@ private[reflect] trait BuildUtils { self: Universe => val SyntacticFunction: SyntacticFunctionExtractor trait SyntacticFunctionExtractor { - def apply(params: List[ValDef], body: Tree): Tree + def apply(params: List[Tree], body: Tree): Tree def unapply(tree: Tree): Option[(List[ValDef], Tree)] } @@ -204,7 +197,7 @@ private[reflect] trait BuildUtils { self: Universe => val SyntacticDefDef: SyntacticDefDefExtractor trait SyntacticDefDefExtractor { - def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef + def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[Tree]], tpt: Tree, rhs: Tree): DefDef def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[List[ValDef]], Tree, Tree)] } @@ -252,5 +245,33 @@ private[reflect] trait BuildUtils { self: Universe => def apply(enums: List[Tree], body: Tree): Tree def unapply(tree: Tree): Option[(List[Tree], Tree)] } + + def UnliftHelper1[T](unliftable: Unliftable[T]): UnliftHelper1[T] + trait UnliftHelper1[T] { + def unapply(lst: List[Tree]): Option[List[T]] + } + + def UnliftHelper2[T](unliftable: Unliftable[T]): UnliftHelper2[T] + trait UnliftHelper2[T] { + def unapply(lst: List[List[Tree]]): Option[List[List[T]]] + } + + val SyntacticMatch: SyntacticMatchExtractor + trait SyntacticMatchExtractor { + def apply(selector: Tree, cases: List[Tree]): Match + def unapply(tree: Match): Option[(Tree, List[CaseDef])] + } + + val SyntacticTry: SyntacticTryExtractor + trait SyntacticTryExtractor { + def apply(block: Tree, catches: List[Tree], finalizer: Tree): Try + def unapply(tree: Try): Option[(Tree, List[CaseDef], Tree)] + } + + val SyntacticIdent: SyntacticIdentExtractor + trait SyntacticIdentExtractor { + def apply(name: Name, isBackquoted: Boolean = false): Ident + def unapply(tree: Ident): Option[(Name, Boolean)] + } } } diff --git a/src/reflect/scala/reflect/api/Liftable.scala b/src/reflect/scala/reflect/api/Liftable.scala deleted file mode 100644 index 8f6fe066dd..0000000000 --- a/src/reflect/scala/reflect/api/Liftable.scala +++ /dev/null @@ -1,32 +0,0 @@ -package scala.reflect -package api - -trait Liftable[T] { - def apply(universe: api.Universe, value: T): universe.Tree -} - -object Liftable { - private class LiftableConstant[T] extends Liftable[T] { - def apply(universe: Universe, value: T): universe.Tree = - universe.Literal(universe.Constant(value)) - } - - implicit lazy val liftByte: Liftable[Byte] = new LiftableConstant[Byte] - implicit lazy val liftShort: Liftable[Short] = new LiftableConstant[Short] - implicit lazy val liftChar: Liftable[Char] = new LiftableConstant[Char] - implicit lazy val liftInt: Liftable[Int] = new LiftableConstant[Int] - implicit lazy val liftLong: Liftable[Long] = new LiftableConstant[Long] - implicit lazy val liftFloat: Liftable[Float] = new LiftableConstant[Float] - implicit lazy val liftDouble: Liftable[Double] = new LiftableConstant[Double] - implicit lazy val liftBoolean: Liftable[Boolean] = new LiftableConstant[Boolean] - implicit lazy val liftString: Liftable[String] = new LiftableConstant[String] - implicit lazy val liftUnit: Liftable[Unit] = new LiftableConstant[Unit] - - implicit lazy val liftScalaSymbol: Liftable[scala.Symbol] = new Liftable[scala.Symbol] { - def apply(universe: Universe, value: scala.Symbol): universe.Tree = { - import universe._ - val symbol = Select(Ident(TermName("scala")), TermName("Symbol")) - Apply(symbol, List(Literal(Constant(value.name)))) - } - } -} diff --git a/src/reflect/scala/reflect/api/StandardLiftables.scala b/src/reflect/scala/reflect/api/StandardLiftables.scala index ecea550225..57464459be 100644 --- a/src/reflect/scala/reflect/api/StandardLiftables.scala +++ b/src/reflect/scala/reflect/api/StandardLiftables.scala @@ -2,35 +2,225 @@ package scala.reflect package api trait StandardLiftables { self: Universe => + import build.{SyntacticTuple, ScalaDot} - private def requireSameUniverse[T](universe: Universe, tp: String, value: T) = - require(universe eq self, s"Can't lift $tp ${showRaw(value)} from universe ${showRaw(universe)} using lift$tp defined for ${showRaw(self)}.") + trait Liftable[T] { + def apply(value: T): Tree + } + + object Liftable { + def apply[T](f: T => Tree): Liftable[T] = + new Liftable[T] { def apply(value: T): Tree = f(value) } + + private def lift[T: Liftable](value: T): Tree = implicitly[Liftable[T]].apply(value) + private def selectScala(names: Name*) = names.tail.foldLeft(ScalaDot(names.head)) { Select(_, _) } + private def callScala(names: Name*)(args: List[Tree]) = Apply(selectScala(names: _*), args) + private def callCollection(name: Name)(args: List[Tree]) = callScala(nme.collection, nme.immutable, name)(args) + private def liftAsLiteral[T]: Liftable[T] = Liftable { v => Literal(Constant(v)) } + + implicit def liftByte[T <: Byte]: Liftable[T] = liftAsLiteral[T] + implicit def liftShort[T <: Short]: Liftable[T] = liftAsLiteral[T] + implicit def liftChar[T <: Char]: Liftable[T] = liftAsLiteral[T] + implicit def liftInt[T <: Int]: Liftable[T] = liftAsLiteral[T] + implicit def liftLong[T <: Long]: Liftable[T] = liftAsLiteral[T] + implicit def liftFloat[T <: Float]: Liftable[T] = liftAsLiteral[T] + implicit def liftDouble[T <: Double]: Liftable[T] = liftAsLiteral[T] + implicit def liftBoolean: Liftable[Boolean] = liftAsLiteral[Boolean] + implicit def liftUnit: Liftable[Unit] = liftAsLiteral[Unit] + implicit def liftString: Liftable[String] = liftAsLiteral[String] - implicit def liftExpr[T <: Expr[_]]: Liftable[T] = new Liftable[T] { - def apply(universe: Universe, value: T): universe.Tree = { - requireSameUniverse(universe, "Expr", value) - value.tree.asInstanceOf[universe.Tree] + implicit def liftScalaSymbol: Liftable[scala.Symbol] = Liftable { v => + callScala(nme.Symbol)(Literal(Constant(v.name)) :: Nil) } - } - implicit def liftType[T <: Type]: Liftable[T] = new Liftable[T] { - def apply(universe: Universe, value: T): universe.Tree = { - requireSameUniverse(universe, "Type", value) - universe.TypeTree(value.asInstanceOf[universe.Type]) + implicit def liftName[T <: Name]: Liftable[T] = Liftable { name => Ident(name) } + implicit def liftExpr[T <: Expr[_]]: Liftable[T] = Liftable { expr => expr.tree } + implicit def liftType[T <: Type]: Liftable[T] = Liftable { tpe => TypeTree(tpe) } + implicit def liftTypeTag[T <: WeakTypeTag[_]]: Liftable[T] = Liftable { ttag => TypeTree(ttag.tpe) } + implicit def liftConstant[T <: Constant]: Liftable[T] = Liftable { const => Literal(const) } + + implicit def liftArray[T: Liftable]: Liftable[Array[T]] = Liftable { arr => callScala(nme.Array)(arr.map(lift(_)).toList) } + implicit def liftVector[T: Liftable]: Liftable[Vector[T]] = Liftable { vect => callCollection(nme.Vector)(vect.map(lift(_)).toList) } + implicit def liftList[T: Liftable]: Liftable[List[T]] = Liftable { lst => callCollection(nme.List)(lst.map(lift(_))) } + implicit def liftMap[K: Liftable, V: Liftable]: Liftable[Map[K, V]] = Liftable { m => callCollection(nme.Map)(m.toList.map(lift(_))) } + implicit def liftSet[T: Liftable]: Liftable[Set[T]] = Liftable { s => callCollection(nme.Set)(s.toList.map(lift(_))) } + + implicit def liftOption[T: Liftable]: Liftable[Option[T]] = Liftable { + case Some(v) => callScala(nme.Some)(lift(v) :: Nil) + case None => selectScala(nme.None) + } + implicit def liftEither[L: Liftable, R: Liftable]: Liftable[Either[L, R]] = Liftable { + case Left(l) => callScala(nme.util, nme.Left)(lift(l) :: Nil) + case Right(r) => callScala(nme.util, nme.Right)(lift(r) :: Nil) } - } - implicit def liftTypeTag[T <: WeakTypeTag[_]]: Liftable[T] = new Liftable[T] { - def apply(universe: Universe, value: T): universe.Tree = { - requireSameUniverse(universe, "TypeTag", value) - universe.TypeTree(value.asInstanceOf[universe.WeakTypeTag[_]].tpe) + implicit def liftTuple1[T1](implicit liftT1: Liftable[T1]): Liftable[Tuple1[T1]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: Nil) + } + implicit def liftTuple2[T1, T2](implicit liftT1: Liftable[T1], liftT2: Liftable[T2]): Liftable[Tuple2[T1, T2]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: Nil) + } + implicit def liftTuple3[T1, T2, T3](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3]): Liftable[Tuple3[T1, T2, T3]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: Nil) + } + implicit def liftTuple4[T1, T2, T3, T4](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4]): Liftable[Tuple4[T1, T2, T3, T4]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: Nil) + } + implicit def liftTuple5[T1, T2, T3, T4, T5](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5]): Liftable[Tuple5[T1, T2, T3, T4, T5]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: Nil) + } + implicit def liftTuple6[T1, T2, T3, T4, T5, T6](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6]): Liftable[Tuple6[T1, T2, T3, T4, T5, T6]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: Nil) + } + implicit def liftTuple7[T1, T2, T3, T4, T5, T6, T7](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7]): Liftable[Tuple7[T1, T2, T3, T4, T5, T6, T7]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: Nil) + } + implicit def liftTuple8[T1, T2, T3, T4, T5, T6, T7, T8](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8]): Liftable[Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: Nil) + } + implicit def liftTuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9]): Liftable[Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: Nil) + } + implicit def liftTuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10]): Liftable[Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: Nil) + } + implicit def liftTuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11]): Liftable[Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: Nil) + } + implicit def liftTuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12]): Liftable[Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: Nil) + } + implicit def liftTuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13]): Liftable[Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: Nil) + } + implicit def liftTuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14]): Liftable[Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: Nil) + } + implicit def liftTuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15]): Liftable[Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: Nil) + } + implicit def liftTuple16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16]): Liftable[Tuple16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: Nil) + } + implicit def liftTuple17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16], liftT17: Liftable[T17]): Liftable[Tuple17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: liftT17(t._17) :: Nil) + } + implicit def liftTuple18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16], liftT17: Liftable[T17], liftT18: Liftable[T18]): Liftable[Tuple18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: liftT17(t._17) :: liftT18(t._18) :: Nil) + } + implicit def liftTuple19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16], liftT17: Liftable[T17], liftT18: Liftable[T18], liftT19: Liftable[T19]): Liftable[Tuple19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: liftT17(t._17) :: liftT18(t._18) :: liftT19(t._19) :: Nil) + } + implicit def liftTuple20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16], liftT17: Liftable[T17], liftT18: Liftable[T18], liftT19: Liftable[T19], liftT20: Liftable[T20]): Liftable[Tuple20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: liftT17(t._17) :: liftT18(t._18) :: liftT19(t._19) :: liftT20(t._20) :: Nil) + } + implicit def liftTuple21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16], liftT17: Liftable[T17], liftT18: Liftable[T18], liftT19: Liftable[T19], liftT20: Liftable[T20], liftT21: Liftable[T21]): Liftable[Tuple21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: liftT17(t._17) :: liftT18(t._18) :: liftT19(t._19) :: liftT20(t._20) :: liftT21(t._21) :: Nil) + } + implicit def liftTuple22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22](implicit liftT1: Liftable[T1], liftT2: Liftable[T2], liftT3: Liftable[T3], liftT4: Liftable[T4], liftT5: Liftable[T5], liftT6: Liftable[T6], liftT7: Liftable[T7], liftT8: Liftable[T8], liftT9: Liftable[T9], liftT10: Liftable[T10], liftT11: Liftable[T11], liftT12: Liftable[T12], liftT13: Liftable[T13], liftT14: Liftable[T14], liftT15: Liftable[T15], liftT16: Liftable[T16], liftT17: Liftable[T17], liftT18: Liftable[T18], liftT19: Liftable[T19], liftT20: Liftable[T20], liftT21: Liftable[T21], liftT22: Liftable[T22]): Liftable[Tuple22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22]] = Liftable { t => + SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: liftT3(t._3) :: liftT4(t._4) :: liftT5(t._5) :: liftT6(t._6) :: liftT7(t._7) :: liftT8(t._8) :: liftT9(t._9) :: liftT10(t._10) :: liftT11(t._11) :: liftT12(t._12) :: liftT13(t._13) :: liftT14(t._14) :: liftT15(t._15) :: liftT16(t._16) :: liftT17(t._17) :: liftT18(t._18) :: liftT19(t._19) :: liftT20(t._20) :: liftT21(t._21) :: liftT22(t._22) :: Nil) } } - implicit def liftConstant[T <: Constant]: Liftable[T] = new Liftable[T] { - def apply(universe: Universe, value: T): universe.Tree = { - requireSameUniverse(universe, "Constant", value) - universe.Literal(value.asInstanceOf[universe.Constant]) + trait Unliftable[T] { + def unapply(tree: Tree): Option[T] + } + + object Unliftable { + def apply[T](pf: PartialFunction[Tree, T]): Unliftable[T] = new Unliftable[T] { + def unapply(value: Tree): Option[T] = pf.lift(value) + } + + private def unliftPrimitive[Unboxed: ClassTag, Boxed: ClassTag] = Unliftable[Unboxed] { + case Literal(Constant(value)) + if value.getClass == implicitly[ClassTag[Boxed]].runtimeClass + || value.getClass == implicitly[ClassTag[Unboxed]].runtimeClass => + value.asInstanceOf[Unboxed] + } + implicit def unliftByte: Unliftable[Byte] = unliftPrimitive[Byte, java.lang.Byte] + implicit def unliftShort: Unliftable[Short] = unliftPrimitive[Short, java.lang.Short] + implicit def unliftChar: Unliftable[Char] = unliftPrimitive[Char, java.lang.Character] + implicit def unliftInt: Unliftable[Int] = unliftPrimitive[Int, java.lang.Integer] + implicit def unliftLong: Unliftable[Long] = unliftPrimitive[Long, java.lang.Long] + implicit def unliftFloat: Unliftable[Float] = unliftPrimitive[Float, java.lang.Float] + implicit def unliftDouble: Unliftable[Double] = unliftPrimitive[Double, java.lang.Double] + implicit def unliftBoolean: Unliftable[Boolean] = unliftPrimitive[Boolean, java.lang.Boolean] + implicit def unliftUnit: Unliftable[Unit] = unliftPrimitive[Unit, scala.runtime.BoxedUnit] + implicit def unliftString: Unliftable[String] = Unliftable { case Literal(Constant(s: String)) => s } + + implicit def unliftScalaSymbol: Unliftable[scala.Symbol] = Unliftable { + case Apply(ScalaDot(nme.Symbol), List(Literal(Constant(name: String)))) => scala.Symbol(name) + } + + implicit def unliftName[T <: Name : ClassTag]: Unliftable[T] = Unliftable[T] { case Ident(name: T) => name; case Bind(name: T, Ident(nme.WILDCARD)) => name} + implicit def unliftType: Unliftable[Type] = Unliftable[Type] { case tt: TypeTree if tt.tpe != null => tt.tpe } + implicit def unliftConstant: Unliftable[Constant] = Unliftable[Constant] { case Literal(const) => const } + + implicit def unliftTuple1[T1](implicit UnliftT1: Unliftable[T1]): Unliftable[Tuple1[T1]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: Nil) => Tuple1(v1) + } + implicit def unliftTuple2[T1, T2](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2]): Unliftable[Tuple2[T1, T2]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: Nil) => Tuple2(v1, v2) + } + implicit def unliftTuple3[T1, T2, T3](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3]): Unliftable[Tuple3[T1, T2, T3]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: Nil) => Tuple3(v1, v2, v3) + } + implicit def unliftTuple4[T1, T2, T3, T4](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4]): Unliftable[Tuple4[T1, T2, T3, T4]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: Nil) => Tuple4(v1, v2, v3, v4) + } + implicit def unliftTuple5[T1, T2, T3, T4, T5](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5]): Unliftable[Tuple5[T1, T2, T3, T4, T5]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: Nil) => Tuple5(v1, v2, v3, v4, v5) + } + implicit def unliftTuple6[T1, T2, T3, T4, T5, T6](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6]): Unliftable[Tuple6[T1, T2, T3, T4, T5, T6]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: Nil) => Tuple6(v1, v2, v3, v4, v5, v6) + } + implicit def unliftTuple7[T1, T2, T3, T4, T5, T6, T7](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7]): Unliftable[Tuple7[T1, T2, T3, T4, T5, T6, T7]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: Nil) => Tuple7(v1, v2, v3, v4, v5, v6, v7) + } + implicit def unliftTuple8[T1, T2, T3, T4, T5, T6, T7, T8](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8]): Unliftable[Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: Nil) => Tuple8(v1, v2, v3, v4, v5, v6, v7, v8) + } + implicit def unliftTuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9]): Unliftable[Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: Nil) => Tuple9(v1, v2, v3, v4, v5, v6, v7, v8, v9) + } + implicit def unliftTuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10]): Unliftable[Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: Nil) => Tuple10(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) + } + implicit def unliftTuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11]): Unliftable[Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: Nil) => Tuple11(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) + } + implicit def unliftTuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12]): Unliftable[Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: Nil) => Tuple12(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) + } + implicit def unliftTuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13]): Unliftable[Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: Nil) => Tuple13(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) + } + implicit def unliftTuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14]): Unliftable[Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: Nil) => Tuple14(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) + } + implicit def unliftTuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15]): Unliftable[Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: Nil) => Tuple15(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) + } + implicit def unliftTuple16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16]): Unliftable[Tuple16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: Nil) => Tuple16(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) + } + implicit def unliftTuple17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16], UnliftT17: Unliftable[T17]): Unliftable[Tuple17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: UnliftT17(v17) :: Nil) => Tuple17(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) + } + implicit def unliftTuple18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16], UnliftT17: Unliftable[T17], UnliftT18: Unliftable[T18]): Unliftable[Tuple18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: UnliftT17(v17) :: UnliftT18(v18) :: Nil) => Tuple18(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) + } + implicit def unliftTuple19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16], UnliftT17: Unliftable[T17], UnliftT18: Unliftable[T18], UnliftT19: Unliftable[T19]): Unliftable[Tuple19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: UnliftT17(v17) :: UnliftT18(v18) :: UnliftT19(v19) :: Nil) => Tuple19(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) + } + implicit def unliftTuple20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16], UnliftT17: Unliftable[T17], UnliftT18: Unliftable[T18], UnliftT19: Unliftable[T19], UnliftT20: Unliftable[T20]): Unliftable[Tuple20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: UnliftT17(v17) :: UnliftT18(v18) :: UnliftT19(v19) :: UnliftT20(v20) :: Nil) => Tuple20(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) + } + implicit def unliftTuple21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16], UnliftT17: Unliftable[T17], UnliftT18: Unliftable[T18], UnliftT19: Unliftable[T19], UnliftT20: Unliftable[T20], UnliftT21: Unliftable[T21]): Unliftable[Tuple21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: UnliftT17(v17) :: UnliftT18(v18) :: UnliftT19(v19) :: UnliftT20(v20) :: UnliftT21(v21) :: Nil) => Tuple21(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) + } + implicit def unliftTuple22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2], UnliftT3: Unliftable[T3], UnliftT4: Unliftable[T4], UnliftT5: Unliftable[T5], UnliftT6: Unliftable[T6], UnliftT7: Unliftable[T7], UnliftT8: Unliftable[T8], UnliftT9: Unliftable[T9], UnliftT10: Unliftable[T10], UnliftT11: Unliftable[T11], UnliftT12: Unliftable[T12], UnliftT13: Unliftable[T13], UnliftT14: Unliftable[T14], UnliftT15: Unliftable[T15], UnliftT16: Unliftable[T16], UnliftT17: Unliftable[T17], UnliftT18: Unliftable[T18], UnliftT19: Unliftable[T19], UnliftT20: Unliftable[T20], UnliftT21: Unliftable[T21], UnliftT22: Unliftable[T22]): Unliftable[Tuple22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22]] = Unliftable { + case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: UnliftT3(v3) :: UnliftT4(v4) :: UnliftT5(v5) :: UnliftT6(v6) :: UnliftT7(v7) :: UnliftT8(v8) :: UnliftT9(v9) :: UnliftT10(v10) :: UnliftT11(v11) :: UnliftT12(v12) :: UnliftT13(v13) :: UnliftT14(v14) :: UnliftT15(v15) :: UnliftT16(v16) :: UnliftT17(v17) :: UnliftT18(v18) :: UnliftT19(v19) :: UnliftT20(v20) :: UnliftT21(v21) :: UnliftT22(v22) :: Nil) => Tuple22(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) } } } diff --git a/src/reflect/scala/reflect/api/StandardNames.scala b/src/reflect/scala/reflect/api/StandardNames.scala index aec5f19fa0..4ea6ddc7f8 100644 --- a/src/reflect/scala/reflect/api/StandardNames.scala +++ b/src/reflect/scala/reflect/api/StandardNames.scala @@ -96,6 +96,20 @@ trait StandardNames { * of non-private vals and vars are renamed using `LOCAL_SUFFIX_STRING`. */ val LOCAL_SUFFIX_STRING: String + + protected[reflect] val Array: NameType + protected[reflect] val collection: NameType + protected[reflect] val immutable: NameType + protected[reflect] val Left: NameType + protected[reflect] val List: NameType + protected[reflect] val Map: NameType + protected[reflect] val None: NameType + protected[reflect] val Right: NameType + protected[reflect] val Set: NameType + protected[reflect] val Some: NameType + protected[reflect] val Symbol: NameType + protected[reflect] val util: NameType + protected[reflect] val Vector: NameType } /** Defines standard type names that can be accessed via the [[tpnme]] member. diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index 8fc1869dd2..13c2268227 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -71,12 +71,16 @@ trait BuildUtils { self: SymbolTable => def mkAnnotation(trees: List[Tree]): List[Tree] = trees.map(mkAnnotation) - def mkVparamss(argss: List[List[ValDef]]): List[List[ValDef]] = argss.map(_.map(mkParam)) + def mkVparamss(argss: List[List[Tree]]): List[List[ValDef]] = argss.map(_.map(mkParam)) - def mkParam(vd: ValDef): ValDef = { - var newmods = (vd.mods | PARAM) & (~DEFERRED) - if (vd.rhs.nonEmpty) newmods |= DEFAULTPARAM - copyValDef(vd)(mods = newmods) + def mkParam(tree: Tree): ValDef = tree match { + case vd: ValDef => + var newmods = (vd.mods | PARAM) & (~DEFERRED) + if (vd.rhs.nonEmpty) newmods |= DEFAULTPARAM + copyValDef(vd)(mods = newmods) + case _ => + throw new IllegalArgumentException(s"$tree is not valid represenation of function parameter, " + + """consider reformatting it into q"val $name: $T = $default" shape""") } def mkTparams(tparams: List[Tree]): List[TypeDef] = @@ -159,18 +163,11 @@ trait BuildUtils { self: SymbolTable => def apply(tree: Tree, argss: List[List[Tree]]): Tree = argss.foldLeft(tree) { (f, args) => Apply(f, args.map(treeInfo.assignmentToMaybeNamedArg)) } - def unapply(tree: Tree): Some[(Tree, List[List[Tree]])] = { - val treeInfo.Applied(fun, targs, argss) = tree - Some((SyntacticTypeApplied(fun, targs), argss)) - } - } - - object SyntacticApply extends SyntacticApplyExtractor { - def apply(tree: Tree, args: List[Tree]): Tree = SyntacticApplied(tree, List(args)) - - def unapply(tree: Tree): Some[(Tree, List[Tree])] = tree match { - case Apply(fun, args) => Some((fun, args)) - case other => Some((other, Nil)) + def unapply(tree: Tree): Some[(Tree, List[List[Tree]])] = tree match { + case UnApply(treeInfo.Unapplied(Select(fun, nme.unapply)), pats) => + Some((fun, pats :: Nil)) + case treeInfo.Applied(fun, targs, argss) => + Some((SyntacticTypeApplied(fun, targs), argss)) } } @@ -215,24 +212,41 @@ trait BuildUtils { self: SymbolTable => case Nil :: (tail @ ((head :: _) :: _)) if head.mods.isImplicit => tail case other => other } - // undo flag modifications by mergeing flag info from constructor args and fieldDefs + // undo flag modifications by merging flag info from constructor args and fieldDefs val modsMap = fieldDefs.map { case ValDef(mods, name, _, _) => name -> mods }.toMap - val vparamss = mmap(vparamssRestoredImplicits) { vd => - val originalMods = modsMap(vd.name) | (vd.mods.flags & DEFAULTPARAM) - atPos(vd.pos)(ValDef(originalMods, vd.name, vd.tpt, vd.rhs)) + def ctorArgsCorrespondToFields = vparamssRestoredImplicits.flatten.forall { vd => modsMap.contains(vd.name) } + if (!ctorArgsCorrespondToFields) None + else { + val vparamss = mmap(vparamssRestoredImplicits) { vd => + val originalMods = modsMap(vd.name) | (vd.mods.flags & DEFAULTPARAM) + atPos(vd.pos)(ValDef(originalMods, vd.name, vd.tpt, vd.rhs)) + } + result(ctorMods, vparamss, edefs, body) } - result(ctorMods, vparamss, edefs, body) } } } } + protected def mkSelfType(tree: Tree) = tree match { + case vd: ValDef => + require(vd.rhs.isEmpty, "self types must have empty right hand side") + copyValDef(vd)(mods = (vd.mods | PRIVATE) & (~DEFERRED)) + case _ => + throw new IllegalArgumentException(s"$tree is not a valid representation of self type, " + + """consider reformatting into q"val $self: $T" shape""") + } + object SyntacticClassDef extends SyntacticClassDefExtractor { - def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], - constrMods: Modifiers, vparamss: List[List[ValDef]], earlyDefs: List[Tree], - parents: List[Tree], selfType: ValDef, body: List[Tree]): ClassDef = { + def apply(mods: Modifiers, name: TypeName, tparams: List[Tree], + constrMods: Modifiers, vparamss: List[List[Tree]], earlyDefs: List[Tree], + parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef = { val extraFlags = PARAMACCESSOR | (if (mods.isCase) CASEACCESSOR else 0L) - val vparamss0 = vparamss.map { _.map { vd => copyValDef(vd)(mods = (vd.mods | extraFlags) & (~DEFERRED)) } } + val vparamss0 = vparamss.map { _.map { + case vd: ValDef => copyValDef(vd)(mods = (vd.mods | extraFlags) & (~DEFERRED)) + case tree => throw new IllegalArgumentException(s"$tree is not valid representation of class parameter, " + + """consider reformatting it into q"val $name: $T = $default" shape""") + } } val tparams0 = mkTparams(tparams) val parents0 = gen.mkParents(mods, if (mods.isCase) parents.filter { @@ -241,7 +255,8 @@ trait BuildUtils { self: SymbolTable => } else parents ) val body0 = earlyDefs ::: body - val templ = gen.mkTemplate(parents0, selfType, constrMods, vparamss0, body0) + val selfType0 = mkSelfType(selfType) + val templ = gen.mkTemplate(parents0, selfType0, constrMods, vparamss0, body0) gen.mkClassDef(mods, name, tparams0, templ) } @@ -256,10 +271,10 @@ trait BuildUtils { self: SymbolTable => } object SyntacticTraitDef extends SyntacticTraitDefExtractor { - def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], earlyDefs: List[Tree], - parents: List[Tree], selfType: ValDef, body: List[Tree]): ClassDef = { + def apply(mods: Modifiers, name: TypeName, tparams: List[Tree], earlyDefs: List[Tree], + parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef = { val mods0 = mods | TRAIT | ABSTRACT - val templ = gen.mkTemplate(parents, selfType, Modifiers(TRAIT), Nil, earlyDefs ::: body) + val templ = gen.mkTemplate(parents, mkSelfType(selfType), Modifiers(TRAIT), Nil, earlyDefs ::: body) gen.mkClassDef(mods0, name, mkTparams(tparams), templ) } @@ -274,8 +289,8 @@ trait BuildUtils { self: SymbolTable => object SyntacticObjectDef extends SyntacticObjectDefExtractor { def apply(mods: Modifiers, name: TermName, earlyDefs: List[Tree], - parents: List[Tree], selfType: ValDef, body: List[Tree]) = - ModuleDef(mods, name, gen.mkTemplate(parents, selfType, NoMods, Nil, earlyDefs ::: body)) + parents: List[Tree], selfType: Tree, body: List[Tree]) = + ModuleDef(mods, name, gen.mkTemplate(parents, mkSelfType(selfType), NoMods, Nil, earlyDefs ::: body)) def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[Tree], ValDef, List[Tree])] = tree match { case ModuleDef(mods, name, UnMkTemplate(parents, selfType, _, _, earlyDefs, body)) => @@ -287,7 +302,7 @@ trait BuildUtils { self: SymbolTable => object SyntacticPackageObjectDef extends SyntacticPackageObjectDefExtractor { def apply(name: TermName, earlyDefs: List[Tree], - parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree = + parents: List[Tree], selfType: Tree, body: List[Tree]): Tree = gen.mkPackageObject(SyntacticObjectDef(NoMods, name, earlyDefs, parents, selfType, body)) def unapply(tree: Tree): Option[(TermName, List[Tree], List[Tree], ValDef, List[Tree])] = tree match { @@ -377,11 +392,9 @@ trait BuildUtils { self: SymbolTable => } object SyntacticFunction extends SyntacticFunctionExtractor { - def apply(params: List[ValDef], body: Tree): Tree = { - val params0 = params.map { arg => - require(arg.rhs.isEmpty, "anonymous functions don't support default values") - mkParam(arg) - } + def apply(params: List[Tree], body: Tree): Tree = { + val params0 :: Nil = mkVparamss(params :: Nil) + require(params0.forall { _.rhs.isEmpty }, "anonymous functions don't support parameters with default values") Function(params0, body) } @@ -392,8 +405,8 @@ trait BuildUtils { self: SymbolTable => } object SyntacticNew extends SyntacticNewExtractor { - def apply(earlyDefs: List[Tree], parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree = - gen.mkNew(parents, selfType, earlyDefs ::: body, NoPosition, NoPosition) + def apply(earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): Tree = + gen.mkNew(parents, mkSelfType(selfType), earlyDefs ::: body, NoPosition, NoPosition) def unapply(tree: Tree): Option[(List[Tree], List[Tree], ValDef, List[Tree])] = tree match { case SyntacticApplied(Select(New(SyntacticTypeApplied(ident, targs)), nme.CONSTRUCTOR), argss) => @@ -407,7 +420,7 @@ trait BuildUtils { self: SymbolTable => } object SyntacticDefDef extends SyntacticDefDefExtractor { - def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef = + def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[Tree]], tpt: Tree, rhs: Tree): DefDef = DefDef(mods, name, mkTparams(tparams), mkVparamss(vparamss), tpt, rhs) def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[List[ValDef]], Tree, Tree)] = tree match { @@ -442,6 +455,20 @@ trait BuildUtils { self: SymbolTable => } } + def UnliftHelper1[T](unliftable: Unliftable[T]) = new UnliftHelper1[T] { + def unapply(lst: List[Tree]): Option[List[T]] = { + val unlifted = lst.flatMap { unliftable.unapply(_) } + if (unlifted.length == lst.length) Some(unlifted) else None + } + } + + def UnliftHelper2[T](unliftable: Unliftable[T]) = new UnliftHelper2[T] { + def unapply(lst: List[List[Tree]]): Option[List[List[T]]] = { + val unlifted = lst.map { l => l.flatMap { unliftable.unapply(_) } } + if (unlifted.flatten.length == lst.flatten.length) Some(unlifted) else None + } + } + object SyntacticValFrom extends SyntacticValFromExtractor { def apply(pat: Tree, rhs: Tree): Tree = gen.ValFrom(pat, gen.mkCheckIfRefutable(pat, rhs)) def unapply(tree: Tree): Option[(Tree, Tree)] = tree match { @@ -672,6 +699,30 @@ trait BuildUtils { self: SymbolTable => case annottee => Some(annottee) } } + + protected def mkCases(cases: List[Tree]): List[CaseDef] = cases.map { + case c: CaseDef => c + case tree => throw new IllegalArgumentException("$tree is not valid representation of pattern match case") + } + + object SyntacticMatch extends SyntacticMatchExtractor { + def apply(selector: Tree, cases: List[Tree]) = Match(selector, mkCases(cases)) + def unapply(tree: Match): Option[(Tree, List[CaseDef])] = Match.unapply(tree) + } + + object SyntacticTry extends SyntacticTryExtractor { + def apply(block: Tree, catches: List[Tree], finalizer: Tree) = Try(block, mkCases(catches), finalizer) + def unapply(tree: Try): Option[(Tree, List[CaseDef], Tree)] = Try.unapply(tree) + } + + object SyntacticIdent extends SyntacticIdentExtractor { + def apply(name: Name, isBackquoted: Boolean) = { + val id = self.Ident(name) + if (isBackquoted) id updateAttachment BackquotedIdentifierAttachment + id + } + def unapply(tree: Ident): Some[(Name, Boolean)] = Some((tree.name, tree.hasAttachment[BackquotedIdentifierAttachment.type])) + } } val build: BuildImpl = new BuildImpl diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 19f06894c8..1fe6f249b8 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -481,7 +481,6 @@ trait Definitions extends api.StandardDefinitions { lazy val TypeCreatorClass = getClassIfDefined("scala.reflect.api.TypeCreator") // defined in scala-reflect.jar, so we need to be careful lazy val TreeCreatorClass = getClassIfDefined("scala.reflect.api.TreeCreator") // defined in scala-reflect.jar, so we need to be careful - lazy val LiftableClass = getClassIfDefined("scala.reflect.api.Liftable") // defined in scala-reflect.jar, so we need to be careful lazy val BlackboxMacroClass = getClassIfDefined("scala.reflect.macros.BlackboxMacro") // defined in scala-reflect.jar, so we need to be careful def BlackboxMacroContextValue = BlackboxMacroClass.map(sym => getMemberValue(sym, nme.c)) @@ -1371,6 +1370,8 @@ trait Definitions extends api.StandardDefinitions { lazy val symbolType = universeMemberType(tpnme.Symbol) lazy val treeType = universeMemberType(tpnme.Tree) lazy val caseDefType = universeMemberType(tpnme.CaseDef) + lazy val liftableType = universeMemberType(tpnme.Liftable) + lazy val unliftableType = universeMemberType(tpnme.Unliftable) lazy val iterableTreeType = appliedType(IterableClass, treeType) lazy val listTreeType = appliedType(ListClass, treeType) lazy val listListTreeType = appliedType(ListClass, listTreeType) diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala index 46f241643b..09fd996f39 100644 --- a/src/reflect/scala/reflect/internal/StdAttachments.scala +++ b/src/reflect/scala/reflect/internal/StdAttachments.scala @@ -35,4 +35,7 @@ trait StdAttachments { /** Identifies trees are either result or intermidiate value of for loop desugaring. */ case object ForAttachment extends PlainAttachment + + /** Untyped list of subpatterns attached to selector dummy. */ + case class SubpatternsAttachment(patterns: List[Tree]) } diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index c26e815df1..5ad2b15e8c 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -124,8 +124,15 @@ trait StdNames { final val AnyRef: NameType = "AnyRef" final val Array: NameType = "Array" final val List: NameType = "List" + final val Left: NameType = "Left" + final val Right: NameType = "Right" + final val Vector: NameType = "Vector" final val Seq: NameType = "Seq" + final val Set: NameType = "Set" + final val Some: NameType = "Some" final val Symbol: NameType = "Symbol" + final val Map: NameType = "Map" + final val None: NameType = "None" final val WeakTypeTag: NameType = "WeakTypeTag" final val TypeTag : NameType = "TypeTag" final val Expr: NameType = "Expr" @@ -239,6 +246,8 @@ trait StdNames { final val Enum: NameType = "Enum" final val Group: NameType = "Group" final val implicitNotFound: NameType = "implicitNotFound" + final val Liftable: NameType = "Liftable" + final val Unliftable: NameType = "Unliftable" final val Name: NameType = "Name" final val Tree: NameType = "Tree" final val TermName: NameType = "TermName" @@ -328,6 +337,7 @@ trait StdNames { val QUASIQUOTE_TUPLE: NameType = "$quasiquote$tuple$" val QUASIQUOTE_CASE: NameType = "$quasiquote$case$" val QUASIQUOTE_FOR_ENUM: NameType = "$quasiquote$for$enum$" + val QUASIQUOTE_UNLIFT_HELPER: String = "$quasiquote$unlift$helper$" val MIXIN_CONSTRUCTOR: NameType = "$init$" val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$" val OUTER: NameType = "$outer" @@ -588,7 +598,6 @@ trait StdNames { val Select: NameType = "Select" val SelectFromTypeTree: NameType = "SelectFromTypeTree" val SyntacticApplied: NameType = "SyntacticApplied" - val SyntacticApply: NameType = "SyntacticApply" val SyntacticAssign: NameType = "SyntacticAssign" val SyntacticBlock: NameType = "SyntacticBlock" val SyntacticClassDef: NameType = "SyntacticClassDef" @@ -598,10 +607,13 @@ trait StdNames { val SyntacticForYield: NameType = "SyntacticForYield" val SyntacticFunction: NameType = "SyntacticFunction" val SyntacticFunctionType: NameType = "SyntacticFunctionType" - val SyntacticPackageObjectDef: NameType = "SyntacticPackageObjectDef" - val SyntacticObjectDef: NameType = "SyntacticObjectDef" + val SyntacticIdent: NameType = "SyntacticIdent" + val SyntacticMatch: NameType = "SyntacticMatch" val SyntacticNew: NameType = "SyntacticNew" + val SyntacticObjectDef: NameType = "SyntacticObjectDef" + val SyntacticPackageObjectDef: NameType = "SyntacticPackageObjectDef" val SyntacticTraitDef: NameType = "SyntacticTraitDef" + val SyntacticTry: NameType = "SyntacticTry" val SyntacticTuple: NameType = "SyntacticTuple" val SyntacticTupleType: NameType = "SyntacticTupleType" val SyntacticTypeApplied: NameType = "SyntacticTypeApplied" @@ -751,10 +763,13 @@ trait StdNames { val typedProductIterator: NameType = "typedProductIterator" val TypeName: NameType = "TypeName" val typeTagToManifest: NameType = "typeTagToManifest" + val util: NameType = "util" val unapply: NameType = "unapply" val unapplySeq: NameType = "unapplySeq" val unbox: NameType = "unbox" val universe: NameType = "universe" + val UnliftHelper1: NameType = "UnliftHelper1" + val UnliftHelper2: NameType = "UnliftHelper2" val update: NameType = "update" val updateDynamic: NameType = "updateDynamic" val value: NameType = "value" @@ -784,7 +799,7 @@ trait StdNames { final val STAR : NameType = "*" final val TILDE: NameType = "~" - final val isUnary: Set[Name] = Set(MINUS, PLUS, TILDE, BANG) + final val isUnary: Set[Name] = scala.collection.immutable.Set(MINUS, PLUS, TILDE, BANG) } // value-conversion methods @@ -837,8 +852,8 @@ trait StdNames { val UNARY_! = encode("unary_!") // Grouped here so Cleanup knows what tests to perform. - val CommonOpNames = Set[Name](OR, XOR, AND, EQ, NE) - val BooleanOpNames = Set[Name](ZOR, ZAND, UNARY_!) ++ CommonOpNames + val CommonOpNames = scala.collection.immutable.Set[Name](OR, XOR, AND, EQ, NE) + val BooleanOpNames = scala.collection.immutable.Set[Name](ZOR, ZAND, UNARY_!) ++ CommonOpNames val add: NameType = "add" val complement: NameType = "complement" diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 85bc3158f6..0dfcf06874 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -1379,6 +1379,13 @@ trait Symbols extends api.Symbols { self: SymbolTable => def hasRawInfo: Boolean = infos ne null def hasCompleteInfo = hasRawInfo && rawInfo.isComplete + // does not run adaptToNewRun, which is prone to trigger cycles (SI-8029) + // TODO: give this a better name if you understand the intent of the caller. + // Is it something to do with `reallyExists` or `isStale`? + final def rawInfoIsNoType: Boolean = { + hasRawInfo && (infos.info eq NoType) + } + /** Return info without checking for initialization or completing */ def rawInfo: Type = { var infos = this.infos @@ -2038,7 +2045,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Is this symbol defined in the same scope and compilation unit as `that` symbol? */ def isCoDefinedWith(that: Symbol) = ( - (this.rawInfo ne NoType) + !rawInfoIsNoType && (this.effectiveOwner == that.effectiveOwner) && ( !this.effectiveOwner.isPackageClass || (this.associatedFile eq NoAbstractFile) @@ -2475,10 +2482,14 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** String representation, including symbol's kind e.g., "class Foo", "method Bar". * If hasMeaninglessName is true, uses the owner's name to disambiguate identity. */ - override def toString: String = compose( - kindString, - if (hasMeaninglessName) owner.decodedName + idString else nameString - ) + override def toString: String = { + if (isPackageObjectOrClass && !settings.debug) + s"package object ${owner.decodedName}" + else compose( + kindString, + if (hasMeaninglessName) owner.decodedName + idString else nameString + ) + } /** String representation of location. */ diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index e483fa6ba8..99e6ae633f 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -3392,11 +3392,14 @@ trait Types /** Rebind symbol `sym` to an overriding member in type `pre`. */ private def rebind(pre: Type, sym: Symbol): Symbol = { if (!sym.isOverridableMember || sym.owner == pre.typeSymbol) sym - else pre.nonPrivateMember(sym.name).suchThat(sym => - // SI-7928 `isModuleNotMethod` is here to avoid crashing with overloaded module accessor and module symbols - // after refchecks eliminates a ModuleDef that implements and interface. - sym.isType || (!sym.isModuleNotMethod && sym.isStable && !sym.hasVolatileType) - ) orElse sym + else pre.nonPrivateMember(sym.name).suchThat { sym => + // SI-7928 `isModuleNotMethod` is here to avoid crashing with spuriously "overloaded" module accessor and module symbols. + // These appear after refchecks eliminates ModuleDefs that implement an interface. + // Here, we exclude the module symbol, which allows us to bind to the accessor. + // SI-8054 We must only do this after refchecks, otherwise we exclude the module symbol which does not yet have an accessor! + val isModuleWithAccessor = phase.refChecked && sym.isModuleNotMethod + sym.isType || (!isModuleWithAccessor && sym.isStable && !sym.hasVolatileType) + } orElse sym } /** Convert a `super` prefix to a this-type if `sym` is abstract or final. */ diff --git a/src/reflect/scala/reflect/internal/util/StringOps.scala b/src/reflect/scala/reflect/internal/util/StringOps.scala index 14f349f502..efb8126ff0 100644 --- a/src/reflect/scala/reflect/internal/util/StringOps.scala +++ b/src/reflect/scala/reflect/internal/util/StringOps.scala @@ -23,12 +23,16 @@ trait StringOps { def oempty(xs: String*) = xs filterNot (x => x == null || x == "") def ojoin(xs: String*): String = oempty(xs: _*) mkString " " def longestCommonPrefix(xs: List[String]): String = xs match { - case Nil => "" - case xs if xs contains "" => "" - case x :: xs => - val ch = x charAt 0 - if (xs exists (_.head != ch)) "" - else "" + ch + longestCommonPrefix(xs map (_ substring 1)) + case Nil => "" + case w :: Nil => w + case _ => + def lcp(ss: List[String]): String = { + val w :: ws = ss + if (w == "") "" + else if (ws exists (s => s == "" || (s charAt 0) != (w charAt 0))) "" + else w.substring(0, 1) + lcp(ss map (_ substring 1)) + } + lcp(xs) } /** Like String#trim, but trailing whitespace only. */ diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 344f7682c1..0f41506382 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -57,6 +57,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => this.CompoundTypeTreeOriginalAttachment this.BackquotedIdentifierAttachment this.ForAttachment + this.SubpatternsAttachment this.noPrint this.typeDebug // inaccessible: this.maxFree @@ -204,6 +205,8 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => this.TermName this.TypeName this.BooleanFlag + this.Liftable + this.Unliftable this.WeakTypeTag this.TypeTag this.Expr @@ -315,7 +318,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.MirrorClass definitions.TypeCreatorClass definitions.TreeCreatorClass - definitions.LiftableClass definitions.BlackboxMacroClass definitions.WhiteboxMacroClass definitions.BlackboxContextClass diff --git a/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala index 1b3d60d41a..53c7c82e89 100644 --- a/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala +++ b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala @@ -294,7 +294,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput // This is jline's entry point for completion. override def complete(buf: String, cursor: Int): Candidates = { verbosity = if (isConsecutiveTabs(buf, cursor)) verbosity + 1 else 0 - repldbg("\ncomplete(%s, %d) last = (%s, %d), verbosity: %s".format(buf, cursor, lastBuf, lastCursor, verbosity)) + repldbg(f"%ncomplete($buf, $cursor%d) last = ($lastBuf, $lastCursor%d), verbosity: $verbosity") // we don't try lower priority completions unless higher ones return no results. def tryCompletion(p: Parsed, completionFunction: Parsed => List[String]): Option[Candidates] = { @@ -307,8 +307,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput val advance = longestCommonPrefix(winners) lastCursor = p.position + advance.length lastBuf = (buf take p.position) + advance - repldbg("tryCompletion(%s, _) lastBuf = %s, lastCursor = %s, p.position = %s".format( - p, lastBuf, lastCursor, p.position)) + repldbg(s"tryCompletion($p, _) lastBuf = $lastBuf, lastCursor = $lastCursor, p.position = ${p.position}") p.position } diff --git a/src/swing/scala/swing/Publisher.scala b/src/swing/scala/swing/Publisher.scala index 96207de808..578ef71e09 100644 --- a/src/swing/scala/swing/Publisher.scala +++ b/src/swing/scala/swing/Publisher.scala @@ -44,7 +44,7 @@ trait Publisher extends Reactor { /** * Notify all registered reactions. */ - def publish(e: Event) { for (l <- listeners) l(e) } + def publish(e: Event) { for (l <- listeners) if (l.isDefinedAt(e)) l(e) } listenTo(this) } |