summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-07-29 21:42:25 +0000
committerPaul Phillips <paulp@improving.org>2011-07-29 21:42:25 +0000
commit9bdc1a0b6deb5bf8a056af0253b25fcf5d92c7f7 (patch)
tree9625ceb6358baf68b84eae5e1dc6fa74d267e425 /src/compiler
parent902c61f397069b9918f1854b8bf95a50b52c08fc (diff)
downloadscala-9bdc1a0b6deb5bf8a056af0253b25fcf5d92c7f7.tar.gz
scala-9bdc1a0b6deb5bf8a056af0253b25fcf5d92c7f7.tar.bz2
scala-9bdc1a0b6deb5bf8a056af0253b25fcf5d92c7f7.zip
Following up on things that -Xlint told me, som...
Following up on things that -Xlint told me, sometimes because Mr. Linty was being sensible and other times just to shut him up so we can hear better in the future. - made xml.Equality public because it occurs in public method signatures - made some actor classes with inaccessible-unoverridable methods final - eliminated a bunch of "dead code follows" warnings by deleting the dead code which really did follow - improved the reliability of warnings about inaccessible types For the changes in actors, review by phaller.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala9
-rw-r--r--src/compiler/scala/reflect/internal/TreeInfo.scala2
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala2
-rw-r--r--src/compiler/scala/reflect/internal/transform/Erasure.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/matching/Patterns.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/FscSettings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/MutableSettings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Adaptations.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala21
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala4
-rw-r--r--src/compiler/scala/tools/reflect/Invoked.scala6
-rw-r--r--src/compiler/scala/tools/util/Javap.scala18
-rw-r--r--src/compiler/scala/tools/util/StringOps.scala2
19 files changed, 52 insertions, 41 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index d076e80836..32e0b35d18 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -255,14 +255,16 @@ trait Definitions extends reflect.api.StandardDefinitions {
// classes with special meanings
lazy val StringAddClass = getClass("scala.runtime.StringAdd")
+ lazy val ArrowAssocClass = getClass("scala.Predef.ArrowAssoc")
lazy val StringAdd_+ = getMember(StringAddClass, nme.PLUS)
lazy val NotNullClass = getClass("scala.NotNull")
lazy val DelayedInitClass = getClass("scala.DelayedInit")
def delayedInitMethod = getMember(DelayedInitClass, nme.delayedInit)
// a dummy value that communicates that a delayedInit call is compiler-generated
// from phase UnCurry to phase Constructors
- def delayedInitArgVal = EmptyPackageClass.newValue(NoPosition, nme.delayedInitArg)
- .setInfo(UnitClass.tpe)
+ // !!! This is not used anywhere (it was checked in that way.)
+ // def delayedInitArgVal = EmptyPackageClass.newValue(NoPosition, nme.delayedInitArg)
+ // .setInfo(UnitClass.tpe)
lazy val TypeConstraintClass = getClass("scala.annotation.TypeConstraint")
lazy val SingletonClass = newClass(ScalaPackageClass, tpnme.Singleton, anyparam) setFlag (ABSTRACT | TRAIT | FINAL)
@@ -371,6 +373,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
// The given symbol represents either String.+ or StringAdd.+
def isStringAddition(sym: Symbol) = sym == String_+ || sym == StringAdd_+
+ def isArrowAssoc(sym: Symbol) = ArrowAssocClass.tpe.decls.toList contains sym
def isOptionType(tp: Type) = cond(tp.normalize) { case TypeRef(_, OptionClass, List(_)) => true }
def isSomeType(tp: Type) = cond(tp.normalize) { case TypeRef(_, SomeClass, List(_)) => true }
@@ -450,7 +453,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
}
}
- /** if tpe <: ProductN[T1,...,TN], returns Some(T1,...,TN) else None */
+ /** if tpe <: ProductN[T1,...,TN], returns Some((T1,...,TN)) else None */
def getProductArgs(tpe: Type): Option[List[Type]] =
tpe.baseClasses collectFirst { case x if isExactProductType(x.tpe) => tpe.baseType(x).typeArgs }
diff --git a/src/compiler/scala/reflect/internal/TreeInfo.scala b/src/compiler/scala/reflect/internal/TreeInfo.scala
index afb56d9999..a8ec7e34f5 100644
--- a/src/compiler/scala/reflect/internal/TreeInfo.scala
+++ b/src/compiler/scala/reflect/internal/TreeInfo.scala
@@ -410,7 +410,7 @@ abstract class TreeInfo {
}
object IsIf extends SeeThroughBlocks[Option[(Tree, Tree, Tree)]] {
protected def unapplyImpl(x: Tree) = x match {
- case If(cond, thenp, elsep) => Some(cond, thenp, elsep)
+ case If(cond, thenp, elsep) => Some((cond, thenp, elsep))
case _ => None
}
}
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index c34d285d9e..545b86f6ab 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -116,7 +116,7 @@ trait Types extends api.Types { self: SymbolTable =>
}
private[Types] def record(tv: TypeVar) = {
- log ::= (tv, tv.constr.cloneInternal)
+ log ::= ((tv, tv.constr.cloneInternal))
}
private[scala] def clear() {
if (settings.debug.value)
diff --git a/src/compiler/scala/reflect/internal/transform/Erasure.scala b/src/compiler/scala/reflect/internal/transform/Erasure.scala
index dec20a130e..6896a4aa5f 100644
--- a/src/compiler/scala/reflect/internal/transform/Erasure.scala
+++ b/src/compiler/scala/reflect/internal/transform/Erasure.scala
@@ -24,7 +24,7 @@ trait Erasure {
}
/** If `tp` is of the form Array[...Array[T]...] where `T` is an abstract type
- * then Some(N, T) where N is the number of Array constructors enclosing `T`,
+ * then Some((N, T)) where N is the number of Array constructors enclosing `T`,
* otherwise None. Existentials on any level are ignored.
*/
def unapply(tp: Type): Option[(Int, Type)] = tp.normalize match {
@@ -36,7 +36,7 @@ trait Erasure {
case None => None
}
case core =>
- Some(1, core)
+ Some((1, core))
}
case ExistentialType(tparams, restp) =>
unapply(restp)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index cf2814165a..ac9f853477 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -185,7 +185,7 @@ self =>
override def blockExpr(): Tree = skipBraces(EmptyTree)
- override def templateBody(isPre: Boolean) = skipBraces(emptyValDef, List(EmptyTree))
+ override def templateBody(isPre: Boolean) = skipBraces((emptyValDef, List(EmptyTree)))
}
class UnitParser(val unit: global.CompilationUnit, patches: List[BracePatch]) extends SourceFileParser(unit.source) {
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 03de24c550..70dd8cd920 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -1106,7 +1106,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
if (! (covered contains b) ) {
if (start >= 0) { // we're inside a handler range
end = labels(b).getAnchor()
- ranges ::= (start, end)
+ ranges ::= ((start, end))
start = -1
}
} else {
@@ -1123,7 +1123,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
* code!
*/
if (start >= 0) {
- ranges ::= (start, jcode.getPC())
+ ranges ::= ((start, jcode.getPC()))
}
if (!covered.isEmpty)
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index a093c875b8..fc53a34c45 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -589,7 +589,7 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
}
sources foreach (removeUnitOf(_))
minRunId = currentRunId
- respond(response) ()
+ respond(response)(())
demandNewCompilerRun()
}
diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala
index b25bf2d649..3abb0c5ba3 100644
--- a/src/compiler/scala/tools/nsc/matching/Patterns.scala
+++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala
@@ -316,7 +316,7 @@ trait Patterns extends ast.TreeDSL {
case UnApply(
Apply(TypeApply(Select(qual, nme.unapplySeq), List(tpt)), _),
List(ArrayValue(_, elems))) =>
- Some(qual.symbol, tpt, elems)
+ Some((qual.symbol, tpt, elems))
case _ =>
None
}
diff --git a/src/compiler/scala/tools/nsc/settings/FscSettings.scala b/src/compiler/scala/tools/nsc/settings/FscSettings.scala
index bb62750026..bb6e2ad920 100644
--- a/src/compiler/scala/tools/nsc/settings/FscSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/FscSettings.scala
@@ -24,7 +24,7 @@ class FscSettings(error: String => Unit) extends Settings(error) {
val server = StringSetting ("-server", "hostname:portnumber", "Specify compile server socket", "")
val preferIPv4 = BooleanSetting("-ipv4", "Use IPv4 rather than IPv6 for the server socket")
val idleMins = IntSetting ("-max-idle", "Set idle timeout in minutes for fsc (use 0 for no timeout)",
- 30, Some(0, Int.MaxValue), (_: String) => None)
+ 30, Some((0, Int.MaxValue)), (_: String) => None)
// For improved help output, separating fsc options from the others.
def fscSpecific = Set[Settings#Setting](
diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
index b96d9fbb1e..96175ff89d 100644
--- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
@@ -263,7 +263,7 @@ class MutableSettings(val errorFn: String => Unit)
def add(src: AbstractFile, dst: AbstractFile) {
singleOutDir = None
- outputDirs ::= (src, dst)
+ outputDirs ::= ((src, dst))
}
/** Return the list of source-destination directory pairs. */
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 6325fd6eb4..ed432562dc 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -59,7 +59,7 @@ trait ScalaSettings extends AbsScalaSettings
val future = BooleanSetting ("-Xfuture", "Turn on future language features.")
val genPhaseGraph = StringSetting ("-Xgenerate-phase-graph", "file", "Generate the phase graphs (outputs .dot files) to fileX.dot.", "")
val XlogImplicits = BooleanSetting ("-Xlog-implicits", "Show more detail on why some implicits are not applicable.")
- val maxClassfileName = IntSetting ("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, Some(72, 255), _ => None)
+ val maxClassfileName = IntSetting ("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, Some((72, 255)), _ => None)
val Xmigration28 = BooleanSetting ("-Xmigration", "Warn about constructs whose behavior may have changed between 2.7 and 2.8.")
val nouescape = BooleanSetting ("-Xno-uescape", "Disable handling of \\u unicode escapes.")
val Xnojline = BooleanSetting ("-Xnojline", "Do not use JLine for editing.")
@@ -121,7 +121,7 @@ trait ScalaSettings extends AbsScalaSettings
val Yprofile = PhasesSetting ("-Yprofile", "(Requires jvm -agentpath to contain yjgpagent) Profile CPU usage of given phases.")
val YprofileMem = BooleanSetting ("-Yprofile-memory", "Profile memory, get heap snapshot after each compiler run (requires yjpagent, see above).")
val YprofileClass = StringSetting ("-Yprofile-class", "class", "Name of profiler class.", "scala.tools.util.YourkitProfiling")
- val Yrecursion = IntSetting ("-Yrecursion", "Set recursion depth used when locking symbols.", 0, Some(0, Int.MaxValue), (_: String) => None)
+ val Yrecursion = IntSetting ("-Yrecursion", "Set recursion depth used when locking symbols.", 0, Some((0, Int.MaxValue)), (_: String) => None)
val selfInAnnots = BooleanSetting ("-Yself-in-annots", "Include a \"self\" identifier inside of annotations.")
val Xshowtrees = BooleanSetting ("-Yshow-trees", "(Requires -Xprint:) Print detailed ASTs.")
val Yshowsyms = BooleanSetting ("-Yshow-syms", "Print the AST symbol hierarchy after each phase.")
@@ -170,7 +170,7 @@ trait ScalaSettings extends AbsScalaSettings
val YpresentationLog = StringSetting("-Ypresentation-log", "file", "Log presentation compiler events into file", "")
val YpresentationReplay = StringSetting("-Ypresentation-replay", "file", "Replay presentation compiler events from file", "")
- val YpresentationDelay = IntSetting("-Ypresentation-delay", "Wait number of ms after typing before starting typechecking", 0, Some(0, 999), str => Some(str.toInt))
+ val YpresentationDelay = IntSetting("-Ypresentation-delay", "Wait number of ms after typing before starting typechecking", 0, Some((0, 999)), str => Some(str.toInt))
/**
* -P "Plugin" settings
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index e0c6e8678b..b5b770b003 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -230,7 +230,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
case DefDef(_, _, _, _, _, body)
if (tree.symbol.isOuterAccessor && tree.symbol.owner == clazz && clazz.isFinal) =>
log("outerAccessors += " + tree.symbol.fullName)
- outerAccessors ::= (tree.symbol, body)
+ outerAccessors ::= ((tree.symbol, body))
case Select(_, _) =>
if (!mustbeKept(tree.symbol)) {
log("accessedSyms += " + tree.symbol.fullName)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala b/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala
index 3dee4650de..99d5363d5e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala
@@ -59,6 +59,7 @@ trait Adaptations {
// an opt-in compiler option is given.
oneArgObject && !(
isStringAddition(t.symbol)
+ || isArrowAssoc(t.symbol)
|| t.symbol.name == nme.equals_
|| t.symbol.name == nme.EQ
|| t.symbol.name == nme.NE
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 765881ac81..097bbf5915 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -219,7 +219,7 @@ trait Implicits {
object Function1 {
val Sym = FunctionClass(1)
def unapply(tp: Type) = tp match {
- case TypeRef(_, Sym, arg1 :: arg2 :: _) => Some(arg1, arg2)
+ case TypeRef(_, Sym, arg1 :: arg2 :: _) => Some((arg1, arg2))
case _ => None
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 8e1ee97387..37b5870ac5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1221,22 +1221,27 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
otherSym.decodedName, cannot, memberSym.decodedName)
)
}
+
/** Warn about situations where a method signature will include a type which
* has more restrictive access than the method itself.
*/
private def checkAccessibilityOfReferencedTypes(tree: Tree) {
val member = tree.symbol
- // types of the value parameters
- member.paramss.flatten foreach { p =>
- val normalized = p.tpe.normalize
- if ((normalized ne p.tpe) && lessAccessibleSymsInType(normalized, member).isEmpty) ()
- else lessAccessibleSymsInType(p.tpe, member) foreach (sym => warnLessAccessible(sym, member))
+ def checkAccessibilityOfType(tpe: Type) {
+ val inaccessible = lessAccessibleSymsInType(tpe, member)
+ // if the unnormalized type is accessible, that's good enough
+ if (inaccessible.isEmpty) ()
+ // or if the normalized type is, that's good too
+ else if ((tpe ne tpe.normalize) && lessAccessibleSymsInType(tpe.normalize, member).isEmpty) ()
+ // otherwise warn about the inaccessible syms in the unnormalized type
+ else inaccessible foreach (sym => warnLessAccessible(sym, member))
}
+
+ // types of the value parameters
+ member.paramss.flatten foreach (p => checkAccessibilityOfType(p.tpe))
// upper bounds of type parameters
- member.typeParams.map(_.info.bounds.hi.widen) foreach { tp =>
- lessAccessibleSymsInType(tp, member) foreach (sym => warnLessAccessible(sym, member))
- }
+ member.typeParams.map(_.info.bounds.hi.widen) foreach checkAccessibilityOfType
}
/** Check that a deprecated val or def does not override a
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 4125ab0285..23482eb609 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2118,6 +2118,8 @@ trait Typers extends Modes with Adaptations {
} else {
val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) this
else newTyper(context.make(stat, exprOwner))
+ // XXX this creates a spurious dead code warning if an exception is thrown
+ // in a constructor, even if it is the only thing in the constructor.
val result = checkDead(localTyper.typed(stat, EXPRmode | BYVALmode, WildcardType))
if (treeInfo.isSelfOrSuperConstrCall(result)) {
context.inConstructorSuffix = true
@@ -2202,7 +2204,7 @@ trait Typers extends Modes with Adaptations {
}) ::: newStats.toList
}
}
- val result = stats mapConserve (typedStat)
+ val result = stats mapConserve typedStat
if (phase.erasedTypes) result
else checkNoDoubleDefsAndAddSynthetics(result)
}
diff --git a/src/compiler/scala/tools/reflect/Invoked.scala b/src/compiler/scala/tools/reflect/Invoked.scala
index fbc528ea45..30c6201a0d 100644
--- a/src/compiler/scala/tools/reflect/Invoked.scala
+++ b/src/compiler/scala/tools/reflect/Invoked.scala
@@ -34,18 +34,18 @@ object Invoked {
new Invoked(proxy, m, fixedArgs)
}
def unapply(x: Any) = x match {
- case x: Invoked => Some(x.proxy, x.m, x.args)
+ case x: Invoked => Some((x.proxy, x.m, x.args))
case _ => None
}
object NameAndArgs {
def unapply(x: Any) = x match {
- case x: Invoked => Some(x.name, x.args)
+ case x: Invoked => Some((x.name, x.args))
case _ => None
}
}
object NameAndArity {
def unapply(x: Any) = x match {
- case x: Invoked => Some(x.name, x.arity)
+ case x: Invoked => Some((x.name, x.arity))
case _ => None
}
}
diff --git a/src/compiler/scala/tools/util/Javap.scala b/src/compiler/scala/tools/util/Javap.scala
index 679fc0965b..04033e913d 100644
--- a/src/compiler/scala/tools/util/Javap.scala
+++ b/src/compiler/scala/tools/util/Javap.scala
@@ -121,15 +121,15 @@ object Javap {
}
private val envActionMap: Map[String, (String, Any)] = {
val map = Map(
- "-l" -> ("showLineAndLocal", true),
- "-c" -> ("showDisassembled", true),
- "-s" -> ("showInternalSigs", true),
- "-verbose" -> ("showVerbose", true),
- "-private" -> ("showAccess", Access.PRIVATE),
- "-package" -> ("showAccess", Access.PACKAGE),
- "-protected" -> ("showAccess", Access.PROTECTED),
- "-public" -> ("showAccess", Access.PUBLIC),
- "-all" -> ("showallAttr", true)
+ "-l" -> (("showLineAndLocal", true)),
+ "-c" -> (("showDisassembled", true)),
+ "-s" -> (("showInternalSigs", true)),
+ "-verbose" -> (("showVerbose", true)),
+ "-private" -> (("showAccess", Access.PRIVATE)),
+ "-package" -> (("showAccess", Access.PACKAGE)),
+ "-protected" -> (("showAccess", Access.PROTECTED)),
+ "-public" -> (("showAccess", Access.PUBLIC)),
+ "-all" -> (("showallAttr", true))
)
map ++ List(
"-v" -> map("-verbose"),
diff --git a/src/compiler/scala/tools/util/StringOps.scala b/src/compiler/scala/tools/util/StringOps.scala
index 65ff582011..2773aad87f 100644
--- a/src/compiler/scala/tools/util/StringOps.scala
+++ b/src/compiler/scala/tools/util/StringOps.scala
@@ -52,7 +52,7 @@ trait StringOps {
def splitAt(str: String, idx: Int, doDropIndex: Boolean = false): Option[(String, String)] =
if (idx == -1) None
- else Some(str take idx, str drop (if (doDropIndex) idx + 1 else idx))
+ else Some((str take idx, str drop (if (doDropIndex) idx + 1 else idx)))
/** Returns a string meaning "n elements".
*