diff options
author | Paul Phillips <paulp@improving.org> | 2013-05-16 22:30:24 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-05-16 22:34:16 -0700 |
commit | 0c3ca2248d55eeeee2db6693e5fc46b9ba049eda (patch) | |
tree | 71686d0b99fc1d4a245ddb24efe50398b0c00c78 /src | |
parent | c663ecf8677eda3fe8c91170b614eb7166b18711 (diff) | |
parent | 13b4628aabb8e7a293a382dcab6db5848f672f94 (diff) | |
download | scala-0c3ca2248d55eeeee2db6693e5fc46b9ba049eda.tar.gz scala-0c3ca2248d55eeeee2db6693e5fc46b9ba049eda.tar.bz2 scala-0c3ca2248d55eeeee2db6693e5fc46b9ba049eda.zip |
Merge branch 'master' into HEAD
* master:
SI-7469 Remove @deprecated scala.util.logging
SI-3943 Test case for already-fixed Java interop bug
Fix formatting for couple of docs in the compiler
SI-7476 Add documentation to GenericTraversableTemplate
SI-7469 Remove @deprecated scala.util.parsing.ast
SI-7469 Remove @deprecated MurmurHash elements
SI-7469 Remove deprecated elements in s.u.parsing.combinator
SI-7469 Make @deprecated elems in scala.concurrent private[scala]
removes duplication in inferImplicitValue
SI-7047 fixes silent for c.inferImplicitXXX
SI-7167 implicit macros decide what is divergence
macroExpandAll is now triggered in all invocations of typed
SI-5923 instantiates targs in deferred macro applications
SI-6406 Restore deprecated API
SI-6039 Harden against irrelevant filesystem details
Limit unnecessary calls to Type#toString.
fix typo in comment
SI-7432 add testcases
SI-7432 Range.min should throw NoSuchElementException on empty range
AbstractFile.getDirectory does not return null when outDir is "."
Conflicts:
src/compiler/scala/tools/nsc/typechecker/Typers.scala
Diffstat (limited to 'src')
37 files changed, 223 insertions, 841 deletions
diff --git a/src/compiler/scala/reflect/macros/runtime/Aliases.scala b/src/compiler/scala/reflect/macros/runtime/Aliases.scala index ff870e728e..1c6703aeee 100644 --- a/src/compiler/scala/reflect/macros/runtime/Aliases.scala +++ b/src/compiler/scala/reflect/macros/runtime/Aliases.scala @@ -28,4 +28,8 @@ trait Aliases { override def typeTag[T](implicit ttag: TypeTag[T]) = ttag override def weakTypeOf[T](implicit attag: WeakTypeTag[T]): Type = attag.tpe override def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpe + + implicit class RichOpenImplicit(oi: universe.analyzer.OpenImplicit) { + def toImplicitCandidate = ImplicitCandidate(oi.info.pre, oi.info.sym, oi.pt, oi.tree) + } }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/macros/runtime/Enclosures.scala b/src/compiler/scala/reflect/macros/runtime/Enclosures.scala index 8fe0b09700..f3f92550de 100644 --- a/src/compiler/scala/reflect/macros/runtime/Enclosures.scala +++ b/src/compiler/scala/reflect/macros/runtime/Enclosures.scala @@ -21,16 +21,16 @@ trait Enclosures { // vals are eager to simplify debugging // after all we wouldn't save that much time by making them lazy - val macroApplication: Tree = expandee - def enclosingPackage: PackageDef = strictEnclosure[PackageDef] - val enclosingClass: Tree = lenientEnclosure[ImplDef] - def enclosingImpl: ImplDef = strictEnclosure[ImplDef] - def enclosingTemplate: Template = strictEnclosure[Template] - val enclosingImplicits: List[(Type, Tree)] = site.openImplicits - val enclosingMacros: List[Context] = this :: universe.analyzer.openMacros // include self - val enclosingMethod: Tree = lenientEnclosure[DefDef] - def enclosingDef: DefDef = strictEnclosure[DefDef] - val enclosingPosition: Position = if (enclPoses.isEmpty) NoPosition else enclPoses.head.pos - val enclosingUnit: CompilationUnit = universe.currentRun.currentUnit - val enclosingRun: Run = universe.currentRun + val macroApplication: Tree = expandee + def enclosingPackage: PackageDef = strictEnclosure[PackageDef] + val enclosingClass: Tree = lenientEnclosure[ImplDef] + def enclosingImpl: ImplDef = strictEnclosure[ImplDef] + def enclosingTemplate: Template = strictEnclosure[Template] + val enclosingImplicits: List[ImplicitCandidate] = site.openImplicits.map(_.toImplicitCandidate) + val enclosingMacros: List[Context] = this :: universe.analyzer.openMacros // include self + val enclosingMethod: Tree = lenientEnclosure[DefDef] + def enclosingDef: DefDef = strictEnclosure[DefDef] + val enclosingPosition: Position = if (enclPoses.isEmpty) NoPosition else enclPoses.head.pos + val enclosingUnit: CompilationUnit = universe.currentRun.currentUnit + val enclosingRun: Run = universe.currentRun } diff --git a/src/compiler/scala/reflect/macros/runtime/Typers.scala b/src/compiler/scala/reflect/macros/runtime/Typers.scala index 0ebcf43de0..f60b8dfeb4 100644 --- a/src/compiler/scala/reflect/macros/runtime/Typers.scala +++ b/src/compiler/scala/reflect/macros/runtime/Typers.scala @@ -8,7 +8,7 @@ trait Typers { def openMacros: List[Context] = this :: universe.analyzer.openMacros - def openImplicits: List[(Type, Tree)] = callsiteTyper.context.openImplicits + def openImplicits: List[ImplicitCandidate] = callsiteTyper.context.openImplicits.map(_.toImplicitCandidate) /** * @see [[scala.tools.reflect.ToolBox.typeCheck]] @@ -37,30 +37,13 @@ trait Typers { def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree = { macroLogVerbose("inferring implicit value of type %s, macros = %s".format(pt, !withMacrosDisabled)) - inferImplicit(universe.EmptyTree, pt, isView = false, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = pos) + universe.analyzer.inferImplicit(universe.EmptyTree, pt, false, callsiteTyper.context, silent, withMacrosDisabled, pos, (pos, msg) => throw TypecheckException(pos, msg)) } def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree = { macroLogVerbose("inferring implicit view from %s to %s for %s, macros = %s".format(from, to, tree, !withMacrosDisabled)) val viewTpe = universe.appliedType(universe.definitions.FunctionClass(1).toTypeConstructor, List(from, to)) - inferImplicit(tree, viewTpe, isView = true, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = pos) - } - - private def inferImplicit(tree: Tree, pt: Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: Position): Tree = { - import universe.analyzer.SearchResult - val context = callsiteTyper.context - val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _) - def wrapper (inference: => SearchResult) = wrapper1(inference) - wrapper(universe.analyzer.inferImplicit(tree, pt, reportAmbiguous = true, isView = isView, context = context, saveAmbiguousDivergent = !silent, pos = pos)) match { - case failure if failure.tree.isEmpty => - macroLogVerbose("implicit search has failed. to find out the reason, turn on -Xlog-implicits") - context.firstError match { - case Some(err) => throw new TypecheckException(err.errPos, err.errMsg) - case None => universe.EmptyTree - } - case success => - success.tree - } + universe.analyzer.inferImplicit(tree, viewTpe, true, callsiteTyper.context, silent, withMacrosDisabled, pos, (pos, msg) => throw TypecheckException(pos, msg)) } def resetAllAttrs(tree: Tree): Tree = universe.resetAllAttrs(tree) diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index 250feb69bf..98fb6bd0ef 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -234,10 +234,14 @@ abstract class SymbolLoaders { } } if (!root.isEmptyPackageClass) { + // Only enter packages which contain a class or a non-empty package for (pkg <- classpath.packages) { - enterPackage(root, pkg.name, new PackageLoader(pkg)) + if (pkg.isEmptyOfClassfiles) { + log(s"Discarding $root/$pkg as it contains no classfiles.") + } + else + enterPackage(root, pkg.name, new PackageLoader(pkg)) } - openPackageModule(root) } } diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index 9e867917f9..6f422fcc90 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -89,12 +89,12 @@ abstract class TailCalls extends Transform { */ class TailCallElimination(unit: CompilationUnit) extends Transformer { private def defaultReason = "it contains a recursive call not in tail position" - private val failPositions = perRunCaches.newMap[TailContext, Position]() - private val failReasons = perRunCaches.newMap[TailContext, String]() + private val failPositions = perRunCaches.newMap[TailContext, Position]() withDefault (_.methodPos) + private val failReasons = perRunCaches.newMap[TailContext, String]() withDefaultValue defaultReason private def tailrecFailure(ctx: TailContext) { - val method = ctx.method - val failReason = failReasons.getOrElse(ctx, defaultReason) - val failPos = failPositions.getOrElse(ctx, ctx.methodPos) + val method = ctx.method + val failReason = failReasons(ctx) + val failPos = failPositions(ctx) unit.error(failPos, s"could not optimize @tailrec annotated $method: $failReason") } @@ -237,7 +237,7 @@ abstract class TailCalls extends Transform { if (!ctx.isEligible) fail("it is neither private nor final so can be overridden") else if (!isRecursiveCall) { - if (receiverIsSuper) failHere("it contains a recursive call targeting supertype " + receiver.tpe) + if (receiverIsSuper) failHere("it contains a recursive call targeting a supertype") else failHere(defaultReason) } else if (!matchesTypeArgs) failHere("it is called recursively with different type arguments") diff --git a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala index 8be8b72130..63834ae51e 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala @@ -129,8 +129,9 @@ trait Interface extends ast.TreeDSL { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** Interface with user-defined match monad? - * if there's a `__match` in scope, we use this as the match strategy, assuming it conforms to MatchStrategy as defined below: + * if there's a <code>__match</code> in scope, we use this as the match strategy, assuming it conforms to MatchStrategy as defined below: + {{{ type Matcher[P[_], M[+_], A] = { def flatMap[B](f: P[A] => M[B]): M[B] def orElse[B >: A](alternative: => M[B]): M[B] @@ -144,12 +145,14 @@ trait Interface extends ast.TreeDSL { def one[T](x: P[T]): M[T] def guard[T](cond: P[Boolean], then: => P[T]): M[T] } + }}} * P and M are derived from one's signature (`def one[T](x: P[T]): M[T]`) - * if no `__match` is found, we assume the following implementation (and generate optimized code accordingly) + * if no <code>__match</code> is found, we assume the following implementation (and generate optimized code accordingly) + {{{ object __match extends MatchStrategy[({type Id[x] = x})#Id, Option] { def zero = None def one[T](x: T) = Some(x) @@ -157,6 +160,7 @@ trait Interface extends ast.TreeDSL { def guard[T](cond: Boolean, then: => T): Option[T] = if(cond) Some(then) else None def runOrElse[T, U](x: T)(f: T => Option[U]): U = f(x) getOrElse (throw new MatchError(x)) } + }}} */ trait MatchMonadInterface { diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 21c33aad0d..9794497667 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -213,7 +213,7 @@ trait Contexts { self: Analyzer => def isRootImport: Boolean = false /** Types for which implicit arguments are currently searched */ - var openImplicits: List[(Type,Tree)] = List() + var openImplicits: List[OpenImplicit] = List() /* For a named application block (`Tree`) the corresponding `NamedApplyInfo`. */ var namedApplyBlockInfo: Option[(Tree, NamedApplyInfo)] = None diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index f27c15180e..05db86635a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -100,6 +100,21 @@ trait Implicits { result } + /** A friendly wrapper over inferImplicit to be used in macro contexts and toolboxes. + */ + def inferImplicit(tree: Tree, pt: Type, isView: Boolean, context: Context, silent: Boolean, withMacrosDisabled: Boolean, pos: Position, onError: (Position, String) => Unit): Tree = { + val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _) + def wrapper(inference: => SearchResult) = wrapper1(inference) + val result = wrapper(inferImplicit(tree, pt, reportAmbiguous = true, isView = isView, context = context, saveAmbiguousDivergent = !silent, pos = pos)) + if (result.isFailure && !silent) { + val err = context.firstError + val errPos = err.map(_.errPos).getOrElse(pos) + val errMsg = err.map(_.errMsg).getOrElse("implicit search has failed. to find out the reason, turn on -Xlog-implicits") + onError(errPos, errMsg) + } + result.tree + } + /** Find all views from type `tp` (in which `tpars` are free) * * Note that the trees in the search results in the returned list share the same type variables. @@ -224,6 +239,10 @@ trait Implicits { ) } + /** A class which is used to track pending implicits to prevent infinite implicit searches. + */ + case class OpenImplicit(info: ImplicitInfo, pt: Type, tree: Tree) + /** A sentinel indicating no implicit was found */ val NoImplicitInfo = new ImplicitInfo(null, NoType, NoSymbol) { // equals used to be implemented in ImplicitInfo with an `if(this eq NoImplicitInfo)` @@ -407,13 +426,25 @@ trait Implicits { * @pre `info.tpe` does not contain an error */ private def typedImplicit(info: ImplicitInfo, ptChecked: Boolean, isLocal: Boolean): SearchResult = { - (context.openImplicits find { case (tp, tree1) => tree1.symbol == tree.symbol && dominates(pt, tp)}) match { + // SI-7167 let implicit macros decide what amounts for a divergent implicit search + // imagine a macro writer which wants to synthesize a complex implicit Complex[T] by making recursive calls to Complex[U] for its parts + // e.g. we have `class Foo(val bar: Bar)` and `class Bar(val x: Int)` + // then it's quite reasonable for the macro writer to synthesize Complex[Foo] by calling `inferImplicitValue(typeOf[Complex[Bar])` + // however if we didn't insert the `info.sym.isMacro` check here, then under some circumstances + // (e.g. as described here http://groups.google.com/group/scala-internals/browse_thread/thread/545462b377b0ac0a) + // `dominates` might decide that `Bar` dominates `Foo` and therefore a recursive implicit search should be prohibited + // now when we yield control of divergent expansions to the macro writer, what happens next? + // in the worst case, if the macro writer is careless, we'll get a StackOverflowException from repeated macro calls + // otherwise, the macro writer could check `c.openMacros` and `c.openImplicits` and do `c.abort` when expansions are deemed to be divergent + // upon receiving `c.abort` the typechecker will decide that the corresponding implicit search has failed + // which will fail the entire stack of implicit searches, producing a nice error message provided by the programmer + (context.openImplicits find { case OpenImplicit(info, tp, tree1) => !info.sym.isMacro && tree1.symbol == tree.symbol && dominates(pt, tp)}) match { case Some(pending) => //println("Pending implicit "+pending+" dominates "+pt+"/"+undetParams) //@MDEBUG DivergentSearchFailure case None => try { - context.openImplicits = (pt, tree) :: context.openImplicits + context.openImplicits = OpenImplicit(info, pt, tree) :: context.openImplicits // println(" "*context.openImplicits.length+"typed implicit "+info+" for "+pt) //@MDEBUG val result = typedImplicit0(info, ptChecked, isLocal) if (result.isDivergent) { diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 31cc8bd93c..2cd2f9380b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -396,7 +396,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { case Fallback(fallback) => typed1Expr(fallback) case Delayed(delayed) => - delayed + typer.instantiate(delayed, EXPRmode, WildcardType) case Skipped(skipped) => skipped case Failure(failure) => @@ -780,6 +780,29 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { expanded2 } } + override def onDelayed(delayed: Tree) = { + // If we've been delayed (i.e. bailed out of the expansion because of undetermined type params present in the expandee), + // then there are two possible situations we're in: + // 1) We're in POLYmode, when the typer tests the waters wrt type inference + // (e.g. as in typedArgToPoly in doTypedApply). + // 2) We're out of POLYmode, which means that the typer is out of tricks to infer our type + // (e.g. if we're an argument to a function call, then this means that no previous argument lists + // can determine our type variables for us). + // + // Situation #1 is okay for us, since there's no pressure. In POLYmode we're just verifying that + // there's nothing outrageously wrong with our undetermined type params (from what I understand!). + // + // Situation #2 requires measures to be taken. If we're in it, then noone's going to help us infer + // the undetermined type params. Therefore we need to do something ourselves or otherwise this + // expandee will forever remaing not expanded (see SI-5692). A traditional way out of this conundrum + // is to call `instantiate` and let the inferencer try to find the way out. It works for simple cases, + // but sometimes, if the inferencer lacks information, it will be forced to approximate. This prevents + // an important class of macros, fundep materializers, from working, which I perceive is a problem we need to solve. + // For details see SI-7470. + val shouldInstantiate = typer.context.undetparams.nonEmpty && !mode.inPolyMode + if (shouldInstantiate) typer.instantiatePossiblyExpectingUnit(delayed, mode, pt) + else delayed + } } expander(expandee) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 5cce4865cc..5b1f7160b7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1233,29 +1233,21 @@ trait Typers extends Adaptations with Tags { } if (tree.isType) adaptType() + else if (mode.typingExprNotFun && treeInfo.isMacroApplication(tree)) + macroExpandApply(this, tree, mode, pt) else if (mode.typingPatternFun) adaptConstrPattern() else if (shouldInsertApply(tree)) insertApply() else if (hasUndetsInMonoMode) { // (9) assert(!context.inTypeConstructor, context) //@M - if (mode.typingExprNotFun && pt.typeSymbol == UnitClass) - instantiateExpectingUnit(tree, mode) - else - instantiate(tree, mode, pt) + instantiatePossiblyExpectingUnit(tree, mode, pt) } else if (tree.tpe <:< pt) tree else fallbackAfterVanillaAdapt() } - def expandMacroAndVanillaAdapt(): Tree = { - if (mode.typingExprNotFun && treeInfo.isMacroApplication(tree)) { - val tree1 = macroExpandApply(this, tree, mode, pt) - if (tree == tree1) vanillaAdapt(tree) else tree1 - } - else vanillaAdapt(tree) - } // begin adapt tree.tpe match { @@ -1294,7 +1286,7 @@ trait Typers extends Adaptations with Tags { case mt: MethodType if mode.typingExprNotFunNotLhs && !hasUndetsInMonoMode && !treeInfo.isMacroApplicationOrBlock(tree) => instantiateToMethodType(mt) case _ => - expandMacroAndVanillaAdapt() + vanillaAdapt(tree) } } @@ -1315,6 +1307,13 @@ trait Typers extends Adaptations with Tags { } } + def instantiatePossiblyExpectingUnit(tree: Tree, mode: Mode, pt: Type): Tree = { + if (mode.typingExprNotFun && pt.typeSymbol == UnitClass) + instantiateExpectingUnit(tree, mode) + else + instantiate(tree, mode, pt) + } + private def isAdaptableWithView(qual: Tree) = { val qtpe = qual.tpe.widen ( !isPastTyper diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala index 7f9b81e1ec..536a281e6c 100644 --- a/src/compiler/scala/tools/nsc/util/ClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -211,6 +211,8 @@ abstract class ClassPath[T] { def validPackage(name: String) = (name != "META-INF") && (name != "") && (name.charAt(0) != '.') def validSourceFile(name: String) = endsScala(name) || endsJava(name) + def isEmptyOfClassfiles: Boolean = classes.isEmpty && packages.forall(_.isEmptyOfClassfiles) + /** * Find a ClassRep given a class name of the form "package.subpackage.ClassName". * Does not support nested classes on .NET diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 602982337f..59408096a3 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -180,16 +180,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => transformDuringTyper(tree, withImplicitViewsDisabled = false, withMacrosDisabled = withMacrosDisabled)( (currentTyper, tree) => { trace("inferring implicit %s (macros = %s): ".format(if (isView) "view" else "value", !withMacrosDisabled))(showAttributed(pt, true, true, settings.Yshowsymkinds.value)) - val context = currentTyper.context - val result = analyzer.inferImplicit(tree, pt, reportAmbiguous = true, isView = isView, context = context, saveAmbiguousDivergent = !silent, pos = pos) - if (result.isFailure) { - // @H: what's the point of tracing an empty tree? - trace("implicit search has failed. to find out the reason, turn on -Xlog-implicits: ")(result.tree) - context.firstError foreach { err => - throw ToolBoxError("reflective implicit search has failed: %s".format(err.errMsg)) - } - } - result.tree + analyzer.inferImplicit(tree, pt, isView, currentTyper.context, silent, withMacrosDisabled, pos, (pos, msg) => throw ToolBoxError(msg)) }) def compile(expr0: Tree): () => Any = { diff --git a/src/library/scala/collection/generic/GenericTraversableTemplate.scala b/src/library/scala/collection/generic/GenericTraversableTemplate.scala index adf4319bb8..cd48cd23f4 100644 --- a/src/library/scala/collection/generic/GenericTraversableTemplate.scala +++ b/src/library/scala/collection/generic/GenericTraversableTemplate.scala @@ -74,11 +74,20 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew /** Converts this $coll of pairs into two collections of the first and second * half of each pair. * + * {{{ + * val xs = $Coll( + * (1, "one"), + * (2, "two"), + * (3, "three")).unzip + * // xs == ($Coll(1, 2, 3), + * // $Coll(one, two, three)) + * }}} + * * @tparam A1 the type of the first half of the element pairs * @tparam A2 the type of the second half of the element pairs * @param asPair an implicit conversion which asserts that the element type * of this $coll is a pair. - * @return a pair ${coll}s, containing the first, respectively second + * @return a pair of ${coll}s, containing the first, respectively second * half of each element pair of this $coll. */ def unzip[A1, A2](implicit asPair: A => (A1, A2)): (CC[A1], CC[A2]) = { @@ -95,12 +104,22 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew /** Converts this $coll of triples into three collections of the first, second, * and third element of each triple. * + * {{{ + * val xs = $Coll( + * (1, "one", '1'), + * (2, "two", '2'), + * (3, "three", '3')).unzip3 + * // xs == ($Coll(1, 2, 3), + * // $Coll(one, two, three), + * // $Coll(1, 2, 3)) + * }}} + * * @tparam A1 the type of the first member of the element triples * @tparam A2 the type of the second member of the element triples * @tparam A3 the type of the third member of the element triples * @param asTriple an implicit conversion which asserts that the element type * of this $coll is a triple. - * @return a triple ${coll}s, containing the first, second, respectively + * @return a triple of ${coll}s, containing the first, second, respectively * third member of each element triple of this $coll. */ def unzip3[A1, A2, A3](implicit asTriple: A => (A1, A2, A3)): (CC[A1], CC[A2], CC[A3]) = { @@ -134,10 +153,16 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew * static type of $coll. For example: * * {{{ - * val xs = List(Set(1, 2, 3), Set(1, 2, 3)) + * val xs = List( + * Set(1, 2, 3), + * Set(1, 2, 3) + * ).flatten * // xs == List(1, 2, 3, 1, 2, 3) * - * val ys = Set(List(1, 2, 3), List(3, 2, 1)) + * val ys = Set( + * List(1, 2, 3), + * List(3, 2, 1) + * ).flatten * // ys == Set(1, 2, 3) * }}} */ @@ -151,6 +176,27 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew /** Transposes this $coll of traversable collections into * a $coll of ${coll}s. * + * The resulting collection's type will be guided by the + * static type of $coll. For example: + * + * {{{ + * val xs = List( + * Set(1, 2, 3), + * Set(4, 5, 6)).transpose + * // xs == List( + * // List(1, 4), + * // List(2, 5), + * // List(3, 6)) + * + * val ys = Vector( + * List(1, 2, 3), + * List(4, 5, 6)).transpose + * // ys == Vector( + * // Vector(1, 4), + * // Vector(2, 5), + * // Vector(3, 6)) + * }}} + * * @tparam B the type of the elements of each traversable collection. * @param asTraversable an implicit conversion which asserts that the * element type of this $coll is a `Traversable`. diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 4c424b31f4..09f8143b55 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -82,14 +82,14 @@ extends scala.collection.AbstractSeq[Int] override def min[A1 >: Int](implicit ord: Ordering[A1]): Int = if (ord eq Ordering.Int) { - if (step > 0) start + if (step > 0) head else last } else super.min(ord) override def max[A1 >: Int](implicit ord: Ordering[A1]): Int = if (ord eq Ordering.Int) { if (step > 0) last - else start + else head } else super.max(ord) protected def copy(start: Int, end: Int, step: Int): Range = new Range(start, end, step) diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala index 95b393dd0e..c444050e3d 100644 --- a/src/library/scala/concurrent/Future.scala +++ b/src/library/scala/concurrent/Future.scala @@ -71,7 +71,7 @@ import scala.reflect.ClassTag * val g = future { 3 } * val h = for { * x: Int <- f // returns Future(5) - * y: Int <- g // returns Future(5) + * y: Int <- g // returns Future(3) * } yield x + y * }}} * diff --git a/src/library/scala/concurrent/FutureTaskRunner.scala b/src/library/scala/concurrent/FutureTaskRunner.scala index 9e27ce65b9..089e67cedd 100644 --- a/src/library/scala/concurrent/FutureTaskRunner.scala +++ b/src/library/scala/concurrent/FutureTaskRunner.scala @@ -16,7 +16,7 @@ import scala.language.{implicitConversions, higherKinds} * @author Philipp Haller */ @deprecated("Use `ExecutionContext` instead.", "2.10.0") -trait FutureTaskRunner extends TaskRunner { +private[scala] trait FutureTaskRunner extends TaskRunner { /** The type of the futures that the underlying task runner supports. */ diff --git a/src/library/scala/concurrent/ManagedBlocker.scala b/src/library/scala/concurrent/ManagedBlocker.scala index 7b2966c663..b5a6e21893 100644 --- a/src/library/scala/concurrent/ManagedBlocker.scala +++ b/src/library/scala/concurrent/ManagedBlocker.scala @@ -13,7 +13,7 @@ package scala.concurrent * @author Philipp Haller */ @deprecated("Use `blocking` instead.", "2.10.0") -trait ManagedBlocker { +private[scala] trait ManagedBlocker { /** * Possibly blocks the current thread, for example waiting for diff --git a/src/library/scala/concurrent/SyncVar.scala b/src/library/scala/concurrent/SyncVar.scala index 6d25ffe19e..d22471ac0f 100644 --- a/src/library/scala/concurrent/SyncVar.scala +++ b/src/library/scala/concurrent/SyncVar.scala @@ -79,7 +79,7 @@ class SyncVar[A] { // whether or not the SyncVar is already defined. So, set has been // deprecated in order to eventually be able to make "setting" private @deprecated("Use `put` instead, as `set` is potentionally error-prone", "2.10.0") - def set(x: A): Unit = setVal(x) + private[scala] def set(x: A): Unit = setVal(x) /** Places a value in the SyncVar. If the SyncVar already has a stored value, * it waits until another thread takes it */ @@ -98,7 +98,7 @@ class SyncVar[A] { // whether or not the SyncVar is already defined. So, unset has been // deprecated in order to eventually be able to make "unsetting" private @deprecated("Use `take` instead, as `unset` is potentionally error-prone", "2.10.0") - def unset(): Unit = synchronized { + private[scala] def unset(): Unit = synchronized { isDefined = false value = None notifyAll() diff --git a/src/library/scala/concurrent/TaskRunner.scala b/src/library/scala/concurrent/TaskRunner.scala index a939a3f070..98c212d9fa 100644 --- a/src/library/scala/concurrent/TaskRunner.scala +++ b/src/library/scala/concurrent/TaskRunner.scala @@ -15,7 +15,7 @@ import scala.language.{higherKinds, implicitConversions} * @author Philipp Haller */ @deprecated("Use `ExecutionContext` instead.", "2.10.0") -trait TaskRunner { +private[scala] trait TaskRunner { type Task[T] diff --git a/src/library/scala/concurrent/ThreadPoolRunner.scala b/src/library/scala/concurrent/ThreadPoolRunner.scala index afa14ed2fa..7784681f71 100644 --- a/src/library/scala/concurrent/ThreadPoolRunner.scala +++ b/src/library/scala/concurrent/ThreadPoolRunner.scala @@ -17,7 +17,7 @@ import scala.language.implicitConversions * @author Philipp Haller */ @deprecated("Use `ExecutionContext` instead.", "2.10.0") -trait ThreadPoolRunner extends FutureTaskRunner { +private[scala] trait ThreadPoolRunner extends FutureTaskRunner { type Task[T] = Callable[T] with Runnable type Future[T] = java.util.concurrent.Future[T] diff --git a/src/library/scala/util/MurmurHash.scala b/src/library/scala/util/MurmurHash.scala deleted file mode 100644 index 7d1c57ef77..0000000000 --- a/src/library/scala/util/MurmurHash.scala +++ /dev/null @@ -1,198 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala -package util - -/** An implementation of Austin Appleby's MurmurHash 3.0 algorithm - * (32 bit version); reference: http://code.google.com/p/smhasher - * - * This is the hash used by collections and case classes (including - * tuples). - * - * @author Rex Kerr - * @version 2.9 - * @since 2.9 - */ - -import java.lang.Integer.{ rotateLeft => rotl } -import scala.collection.Iterator - -/** A class designed to generate well-distributed non-cryptographic - * hashes. It is designed to be passed to a collection's foreach method, - * or can take individual hash values with append. Its own hash code is - * set equal to the hash code of whatever it is hashing. - */ -@deprecated("Use the object MurmurHash3 instead.", "2.10.0") -class MurmurHash[@specialized(Int,Long,Float,Double) T](seed: Int) extends (T => Unit) { - import MurmurHash._ - - private var h = startHash(seed) - private var c = hiddenMagicA - private var k = hiddenMagicB - private var hashed = false - private var hashvalue = h - - /** Begin a new hash using the same seed. */ - def reset() { - h = startHash(seed) - c = hiddenMagicA - k = hiddenMagicB - hashed = false - } - - /** Incorporate the hash value of one item. */ - def apply(t: T) { - h = extendHash(h,t.##,c,k) - c = nextMagicA(c) - k = nextMagicB(k) - hashed = false - } - - /** Incorporate a known hash value. */ - def append(i: Int) { - h = extendHash(h,i,c,k) - c = nextMagicA(c) - k = nextMagicB(k) - hashed = false - } - - /** Retrieve the hash value */ - def hash = { - if (!hashed) { - hashvalue = finalizeHash(h) - hashed = true - } - hashvalue - } - override def hashCode = hash -} - -/** An object designed to generate well-distributed non-cryptographic - * hashes. It is designed to hash a collection of integers; along with - * the integers to hash, it generates two magic streams of integers to - * increase the distribution of repetitive input sequences. Thus, - * three methods need to be called at each step (to start and to - * incorporate a new integer) to update the values. Only one method - * needs to be called to finalize the hash. - */ -@deprecated("Use the object MurmurHash3 instead.", "2.10.0") -object MurmurHash { - // Magic values used for MurmurHash's 32 bit hash. - // Don't change these without consulting a hashing expert! - final private val visibleMagic = 0x971e137b - final private val hiddenMagicA = 0x95543787 - final private val hiddenMagicB = 0x2ad7eb25 - final private val visibleMixer = 0x52dce729 - final private val hiddenMixerA = 0x7b7d159c - final private val hiddenMixerB = 0x6bce6396 - final private val finalMixer1 = 0x85ebca6b - final private val finalMixer2 = 0xc2b2ae35 - - // Arbitrary values used for hashing certain classes - final private val seedString = 0xf7ca7fd2 - final private val seedArray = 0x3c074a61 - - /** The first 23 magic integers from the first stream are stored here */ - val storedMagicA = - Iterator.iterate(hiddenMagicA)(nextMagicA).take(23).toArray - - /** The first 23 magic integers from the second stream are stored here */ - val storedMagicB = - Iterator.iterate(hiddenMagicB)(nextMagicB).take(23).toArray - - /** Begin a new hash with a seed value. */ - def startHash(seed: Int) = seed ^ visibleMagic - - /** The initial magic integers in the first stream. */ - def startMagicA = hiddenMagicA - - /** The initial magic integer in the second stream. */ - def startMagicB = hiddenMagicB - - /** Incorporates a new value into an existing hash. - * - * @param hash the prior hash value - * @param value the new value to incorporate - * @param magicA a magic integer from the stream - * @param magicB a magic integer from a different stream - * @return the updated hash value - */ - def extendHash(hash: Int, value: Int, magicA: Int, magicB: Int) = { - (hash ^ rotl(value*magicA,11)*magicB)*3 + visibleMixer - } - - /** Given a magic integer from the first stream, compute the next */ - def nextMagicA(magicA: Int) = magicA*5 + hiddenMixerA - - /** Given a magic integer from the second stream, compute the next */ - def nextMagicB(magicB: Int) = magicB*5 + hiddenMixerB - - /** Once all hashes have been incorporated, this performs a final mixing */ - def finalizeHash(hash: Int) = { - var i = (hash ^ (hash>>>16)) - i *= finalMixer1 - i ^= (i >>> 13) - i *= finalMixer2 - i ^= (i >>> 16) - i - } - - /** Compute a high-quality hash of an array */ - def arrayHash[@specialized T](a: Array[T]) = { - var h = startHash(a.length * seedArray) - var c = hiddenMagicA - var k = hiddenMagicB - var j = 0 - while (j < a.length) { - h = extendHash(h, a(j).##, c, k) - c = nextMagicA(c) - k = nextMagicB(k) - j += 1 - } - finalizeHash(h) - } - - /** Compute a high-quality hash of a string */ - def stringHash(s: String) = { - var h = startHash(s.length * seedString) - var c = hiddenMagicA - var k = hiddenMagicB - var j = 0 - while (j+1 < s.length) { - val i = (s.charAt(j)<<16) + s.charAt(j+1) - h = extendHash(h,i,c,k) - c = nextMagicA(c) - k = nextMagicB(k) - j += 2 - } - if (j < s.length) h = extendHash(h,s.charAt(j),c,k) - finalizeHash(h) - } - - /** Compute a hash that is symmetric in its arguments--that is, - * where the order of appearance of elements does not matter. - * This is useful for hashing sets, for example. - */ - def symmetricHash[T](xs: scala.collection.TraversableOnce[T], seed: Int) = { - var a,b,n = 0 - var c = 1 - xs.seq.foreach(i => { - val h = i.## - a += h - b ^= h - if (h != 0) c *= h - n += 1 - }) - var h = startHash(seed * n) - h = extendHash(h, a, storedMagicA(0), storedMagicB(0)) - h = extendHash(h, b, storedMagicA(1), storedMagicB(1)) - h = extendHash(h, c, storedMagicA(2), storedMagicB(2)) - finalizeHash(h) - } -} diff --git a/src/library/scala/util/hashing/MurmurHash3.scala b/src/library/scala/util/hashing/MurmurHash3.scala index af0b12d8ba..c38d0f4da5 100644 --- a/src/library/scala/util/hashing/MurmurHash3.scala +++ b/src/library/scala/util/hashing/MurmurHash3.scala @@ -275,12 +275,4 @@ object MurmurHash3 extends MurmurHash3 { finalizeHash(h, n) } */ - - @deprecated("Use unorderedHash", "2.10.0") - final def symmetricHash[T](xs: scala.collection.GenTraversableOnce[T], seed: Int = symmetricSeed): Int = - unorderedHash(xs.seq, seed) - - @deprecated("Use orderedHash", "2.10.0") - final def traversableHash[T](xs: scala.collection.GenTraversableOnce[T], seed: Int = traversableSeed): Int = - orderedHash(xs.seq, seed) } diff --git a/src/library/scala/util/logging/ConsoleLogger.scala b/src/library/scala/util/logging/ConsoleLogger.scala deleted file mode 100644 index 5e3d957534..0000000000 --- a/src/library/scala/util/logging/ConsoleLogger.scala +++ /dev/null @@ -1,27 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala -package util.logging - -/** - * The trait `ConsoleLogger` is mixed into a concrete class who - * has class `Logged` among its base classes. - * - * @author Burak Emir - * @version 1.0 - */ -@deprecated("This class will be removed.", "2.10.0") -trait ConsoleLogger extends Logged { - - /** logs argument to Console using [[scala.Console.println]] - */ - override def log(msg: String): Unit = Console.println(msg) -} diff --git a/src/library/scala/util/logging/Logged.scala b/src/library/scala/util/logging/Logged.scala deleted file mode 100644 index 1fc12588db..0000000000 --- a/src/library/scala/util/logging/Logged.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala -package util.logging - -/** Mixing in Logged indicates that a class provides support for logging. - * - * For instance: - * {{{ - * // The developer of the library writes: - * class MyClass extends Logged { - * // do stuff, call log - * } - * - * // The user of the library instantiates: - * val x = new MyClass() with ConsoleLogger - * }}} - * and the logging is sent to the [[scala.util.logging.ConsoleLogger]] object. - */ -@deprecated("This class will be removed.", "2.10.0") -trait Logged { - /** This method should log the message given as argument somewhere - * as a side-effect. - * - * @param msg message to be logged - */ - def log(msg: String): Unit = {} -} diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala index 8d135ecf02..8eac0a2520 100644 --- a/src/library/scala/util/matching/Regex.scala +++ b/src/library/scala/util/matching/Regex.scala @@ -205,6 +205,20 @@ class Regex private[matching](val pattern: Pattern, groupNames: String*) extends else if (m.matcher.pattern == this.pattern) Some(1 to m.groupCount map m.group) else unapplySeq(m.matched) + /** Tries to match target. + * @param target The string to match + * @return The matches + */ + @deprecated("Extracting a match result from anything but a CharSequence or Match is deprecated", "2.11.0") + def unapplySeq(target: Any): Option[List[String]] = target match { + case s: CharSequence => + val m = pattern matcher s + if (runMatcher(m)) Some((1 to m.groupCount).toList map m.group) + else None + case m: Match => unapplySeq(m.matched) + case _ => None + } + // @see UnanchoredRegex protected def runMatcher(m: Matcher) = m.matches() diff --git a/src/library/scala/util/parsing/ast/AbstractSyntax.scala b/src/library/scala/util/parsing/ast/AbstractSyntax.scala deleted file mode 100644 index 3a2e990036..0000000000 --- a/src/library/scala/util/parsing/ast/AbstractSyntax.scala +++ /dev/null @@ -1,33 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala -package util.parsing.ast - -import scala.util.parsing.input.Positional - -/** This component provides the core abstractions for representing an Abstract Syntax Tree - * - * @author Adriaan Moors - */ -@deprecated("This class will be removed", "2.10.0") -trait AbstractSyntax { - /** The base class for elements of the abstract syntax tree. - */ - trait Element extends Positional - - /** The base class for elements in the AST that represent names [[scala.util.parsing.ast.Binders]]. - */ - trait NameElement extends Element { - def name: String - override def equals(that: Any): Boolean = that match { - case n: NameElement => n.name == name - case _ => false - } - } -} diff --git a/src/library/scala/util/parsing/ast/Binders.scala b/src/library/scala/util/parsing/ast/Binders.scala deleted file mode 100644 index 990c603ac5..0000000000 --- a/src/library/scala/util/parsing/ast/Binders.scala +++ /dev/null @@ -1,348 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala -package util.parsing.ast - -import scala.collection.AbstractIterable -import scala.collection.mutable -import scala.language.implicitConversions - -//DISCLAIMER: this code is highly experimental! - - // TODO: avoid clashes when substituting - // TODO: check binders in the same scope are distinct - -/** This trait provides the core ''Scrap-Your-Boilerplate'' abstractions as - * well as implementations for common datatypes. - * - * (Based on Ralf Lämmel's [[http://homepages.cwi.nl/~ralf/syb3/ SYB papers]].) - * - * @author Adriaan Moors - */ -@deprecated("This class will be removed", "2.10.0") -trait Mappable { - trait Mapper { def apply[T <% Mappable[T]](x: T): T } /* TODO: having type `Forall T. T => T` is too strict: - sometimes we want to allow `Forall T >: precision. T => T` for some type `precision`, so that, - beneath a certain threshold, we have some leeway. - concretely: to use gmap for substitution, we simply require that ast nodes are mapped to ast nodes, - we can't require that the type is preserved precisely: a Name may map to e.g., a MethodCall - */ - - trait Mappable[T] { - // one-layer traversal - def gmap(f: Mapper): T - // everywhere f x = f (gmapT (everywhere f) x) - def everywhere(f: Mapper)(implicit c: T => Mappable[T]): T = - f(gmap(new Mapper { def apply[T <% Mappable[T]](x: T): T = x.everywhere(f)})) - } - - implicit def StringIsMappable(s: String): Mappable[String] = - new Mappable[String] { - def gmap(f: Mapper): String = f(s) - } - - implicit def ListIsMappable[t <% Mappable[t]](xs: List[t]): Mappable[List[t]] = - new Mappable[List[t]] { - def gmap(f: Mapper): List[t] = (for (x <- xs) yield f(x)).toList - } - - implicit def OptionIsMappable[t <% Mappable[t]](xs: Option[t]): Mappable[Option[t]] = - new Mappable[Option[t]] { - def gmap(f: Mapper): Option[t] = (for (x <- xs) yield f(x)) - } -} - -/** This component provides functionality for enforcing variable binding - * during parse-time. - * - * When parsing simple languages, like Featherweight Scala, these parser - * combinators will fully enforce the binding discipline. When names are - * allowed to be left unqualified, these mechanisms would have to be - * complemented by an extra phase that resolves names that couldn't be - * resolved using the naive binding rules. (Maybe some machinery to - * model `implicit` binders (e.g., `this` and imported qualifiers) - * and selection on a binder will suffice?) - * - * @author Adriaan Moors - */ -trait Binders extends AbstractSyntax with Mappable { - /** A `Scope` keeps track of one or more syntactic elements that represent bound names. - * The elements it contains share the same scope and must all be distinct, as determined by `==`. - * - * A `NameElement` `n` in the AST that is conceptually bound by a `Scope` `s`, is replaced by a - * `BoundElement(n, s)`. (For example, in `val x:Int=x+1`, the first `x` is modelled by a - * Scope `s` that contains `x` and the second `x` is represented by a `BoundElement(x, s)`) - * The term (`x+1`) in scope of the Scope becomes an `UnderBinder(s, x+1)`. - * - * A `NameElement` `n` is bound by a `Scope` `s` if it is wrapped as a `BoundElement(n, s)`, and - * `s` has a binder element that is semantically equal (`equals` or `==`) to `n`. - * - * A `Scope` is represented textually by its list of binder elements, followed by the scope's `id`. - * For example: `[x, y]!1` represents the scope with `id` `1` and binder elements `x` and `y`. - * (`id` is solely used for this textual representation.) - */ - class Scope[binderType <: NameElement] extends AbstractIterable[binderType] with Iterable[binderType] { - private val substitution: mutable.Map[binderType, Element] = - new mutable.LinkedHashMap[binderType, Element] // a LinkedHashMap is ordered by insertion order -- important! - - /** Returns a unique number identifying this Scope (only used for representation purposes). */ - val id: Int = _Binder.genId - - /** Returns the binders in this scope. - * For a typical let-binding, this is just the variable name. For an argument list to a method body, - * there is one binder per formal argument. - */ - def iterator = substitution.keysIterator - - /** Return the `i`th binder in this scope. */ - def apply(i: Int): binderType = this.iterator.toList(i) - - /** Returns true if this container has a binder equal (as determined by `==`) to `b`. */ - def binds(b: binderType): Boolean = substitution.contains(b) - - def indexFor(b: binderType): Option[Int] = { - val iter = this.iterator.zipWithIndex - for ((that, count) <- iter) { - if (that.name == b.name) // TODO: why do name equals and structural equals differ? - return Some(count + 1) - else - Console.println(that+"!="+b) - } - - None - } - - /** Adds a new binder, for example the variable name in a local variable declaration. - * - * @param b a new binder that is distinct from the existing binders in this scope, - * and shares their conceptual scope. `canAddBinder(b)` must hold. - * @return `binds(b)` and `getElementFor(b) eq b` will hold. - */ - def addBinder(b: binderType) { substitution += Pair(b, b) } - - // TODO: strengthen this condition so that no binders may be added after this scope has been - // linked to its `UnderBinder` (i.e., while parsing, BoundElements may be added to the Scope - // associated to the UnderBinder, but after that, no changes are allowed, except for substitution)? - /** `canAddElement` indicates whether `b` may be added to this scope. - * - * - * @return true if `b` had not been added yet - */ - def canAddBinder(b: binderType): Boolean = !binds(b) - - /** ''Replaces'' the bound occurrences of a contained binder by their new value. - * The bound occurrences of `b` are not actually replaced; the scope keeps track - * of a substitution that maps every binder to its current value. Since a `BoundElement` is - * a proxy for the element it is bound to by its binder, `substitute` may thus be thought of - * as replacing all the bound occurrences of the given binder `b` by their new value `value`. - * - * @param b the binder whose bound occurrences should be given a new value. `binds(b)` must hold. - * @param value the new value for the bound occurrences of `b` - * @return `getElementFor(b) eq value` will hold. - */ - def substitute(b: binderType, value: Element): Unit = substitution(b) = value - - /** Returns the current value for the bound occurrences of `b`. - * - * @param b the contained binder whose current value should be returned `binds(b)` must hold. - */ - def getElementFor(b: binderType): Element = substitution(b) - - override def toString: String = this.iterator.toList.mkString("[",", ","]")+"!"+id // TODO show substitution? - - /** Returns a list of strings that represent the binder elements, each tagged with this scope's id. */ - def bindersToString: List[String] = (for(b <- this.iterator) yield b+"!"+id).toList - - /** Return a new inheriting scope that won't check whether binding is respected until the scope is left (so as to support forward references). */ - def allowForwardRef: Scope[binderType] = this // TODO - - /** Return a nested scope -- binders entered into it won't be visible in this scope, but if this scope allows forward references, - * the binding in the returned scope also does, and thus the check that all variables are bound is deferred until this scope is left. - */ - def nested: Scope[binderType] = this // TODO - - def onEnter() {} - def onLeft() {} - } - - - trait BindingSensitive { - // would like to specify this as one method: - // def alpha_==[t <: NameElement](other: BoundElement[t]): Boolean - // def alpha_==[bt <: binderType, st <: elementT](other: UnderBinder[bt, st]): Boolean - } - - /** A `BoundElement` is bound in a certain scope `scope`, which keeps track of the actual element that - * `el` stands for. - * - * A `BoundElement` is represented textually by its bound element, followed by its scope's `id`. - * For example: `x@1` represents the variable `x` that is bound in the scope with `id` `1`. - * - * @note `scope.binds(el)` holds before and after. - */ - case class BoundElement[boundElement <: NameElement](el: boundElement, scope: Scope[boundElement]) extends NameElement with Proxy with BindingSensitive { - /** Returns the element this `BoundElement` stands for. - * The `Proxy` trait ensures `equals`, `hashCode` and `toString` are forwarded to - * the result of this method. - */ - def self: Element = scope.getElementFor(el) - - def name = self.asInstanceOf[NameElement].name // TODO: this is only safe when substituted to a NameElement, which certainly isn't required -- I want dynamic inheritance! :) - - // decorate element's representation with the id of the scope it's bound in - override def toString: String = super.toString+"@"+scope.id - - def alpha_==[t <: NameElement](other: BoundElement[t]): Boolean = scope.indexFor(el) == other.scope.indexFor(other.el) - } - - /** A variable that escaped its scope (i.e., a free variable) -- we don't deal very well with these yet. */ - class UnboundElement[N <: NameElement](private val el: N) extends NameElement { - def name = el.name+"@??" - } - - // this is useless, as Element is a supertype of BoundElement --> the coercion will never be inferred - // if we knew a more specific type for the element that the bound element represents, this could make sense - // implicit def BoundElementProxy[t <: NameElement](e: BoundElement[t]): Element = e.self - - /** Represents an element with variables that are bound in a certain scope. */ - class UnderBinder[binderType <: NameElement, elementT <% Mappable[elementT]](val scope: Scope[binderType], private[Binders] val element: elementT) extends Element with BindingSensitive { - override def toString: String = "(" + scope.toString + ") in { "+element.toString+" }" - - /** Alpha-equivalence -- TODO - * Returns true if the `element` of the `other` `UnderBinder` is equal to this `element` up to alpha-conversion. - * - * That is, regular equality is used for all elements but `BoundElement`s: such an element is - * equal to a `BoundElement` in `other` if their binders are equal. Binders are equal if they - * are at the same index in their respective scope. - * - * Example: - * {{{ - * UnderBinder([x, y]!1, x@1) alpha_== UnderBinder([a, b]!2, a@2) - * ! (UnderBinder([x, y]!1, y@1) alpha_== UnderBinder([a, b]!2, a@2)) - * }}} - */ - /*def alpha_==[bt <: binderType, st <: elementT](other: UnderBinder[bt, st]): Boolean = { - var result = true - - // TODO: generic zip or gmap2 - element.gmap2(other.element, new Mapper2 { - def apply[s <% Mappable[s], t <% Mappable[t]](x :{s, t}): {s, t} = x match { - case {be1: BoundElement[_], be2: BoundElement[_]} => result == result && be1.alpha_==(be2) // monadic gmap (cheating using state directly) - case {ub1: UnderBinder[_, _], ub2: UnderBinder[_, _]} => result == result && be1.alpha_==(be2) - case {a, b} => result == result && a.equals(b) - }; x - }) - }*/ - - def cloneElementWithSubst(subst: Map[NameElement, NameElement]) = element.gmap(new Mapper { def apply[t <% Mappable[t]](x :t): t = x match{ - case substable: NameElement if subst.contains(substable) => subst.get(substable).asInstanceOf[t] // TODO: wrong... substitution is not (necessarily) the identity function - //Console.println("substed: "+substable+"-> "+subst.get(substable)+")"); - case x => x // Console.println("subst: "+x+"(keys: "+subst.keys+")");x - }}) - - // TODO - def cloneElementNoBoundElements = element.gmap(new Mapper { def apply[t <% Mappable[t]](x :t): t = x match{ - case BoundElement(el, _) => new UnboundElement(el).asInstanceOf[t] // TODO: precision stuff - case x => x - }}) - - def extract: elementT = cloneElementNoBoundElements - def extract(subst: Map[NameElement, NameElement]): elementT = cloneElementWithSubst(subst) - - /** Get a string representation of element, normally we don't allow direct access to element, but just getting a string representation is ok. */ - def elementToString: String = element.toString - } - - //SYB type class instances - implicit def UnderBinderIsMappable[bt <: NameElement <% Mappable[bt], st <% Mappable[st]](ub: UnderBinder[bt, st]): Mappable[UnderBinder[bt, st]] = - new Mappable[UnderBinder[bt, st]] { - def gmap(f: Mapper): UnderBinder[bt, st] = UnderBinder(f(ub.scope), f(ub.element)) - } - - implicit def ScopeIsMappable[bt <: NameElement <% Mappable[bt]](scope: Scope[bt]): Mappable[Scope[bt]] = - new Mappable[Scope[bt]] { - def gmap(f: Mapper): Scope[bt] = { val newScope = new Scope[bt]() - for(b <- scope) newScope.addBinder(f(b)) - newScope - } - } - - implicit def NameElementIsMappable(self: NameElement): Mappable[NameElement] = new Mappable[NameElement] { - def gmap(f: Mapper): NameElement = self match { - case BoundElement(el, scope) => BoundElement(f(el), f(scope)) - case _ => UserNameElementIsMappable(self).gmap(f) - } - } - - def UserNameElementIsMappable[t <: NameElement](self: t): Mappable[t] - - object UnderBinder { - def apply[binderType <: NameElement, elementT <% Mappable[elementT]](scope: Scope[binderType], element: elementT) = new UnderBinder(scope, element) - def unit[bt <: NameElement, elementT <% Mappable[elementT]](x: elementT) = UnderBinder(new Scope[bt](), x) - } - - /** If a list of `UnderBinder`s all have the same scope, they can be turned in to an `UnderBinder` - * containing a list of the elements in the original `UnderBinder`. - * - * The name `sequence` comes from the fact that this method's type is equal to the type of monadic sequence. - * - * @note `!orig.isEmpty` implies `orig.forall(ub => ub.scope eq orig(0).scope)` - * - */ - def sequence[bt <: NameElement, st <% Mappable[st]](orig: List[UnderBinder[bt, st]]): UnderBinder[bt, List[st]] = - if(orig.isEmpty) UnderBinder.unit(Nil) - else UnderBinder(orig(0).scope, orig.map(_.element)) - - // couldn't come up with a better name... - def unsequence[bt <: NameElement, st <% Mappable[st]](orig: UnderBinder[bt, List[st]]): List[UnderBinder[bt, st]] = - orig.element.map(sc => UnderBinder(orig.scope, sc)) - - //TODO: more documentation - /** An environment that maps a `NameElement` to the scope in which it is bound. - * This can be used to model scoping during parsing. - * - * @note This class uses similar techniques as described by ''Burak Emir'' in - * [[http://library.epfl.ch/theses/?nr=3899 Object-oriented pattern matching]], - * but uses `==` instead of `eq`, thus types can't be unified in general. - */ - abstract class BinderEnv { - def apply[A <: NameElement](v: A): Option[Scope[A]] - def extend[a <: NameElement](v : a, x : Scope[a]) = new BinderEnv { - def apply[b <: NameElement](w : b): Option[Scope[b]] = - if(w == v) Some(x.asInstanceOf[Scope[b]]) - else BinderEnv.this.apply(w) - } - } - - object EmptyBinderEnv extends BinderEnv { - def apply[A <: NameElement](v: A): Option[Scope[A]] = None - } - - // TODO: move this to some utility object higher in the scala hierarchy? - /** Returns a given result, but executes the supplied closure before returning. - * (The effect of this closure does not influence the returned value.) - */ - trait ReturnAndDo[T]{ - /** - * @param block code to be executed, purely for its side-effects - */ - def andDo(block: => Unit): T - } - - def return_[T](result: T): ReturnAndDo[T] = - new ReturnAndDo[T] { - val r = result - def andDo(block: => Unit): T = {block; r} - } - - private object _Binder { - private var currentId = 0 - private[Binders] def genId = return_(currentId) andDo {currentId=currentId+1} - } -} diff --git a/src/library/scala/util/parsing/combinator/Parsers.scala b/src/library/scala/util/parsing/combinator/Parsers.scala index 8fc2295d9c..4602c3cc53 100644 --- a/src/library/scala/util/parsing/combinator/Parsers.scala +++ b/src/library/scala/util/parsing/combinator/Parsers.scala @@ -158,12 +158,6 @@ trait Parsers { private lazy val lastNoSuccessVar = new DynamicVariable[Option[NoSuccess]](None) - @deprecated("lastNoSuccess was not thread-safe and will be removed in 2.11.0", "2.10.0") - def lastNoSuccess: NoSuccess = lastNoSuccessVar.value.orNull - - @deprecated("lastNoSuccess was not thread-safe and will be removed in 2.11.0", "2.10.0") - def lastNoSuccess_=(x: NoSuccess): Unit = lastNoSuccessVar.value = Option(x) - /** A common super-class for unsuccessful parse results. */ sealed abstract class NoSuccess(val msg: String, override val next: Input) extends ParseResult[Nothing] { // when we don't care about the difference between Failure and Error val successful = false diff --git a/src/library/scala/util/parsing/combinator/testing/RegexTest.scala b/src/library/scala/util/parsing/combinator/testing/RegexTest.scala deleted file mode 100644 index 727b6caf8d..0000000000 --- a/src/library/scala/util/parsing/combinator/testing/RegexTest.scala +++ /dev/null @@ -1,28 +0,0 @@ - -package scala -package util.parsing.combinator.testing - -import scala.util.parsing.combinator._ -import scala.util.parsing.input._ -import scala.language.postfixOps - -@deprecated("This class will be removed", "2.10.0") -case class Ident(s: String) -@deprecated("This class will be removed", "2.10.0") -case class Number(n: Int) -@deprecated("This class will be removed", "2.10.0") -case class Str(s: String) - -@deprecated("This class will be removed", "2.10.0") -object RegexTest extends RegexParsers { - val ident: Parser[Any] = """[a-zA-Z_]\w*""".r ^^ (s => Ident(s)) - val number: Parser[Any] = """\d\d*""".r ^^ (s => Number(s.toInt)) - val string: Parser[Any] = "\".*\"".r ^^ (s => Str(s.substring(1, s.length - 1))) - val parser = (ident | number | string)* - - def main(args: Array[String]) = { - val in = args mkString " " - println("\nin : "+in) - println(phrase[Any](parser)(new CharSequenceReader(in))) - } -} diff --git a/src/library/scala/util/parsing/combinator/testing/Tester.scala b/src/library/scala/util/parsing/combinator/testing/Tester.scala deleted file mode 100644 index 86c5d68ebe..0000000000 --- a/src/library/scala/util/parsing/combinator/testing/Tester.scala +++ /dev/null @@ -1,45 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala -package util.parsing.combinator.testing - -import scala.util.parsing.combinator.lexical.Lexical -import scala.util.parsing.combinator.syntactical.TokenParsers - -/** Facilitates testing a given parser on various input strings. - * - * Example use: - * {{{ - * val syntactic = new MyParsers - * }}} - * and - * {{{ - * val parser = syntactic.term - * }}} - * (If `MyParsers` extends [[scala.util.parsing.combinator.syntactical.TokenParsers]] - * with a parser called `term`.) - * - * @author Martin Odersky - * @author Adriaan Moors - */ -@deprecated("This class will be removed", "2.10.0") -abstract class Tester { - - val syntactic: TokenParsers { val lexical: Lexical } - val parser: syntactic.Parser[Any] - - /** Scans a String (using a `syntactic.lexical.Scanner`), parses it using - * `phrase(parser)`, and prints the input and the parsed result to the - * console. - */ - def test(in: String) { - Console.println("\nin : "+in) - Console.println(syntactic.phrase[Any](parser)(new syntactic.lexical.Scanner(in))) - } -} diff --git a/src/library/scala/xml/factory/LoggedNodeFactory.scala b/src/library/scala/xml/factory/LoggedNodeFactory.scala index 63b4f42150..bc074bfc83 100644 --- a/src/library/scala/xml/factory/LoggedNodeFactory.scala +++ b/src/library/scala/xml/factory/LoggedNodeFactory.scala @@ -15,8 +15,9 @@ package factory {{{ object testLogged extends App { val x = new scala.xml.parsing.NoBindingFactoryAdapter - with scala.xml.factory.LoggedNodeFactory[scala.xml.Elem] - with scala.util.logging.ConsoleLogger + with scala.xml.factory.LoggedNodeFactory[scala.xml.Elem] { + override def log(s: String) = println(s) + } Console.println("Start") val doc = x.load(new java.net.URL("http://example.com/file.xml")) @@ -28,7 +29,8 @@ object testLogged extends App { * @author Burak Emir * @version 1.0 */ -trait LoggedNodeFactory[A <: Node] extends NodeFactory[A] with scala.util.logging.Logged { +@deprecated("This trait will be removed.", "2.11") +trait LoggedNodeFactory[A <: Node] extends NodeFactory[A] { // configuration values val logNode = true val logText = false @@ -83,4 +85,6 @@ trait LoggedNodeFactory[A <: Node] extends NodeFactory[A] with scala.util.loggin super.makeProcInstr(t, s) } + @deprecated("This method and its usages will be removed. Use a debugger to debug code.", "2.11") + def log(msg: String): Unit = {} } diff --git a/src/library/scala/xml/parsing/MarkupHandler.scala b/src/library/scala/xml/parsing/MarkupHandler.scala index 0daabedf1c..1ebffb9c90 100755 --- a/src/library/scala/xml/parsing/MarkupHandler.scala +++ b/src/library/scala/xml/parsing/MarkupHandler.scala @@ -14,7 +14,6 @@ package parsing import scala.collection.mutable import scala.io.Source -import scala.util.logging.Logged import scala.xml.dtd._ /** class that handles markup - provides callback methods to MarkupParser. @@ -26,8 +25,8 @@ import scala.xml.dtd._ * @todo can we ignore more entity declarations (i.e. those with extIDs)? * @todo expanding entity references */ -abstract class MarkupHandler extends Logged -{ +abstract class MarkupHandler { + /** returns true is this markup handler is validating */ val isValidating: Boolean = false @@ -122,4 +121,7 @@ abstract class MarkupHandler extends Logged def unparsedEntityDecl(name: String, extID: ExternalID, notat: String): Unit = () def notationDecl(notat: String, extID: ExternalID): Unit = () def reportSyntaxError(pos: Int, str: String): Unit + + @deprecated("This method and its usages will be removed. Use a debugger to debug code.", "2.11") + def log(msg: String): Unit = {} } diff --git a/src/library/scala/xml/parsing/ValidatingMarkupHandler.scala b/src/library/scala/xml/parsing/ValidatingMarkupHandler.scala index cec6b358ff..1b20901249 100644 --- a/src/library/scala/xml/parsing/ValidatingMarkupHandler.scala +++ b/src/library/scala/xml/parsing/ValidatingMarkupHandler.scala @@ -13,9 +13,8 @@ package xml package parsing import scala.xml.dtd._ -import scala.util.logging.Logged -abstract class ValidatingMarkupHandler extends MarkupHandler with Logged { +abstract class ValidatingMarkupHandler extends MarkupHandler { var rootLabel:String = _ var qStack: List[Int] = Nil @@ -26,20 +25,6 @@ abstract class ValidatingMarkupHandler extends MarkupHandler with Logged { final override val isValidating = true - override def log(msg: String) {} - - /* - override def checkChildren(pos: Int, pre: String, label:String,ns:NodeSeq): Unit = { - Console.println("checkChildren()"); - val decl = lookupElemDecl(label); - // @todo: nice error message - val res = decl.contentModel.validate(ns); - Console.println("res = "+res); - if(!res) - //sys.error("invalid!"); - } - */ - override def endDTD(n:String) = { rootLabel = n } @@ -116,5 +101,4 @@ abstract class ValidatingMarkupHandler extends MarkupHandler with Logged { /** report a syntax error */ def reportValidationError(pos: Int, str: String): Unit - } diff --git a/src/library/scala/xml/persistent/CachedFileStorage.scala b/src/library/scala/xml/persistent/CachedFileStorage.scala index 347c11651c..57d512a041 100644 --- a/src/library/scala/xml/persistent/CachedFileStorage.scala +++ b/src/library/scala/xml/persistent/CachedFileStorage.scala @@ -14,7 +14,7 @@ import java.io.{ File, FileOutputStream } import java.nio.ByteBuffer import java.nio.channels.Channels import java.lang.Thread -import scala.util.logging.Logged + import scala.collection.Iterator /** Mutable storage of immutable xml trees. Everything is kept in memory, @@ -26,7 +26,7 @@ import scala.collection.Iterator * * @author Burak Emir */ -abstract class CachedFileStorage(private val file1: File) extends Thread with Logged { +abstract class CachedFileStorage(private val file1: File) extends Thread { private val file2 = new File(file1.getParent, file1.getName+"$") @@ -123,4 +123,7 @@ abstract class CachedFileStorage(private val file1: File) extends Thread with Lo this.dirty = true save() } + + @deprecated("This method and its usages will be removed. Use a debugger to debug code.", "2.11") + def log(msg: String): Unit = {} } diff --git a/src/reflect/scala/reflect/io/Path.scala b/src/reflect/scala/reflect/io/Path.scala index 0da962955c..15fce953f2 100644 --- a/src/reflect/scala/reflect/io/Path.scala +++ b/src/reflect/scala/reflect/io/Path.scala @@ -209,7 +209,7 @@ class Path private[io] (val jfile: JFile) { } def isDirectory = { if (Statistics.canEnable) Statistics.incCounter(IOStats.fileIsDirectoryCount) - try jfile.isDirectory() catch { case ex: SecurityException => false } + try jfile.isDirectory() catch { case ex: SecurityException => jfile.getPath == "." } } def isAbsolute = jfile.isAbsolute() def isEmpty = path.length == 0 diff --git a/src/reflect/scala/reflect/macros/Enclosures.scala b/src/reflect/scala/reflect/macros/Enclosures.scala index 8ea05500e4..d6ba5f39cd 100644 --- a/src/reflect/scala/reflect/macros/Enclosures.scala +++ b/src/reflect/scala/reflect/macros/Enclosures.scala @@ -45,13 +45,17 @@ trait Enclosures { */ def enclosingMacros: List[Context] - /** Types along with corresponding trees for which implicit arguments are currently searched. + /** Information about one of the currently considered implicit candidates. + * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters, + * hence implicit searches can recursively trigger other implicit searches. + * * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion. + * If we're in an implicit macro being expanded, it's included in this list. * * Unlike `openImplicits`, this is a val, which means that it gets initialized when the context is created * and always stays the same regardless of whatever happens during macro expansion. */ - def enclosingImplicits: List[(Type, Tree)] + def enclosingImplicits: List[ImplicitCandidate] /** Tries to guess a position for the enclosing application. * But that is simple, right? Just dereference `pos` of `macroApplication`? Not really. diff --git a/src/reflect/scala/reflect/macros/Typers.scala b/src/reflect/scala/reflect/macros/Typers.scala index eaf79f2dab..d7aec9b3ef 100644 --- a/src/reflect/scala/reflect/macros/Typers.scala +++ b/src/reflect/scala/reflect/macros/Typers.scala @@ -11,8 +11,6 @@ package macros trait Typers { self: Context => - import universe._ - /** Contexts that represent macros in-flight, including the current one. Very much like a stack trace, but for macros only. * Can be useful for interoperating with other macros and for imposing compiler-friendly limits on macro expansion. * @@ -25,13 +23,26 @@ trait Typers { */ def openMacros: List[Context] - /** Types along with corresponding trees for which implicit arguments are currently searched. + /** Information about one of the currently considered implicit candidates. + * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters, + * hence implicit searches can recursively trigger other implicit searches. + * + * `pre` and `sym` provide information about the candidate itself. + * `pt` and `tree` store the parameters of the implicit search the candidate is participating in. + */ + case class ImplicitCandidate(pre: Type, sym: Symbol, pt: Type, tree: Tree) + + /** Information about one of the currently considered implicit candidates. + * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters, + * hence implicit searches can recursively trigger other implicit searches. + * * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion. + * If we're in an implicit macro being expanded, it's included in this list. * * Unlike `enclosingImplicits`, this is a def, which means that it gets recalculated on every invocation, * so it might change depending on what is going on during macro expansion. */ - def openImplicits: List[(Type, Tree)] + def openImplicits: List[ImplicitCandidate] /** Typechecks the provided tree against the expected type `pt` in the macro callsite context. * @@ -46,7 +57,7 @@ trait Typers { * * @throws [[scala.reflect.macros.TypecheckException]] */ - def typeCheck(tree: Tree, pt: Type = WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree + def typeCheck(tree: Tree, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree /** Infers an implicit value of the expected type `pt` in the macro callsite context. * Optional `pos` parameter provides a position that will be associated with the implicit search. |