summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAntonio Cunei <antonio.cunei@epfl.ch>2011-03-20 03:02:15 +0000
committerAntonio Cunei <antonio.cunei@epfl.ch>2011-03-20 03:02:15 +0000
commitea94126e2dd5aa62d54ca894a785b1814c432441 (patch)
treecf51dd730619920806a8338eb115e447ddcec5a5 /src
parent1ca657a0a8e2c1d378b6344b1961042bc126e97e (diff)
downloadscala-ea94126e2dd5aa62d54ca894a785b1814c432441.tar.gz
scala-ea94126e2dd5aa62d54ca894a785b1814c432441.tar.bz2
scala-ea94126e2dd5aa62d54ca894a785b1814c432441.zip
Merged revisions 24504-24516 via svnmerge from
https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk ........ r24504 | extempore | 2011-03-19 01:31:59 +0100 (Sat, 19 Mar 2011) | 4 lines rytz's patch for making our crazy long names a bit less crazy. You can now use -Xmax-classfile-name to limit your filenames to as few as 72 characters. Watch out, nanotube gardens, we'll be stepping on your tiny flowers before you know it. No review. ........ r24505 | kzys | 2011-03-19 13:14:14 +0100 (Sat, 19 Mar 2011) | 2 lines [scaladoc] Closes #4361. ........ r24506 | kzys | 2011-03-19 14:02:35 +0100 (Sat, 19 Mar 2011) | 2 lines [scaladoc] Closes #4357. Review by dubochet. ........ r24507 | extempore | 2011-03-19 16:27:01 +0100 (Sat, 19 Mar 2011) | 3 lines A couple more minor tweaks to power mode, and more importantly, fix for a jline NPE provoked if your classloaders loaded classes in a way other than it expected. No review. ........ r24508 | extempore | 2011-03-19 16:27:19 +0100 (Sat, 19 Mar 2011) | 4 lines Some boundary conditions in range. Also bit the bullet on getting infix implicits to Integral and Fractional. As a bonus this patch knocked 10,000 long boxings off a specialized test. Who knew. Closes #4308, #4321, review by community. ........ r24509 | extempore | 2011-03-19 16:38:06 +0100 (Sat, 19 Mar 2011) | 1 line Added a :type command to the repl, no review. ........ r24510 | extempore | 2011-03-19 18:32:37 +0100 (Sat, 19 Mar 2011) | 10 lines Removed long deprecated and obscure CloneableCollection. Discovered we have a scala.collection.mutable.Cloneable which does not extend java.lang.Cloneable, which is why Array is not considered cloneable. That seems wrong, but to be conservative I gave Array the Cloneable interface without altering the scala trait. Also, if @serializable is deprecated in favor of Serializable, should not @cloneable be deprecated analogously? Closes #4307, and a commit-question review by rytz. ........ r24511 | extempore | 2011-03-19 19:12:17 +0100 (Sat, 19 Mar 2011) | 2 lines Fix for crasher with Class objects. Code by moors, comment by extempore. References #4305, no review. ........ r24512 | extempore | 2011-03-19 20:55:42 +0100 (Sat, 19 Mar 2011) | 3 lines Prevent a divergent implicit from terminating implicit search, so that there can still be a winner, as endorsed by martin over a cheese plate. Closes #3883, review by dmharrah. ........ r24513 | extempore | 2011-03-19 20:55:59 +0100 (Sat, 19 Mar 2011) | 3 lines I'm going to assume the patch I dropped off five months ago for #3938 was merely overlooked. Fixes an issue with java types which extend inner classes. Closes #3938, review by odersky. ........ r24514 | extempore | 2011-03-19 21:20:17 +0100 (Sat, 19 Mar 2011) | 1 line Fix for a slice related array view regression. Closes #4352, no review. ........ r24515 | extempore | 2011-03-19 21:29:02 +0100 (Sat, 19 Mar 2011) | 2 lines Oh yeah, now I remember why I started with length overrides. Fix for soon to be failing test, no review. ........ r24516 | extempore | 2011-03-20 00:20:19 +0100 (Sun, 20 Mar 2011) | 2 lines Fix for a big bug in lastIndexOfSlice and some latent negative index bugs in both that and indexOfSlice. This stuff is taxing. Closes #4348, no review. ........
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala6
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala9
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoop.scala10
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala8
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Power.scala83
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/NameManglers.scala23
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Names.scala23
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala39
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/util/Exceptional.scala14
-rw-r--r--src/jline/src/main/java/scala/tools/jline/console/completer/CandidateListCompletionHandler.java9
-rw-r--r--src/library/scala/Array.scala47
-rw-r--r--src/library/scala/collection/SeqLike.scala216
-rw-r--r--src/library/scala/collection/immutable/NumericRange.scala49
-rw-r--r--src/library/scala/collection/immutable/Range.scala12
-rw-r--r--src/library/scala/collection/mutable/Cloneable.scala3
-rw-r--r--src/library/scala/collection/mutable/CloneableCollection.scala22
-rw-r--r--src/library/scala/collection/mutable/IndexedSeqView.scala1
-rw-r--r--src/library/scala/math/Fractional.scala7
-rw-r--r--src/library/scala/math/Integral.scala11
23 files changed, 352 insertions, 248 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index c97fdbf58e..9a1bafa27f 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -237,13 +237,13 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid {
for (annot <- c.symbol.annotations) annot match {
case AnnotationInfo(tp, _, _) if tp.typeSymbol == SerializableAttr =>
- parents = parents ::: List(SerializableClass.tpe)
+ parents :+= SerializableClass.tpe
case AnnotationInfo(tp, _, _) if tp.typeSymbol == CloneableAttr =>
- parents = parents ::: List(CloneableClass.tpe)
+ parents :+= CloneableClass.tpe
case AnnotationInfo(tp, Literal(const) :: _, _) if tp.typeSymbol == SerialVersionUIDAttr =>
serialVUID = Some(const.longValue)
case AnnotationInfo(tp, _, _) if tp.typeSymbol == RemoteAttr =>
- parents = parents ::: List(RemoteInterface.tpe)
+ parents :+= RemoteInterface.tpe
isRemoteClass = true
case _ =>
}
diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
index 124fe54195..d82d5bfa5a 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
@@ -172,7 +172,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
/** Safe HTML tags that can be kept. */
protected val SafeTags =
- new Regex("""((&\w+;)|(<code( [^>]*)?>.*</code>)|(</?(abbr|acronym|address|area|a|bdo|big|blockquote|br|button|b|caption|cite|col|colgroup|dd|del|dfn|em|fieldset|form|hr|img|input|ins|i|kbd|label|legend|link|map|object|optgroup|option|param|pre|q|samp|select|small|span|strong|sub|sup|table|tbody|td|textarea|tfoot|th|thead|tr|tt|var)( [^>]*)?/?>))""")
+ new Regex("""((&\w+;)|(&#\d+;)|(<code( [^>]*)?>.*</code>)|(</?(abbr|acronym|address|area|a|bdo|big|blockquote|br|button|b|caption|cite|col|colgroup|dd|del|dfn|em|fieldset|form|hr|img|input|ins|i|kbd|label|legend|link|map|object|optgroup|option|param|pre|q|samp|select|small|span|strong|sub|sup|table|tbody|td|textarea|tfoot|th|thead|tr|tt|var)( [^>]*)?/?>))""")
protected val safeTagMarker = '\u000E'
@@ -602,8 +602,11 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
def superscript(): Inline = {
jump("^")
val i = inline(check("^"))
- jump("^")
- Superscript(i)
+ if (jump("^")) {
+ Superscript(i)
+ } else {
+ Chain(Seq(Text("^"), i))
+ }
}
def subscript(): Inline = {
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
index 53a3448c20..3d4ff7a20b 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
@@ -216,7 +216,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter)
NoArgs("quit", "exit the interpreter", () => Result(false, None)),
NoArgs("replay", "reset execution and replay all previous commands", replay),
LineArg("sh", "fork a shell and run a command", shCommand),
- NoArgs("silent", "disable/enable automatic printing of results", verbosity)
+ NoArgs("silent", "disable/enable automatic printing of results", verbosity),
+ LineArg("type", "display the type of an expression without evaluating it", typeCommand)
)
}
@@ -315,6 +316,13 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter)
}
}
+ private def typeCommand(line: String): Result = {
+ intp.typeOfExpression(line) match {
+ case Some(tp) => tp.toString
+ case _ => "Failed to determine type."
+ }
+ }
+
private def javapCommand(line: String): Result = {
if (line == "")
return ":javap [-lcsvp] [path1 path2 ...]"
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index 33dcfa59e6..527a9b153a 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -993,7 +993,7 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
def asModule = safeModule(expr) map (_.tpe)
def asExpr = beSilentDuring {
val lhs = freshInternalVarName()
- interpret("val " + lhs + " = { " + expr + " } ") match {
+ interpret("lazy val " + lhs + " = { " + expr + " } ") match {
case IR.Success => typeOfExpression(lhs)
case _ => None
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
index 796934cd35..7430406306 100644
--- a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
@@ -201,7 +201,13 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
}
// top level packages
- object rootClass extends TypeMemberCompletion(RootClass.tpe) { }
+ object rootClass extends TypeMemberCompletion(RootClass.tpe) {
+ override def completions(verbosity: Int) = super.completions(verbosity) :+ "_root_"
+ override def follow(id: String) = id match {
+ case "_root_" => Some(this)
+ case _ => super.follow(id)
+ }
+ }
// members of Predef
object predef extends TypeMemberCompletion(PredefModule.tpe) {
override def excludeEndsWith = super.excludeEndsWith ++ List("Wrapper", "ArrayOps")
diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala
index 6dc8cee219..0933365d9e 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Power.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala
@@ -125,12 +125,16 @@ class Power(repl: ILoop, intp: IMain) {
object InternalInfo {
implicit def apply[T: Manifest] : InternalInfo[T] = new InternalInfo[T](None)
}
- /** Todo: translate manifest type arguments into applied types. */
+ /** Todos...
+ * translate manifest type arguments into applied types
+ * customizable symbol filter (had to hardcode no-spec to reduce noise)
+ */
class InternalInfo[T: Manifest](value: Option[T] = None) {
def companion = symbol.companionSymbol
def info = symbol.info
def module = symbol.moduleClass
def owner = symbol.owner
+ def owners = symbol.ownerChain drop 1
def symDef = symbol.defString
def symName = symbol.name
def tpe = symbol.tpe
@@ -140,16 +144,18 @@ class Power(repl: ILoop, intp: IMain) {
def types = members filter (_.name.isTypeName)
def methods = members filter (_.isMethod)
def overrides = declares filter (_.isOverride)
+ def inPackage = owners find (x => x.isPackageClass || x.isPackage) getOrElse definitions.RootPackage
- def erasure = manifest[T].erasure
- def symbol = getCompilerClass(erasure.getName)
- def members = tpe.members
- def bts = info.baseTypeSeq.toList
- def btsmap = bts map (x => (x, x.decls.toList)) toMap
- def pkgName = erasure.getPackage.getName
- def pkg = getCompilerModule(pkgName)
- def pkgmates = pkg.tpe.members
- def pkgslurp = new PackageSlurper(pkgName) slurp()
+ def erasure = manifest[T].erasure
+ def symbol = getCompilerClass(erasure.getName)
+ def members = tpe.members filterNot (_.name.toString contains "$mc")
+ def allMembers = tpe.members
+ def bts = info.baseTypeSeq.toList
+ def btsmap = bts map (x => (x, x.decls.toList)) toMap
+ def pkgName = erasure.getPackage.getName
+ def pkg = getCompilerModule(pkgName)
+ def pkgmates = pkg.tpe.members
+ def pkgslurp = new PackageSlurper(pkgName) slurp()
def ? = this
@@ -167,28 +173,73 @@ class Power(repl: ILoop, intp: IMain) {
trait PCFormatter extends (Any => List[String]) {
def apply(x: Any): List[String]
+
+ private var indentLevel = 0
+ private def spaces = " " * indentLevel
+ def indented[T](body: => T): T = {
+ indentLevel += 1
+ try body
+ finally indentLevel -= 1
+ }
+
def show(x: Any): Unit = grep(x, _ => true)
- def grep(x: Any, p: String => Boolean): Unit = apply(x) filter p foreach println
+ def grep(x: Any, p: String => Boolean): Unit =
+ apply(x) filter p foreach (x => println(spaces + x))
+ }
+ class MultiPrintingConvenience[T](coll: Traversable[T])(implicit fmt: PCFormatter) {
+ import fmt._
+
+ def freqBy[U](p: T => U) = {
+ val map = coll.toList groupBy p
+ map.toList sortBy (-_._2.size)
+ }
+ def freqByFormatted[U](p: T => U) = {
+ val buf = new mutable.ListBuffer[String]
+
+ freqBy(p) foreach { case (k, vs) =>
+ buf += "%d: %s".format(vs.size, k)
+ vs flatMap fmt foreach (buf += " " + _)
+ }
+ buf.toList
+ }
+
+ /** It makes sense.
+ *
+ * # means how many
+ * ? means "I said, HOW MANY?"
+ * > means print
+ *
+ * Now don't you feel silly for what you were thinking.
+ */
+ def #?>[U](p: T => U) = this freqByFormatted p foreach println
+ def #?[U](p: T => U) = this freqByFormatted p
}
+
class PrintingConvenience[T](value: T)(implicit fmt: PCFormatter) {
def > : Unit = >(_ => true)
def >(s: String): Unit = >(_ contains s)
def >(r: Regex): Unit = >(_ matches r.pattern.toString)
def >(p: String => Boolean): Unit = fmt.grep(value, p)
}
- object Implicits {
- implicit lazy val powerNameOrdering: Ordering[Name] = Ordering[String] on (_.toString)
- implicit object powerSymbolOrdering extends Ordering[Symbol] {
+ protected trait Implicits1 {
+ implicit def replPrinting[T](x: T)(implicit fmt: PCFormatter) = new PrintingConvenience[T](x)
+ }
+ object Implicits extends Implicits1 {
+ implicit lazy val powerNameOrdering: Ordering[Name] = Ordering[String] on (_.toString)
+ implicit lazy val powerSymbolOrdering: Ordering[Symbol] = Ordering[Name] on (_.name)
+ implicit lazy val powerTypeOrdering: Ordering[Type] = Ordering[Symbol] on (_.typeSymbol)
+
+ object symbolSubtypeOrdering extends Ordering[Symbol] {
def compare(s1: Symbol, s2: Symbol) =
if (s1 eq s2) 0
else if (s1 isLess s2) -1
else 1
}
- implicit def replPrinting[T](x: T)(implicit fmt: PCFormatter) = new PrintingConvenience[T](x)
+ implicit def replCollPrinting[T](xs: Traversable[T])(implicit fmt: PCFormatter) = new MultiPrintingConvenience[T](xs)
implicit def replInternalInfo[T: Manifest](x: T): InternalInfo[T] = new InternalInfo[T](Some(x))
implicit object ReplDefaultFormatter extends PCFormatter {
def apply(x: Any): List[String] = x match {
- case Tuple2(k, v) => apply(k) + " -> " + apply(v)
+ case Tuple2(k, v) => List(apply(k) ++ Seq("->") ++ apply(v) mkString " ")
case xs: Traversable[_] => (xs.toList flatMap apply).sorted.distinct
case x => List("" + x)
}
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 1670dfb94a..7405ca0b3d 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -57,6 +57,7 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings {
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 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.")
diff --git a/src/compiler/scala/tools/nsc/symtab/NameManglers.scala b/src/compiler/scala/tools/nsc/symtab/NameManglers.scala
index b24a064139..dae07a29d5 100644
--- a/src/compiler/scala/tools/nsc/symtab/NameManglers.scala
+++ b/src/compiler/scala/tools/nsc/symtab/NameManglers.scala
@@ -22,15 +22,28 @@ trait NameManglers {
def flattenedName(segments: Name*): NameType = compactedString(segments mkString "$")
- private final val MaxFileNameLength = 255
- private final val MaxNameLength = MaxFileNameLength - 6 // leave space for ".class"
-
- /** "COMPACTIFY" */
+ /**
+ * COMPACTIFY
+ *
+ * The hashed name has the form (prefix + marker + md5 + marker + suffix), where
+ * - prefix/suffix.length = MaxNameLength / 4
+ * - md5.length = 32
+ *
+ * We obtain the formula:
+ *
+ * FileNameLength = 2*(MaxNameLength / 4) + 2.marker.length + 32 + 6
+ *
+ * (+6 for ".class"). MaxNameLength can therefore be computed as follows:
+ */
+ private final val marker = "$$$$"
+ private final val MaxNameLength = math.min(
+ settings.maxClassfileName.value - 6,
+ 2 * (settings.maxClassfileName.value - 6 - 2*marker.length - 32) + 6
+ )
private lazy val md5 = MessageDigest.getInstance("MD5")
private def toMD5(s: String, edge: Int) = {
val prefix = s take edge
val suffix = s takeRight edge
- val marker = "$$$$"
val cs = s.toArray
val bytes = Codec toUTF8 cs
diff --git a/src/compiler/scala/tools/nsc/symtab/Names.scala b/src/compiler/scala/tools/nsc/symtab/Names.scala
index 9e0348c2e3..a046058faf 100644
--- a/src/compiler/scala/tools/nsc/symtab/Names.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Names.scala
@@ -23,9 +23,6 @@ trait Names extends reflect.generic.Names {
private final val HASH_MASK = 0x7FFF
private final val NAME_SIZE = 0x20000
- private final val MaxFileNameLength = 255
- private final val MaxClassNameLength = MaxFileNameLength - 6 // leave space for ".class"
-
final val nameDebug = false
/** memory to store all names sequentially
@@ -78,26 +75,6 @@ trait Names extends reflect.generic.Names {
else nc = nc + len
}
- private lazy val md5 = MessageDigest.getInstance("MD5")
-
- /** "COMPACTIFY" */
- private def toMD5(s: String, edge: Int) = {
- val prefix = s take edge
- val suffix = s takeRight edge
- val marker = "$$$$"
-
- val cs = s.toArray
- val bytes = Codec toUTF8 cs
- md5 update bytes
- val md5chars = md5.digest() map (b => (b & 0xFF).toHexString) mkString
-
- prefix + marker + md5chars + marker + suffix
- }
-
- def compactify(s: String): String =
- if (s.length <= MaxClassNameLength) s
- else toMD5(s, MaxClassNameLength / 4)
-
/** Create a term name from the characters in cs[offset..offset+len-1].
*/
def newTermName(cs: Array[Char], offset: Int, len: Int): TermName = {
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 8cc977fa65..fd86fb7345 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -3396,7 +3396,8 @@ A type's typeSymbol should never be inspected directly.
else instParam(ps.tail, as.tail);
val symclazz = sym.owner
if (symclazz == clazz && !pre.isInstanceOf[TypeVar] && (pre.widen.typeSymbol isNonBottomSubClass symclazz)) {
- pre.baseType(symclazz) match {
+ // have to deconst because it may be a Class[T].
+ pre.baseType(symclazz).deconst match {
case TypeRef(_, basesym, baseargs) =>
//Console.println("instantiating " + sym + " from " + basesym + " with " + basesym.typeParams + " and " + baseargs+", pre = "+pre+", symclazz = "+symclazz);//DEBUG
if (sameLength(basesym.typeParams, baseargs)) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 655e5dfe09..3fc8344d8d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -591,7 +591,7 @@ trait Implicits {
* If it is null, no shadowing.
*/
class ImplicitComputation(iss: Infoss, shadowed: util.HashSet[Name]) {
- private var _best: SearchResult = SearchFailure
+ private var best: SearchResult = SearchFailure
/** True if a given ImplicitInfo (already known isValid) is eligible.
*/
@@ -612,6 +612,18 @@ trait Implicits {
*/
private def checkValid(sym: Symbol) = isValid(sym) || { invalidImplicits += sym ; false }
+ /** Preventing a divergent implicit from terminating implicit search,
+ * so that if there is a best candidate it can still be selected.
+ */
+ private var divergence = false
+ private val MaxDiverges = 1 // not sure if this should be > 1
+ private val divergenceHandler = util.Exceptional.expiringHandler(MaxDiverges) {
+ case x: DivergentImplicit =>
+ divergence = true
+ log("discarding divergent implicit during implicit search")
+ SearchFailure
+ }
+
/** Sorted list of eligible implicits.
*/
val eligible = {
@@ -635,10 +647,14 @@ trait Implicits {
@tailrec private def rankImplicits(pending: Infos, acc: Infos): Infos = pending match {
case Nil => acc
case i :: is =>
- typedImplicit(i, true) match {
+ def tryImplicitInfo(i: ImplicitInfo) =
+ try typedImplicit(i, true)
+ catch divergenceHandler
+
+ tryImplicitInfo(i) match {
case SearchFailure => rankImplicits(is, acc)
case newBest =>
- _best = newBest
+ best = newBest
val newPending = undoLog undo {
is filterNot (alt => alt == i || {
try improves(i, alt)
@@ -671,13 +687,20 @@ trait Implicits {
}
}
- if (_best == SearchFailure && invalidImplicits.nonEmpty) {
- setAddendum(tree.pos, () =>
- "\n Note: implicit "+invalidImplicits.head+" is not applicable here"+
- " because it comes after the application point and it lacks an explicit result type")
+ if (best == SearchFailure) {
+ /** If there is no winner, and we witnessed and caught divergence,
+ * now we can throw it for the error message.
+ */
+ if (divergence)
+ throw DivergentImplicit
+
+ if (invalidImplicits.nonEmpty)
+ setAddendum(tree.pos, () =>
+ "\n Note: implicit "+invalidImplicits.head+" is not applicable here"+
+ " because it comes after the application point and it lacks an explicit result type")
}
- _best
+ best
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 7ba561136d..fb8b0058eb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4267,7 +4267,7 @@ trait Typers extends Modes {
val result = typed(tree, forTypeMode(mode) | FUNmode, WildcardType)
val restpe = result.tpe.normalize // normalize to get rid of type aliases for the following check (#1241)
- if (!phase.erasedTypes && restpe.isInstanceOf[TypeRef] && !restpe.prefix.isStable) {
+ if (!phase.erasedTypes && restpe.isInstanceOf[TypeRef] && !restpe.prefix.isStable && !context.unit.isJava) {
error(tree.pos, restpe.prefix+" is not a legal prefix for a constructor")
}
diff --git a/src/compiler/scala/tools/nsc/util/Exceptional.scala b/src/compiler/scala/tools/nsc/util/Exceptional.scala
index 4230f29eb5..459881bb64 100644
--- a/src/compiler/scala/tools/nsc/util/Exceptional.scala
+++ b/src/compiler/scala/tools/nsc/util/Exceptional.scala
@@ -64,6 +64,20 @@ class Exceptional(val ex: Throwable)(implicit prefs: ScalaPrefs) {
object Exceptional {
+ type Catcher[+T] = PartialFunction[Throwable, T]
+
+ /** Creates an exception handler which will only ever catch the given
+ * number of exceptions (if the given pf is defined there) and after
+ * that will disable itself.
+ */
+ def expiringHandler[T](numCatches: Int)(pf: Catcher[T]): Catcher[T] = {
+ var remaining = numCatches;
+ { case ex: Throwable if remaining > 0 && pf.isDefinedAt(ex) =>
+ remaining -= 1
+ pf(ex)
+ }
+ }
+
/** The Throwable => Exceptional implicit plus the associated factory. */
implicit def throwableToExceptional(ex: Throwable)(implicit prefs: ScalaPrefs): Exceptional = apply(ex)(prefs)
def apply(ex: Throwable)(implicit prefs: ScalaPrefs) = new Exceptional(ex)(prefs)
diff --git a/src/jline/src/main/java/scala/tools/jline/console/completer/CandidateListCompletionHandler.java b/src/jline/src/main/java/scala/tools/jline/console/completer/CandidateListCompletionHandler.java
index 002f36b52e..fa5bfd2777 100644
--- a/src/jline/src/main/java/scala/tools/jline/console/completer/CandidateListCompletionHandler.java
+++ b/src/jline/src/main/java/scala/tools/jline/console/completer/CandidateListCompletionHandler.java
@@ -181,12 +181,13 @@ public class CandidateListCompletionHandler
private static final
ResourceBundle
bundle =
- ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName(),
- Locale.getDefault(),
- CandidateListCompletionHandler.class.getClassLoader());
+ ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName(), Locale.getDefault());
public String format(final Object... args) {
- return String.format(bundle.getString(name()), args);
+ if (bundle == null)
+ return "";
+ else
+ return String.format(bundle.getString(name()), args);
}
}
}
diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala
index 7183d9a473..1bdc5b23c9 100644
--- a/src/library/scala/Array.scala
+++ b/src/library/scala/Array.scala
@@ -415,7 +415,7 @@ object Array extends FallbackArrayBuilding {
def unapplySeq[T](x: Array[T]): Option[IndexedSeq[T]] =
if (x == null) None else Some(x.toIndexedSeq)
// !!! the null check should to be necessary, but without it 2241 fails. Seems to be a bug
- // in pattern matcher.
+ // in pattern matcher. @PP: I noted in #4364 I think the behavior is correct.
/** Creates an array containing several copies of an element.
*
@@ -483,7 +483,7 @@ object Array extends FallbackArrayBuilding {
* @author Martin Odersky
* @version 1.0
*/
-final class Array[T](_length: Int) extends java.io.Serializable {
+final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable {
/** Multidimensional array creation */
@deprecated("use `Array.ofDim' instead")
@@ -545,43 +545,28 @@ final class Array[T](_length: Int) extends java.io.Serializable {
def length: Int = throw new Error()
/** The element at given index.
- * <p>
- * Indices start a `0`; `xs.apply(0)` is the first
- * element of array `xs`.
- * </p>
- * <p>
- * Note the indexing syntax `xs(i)` is a shorthand for
- * `xs.apply(i)`.
- * </p>
*
- * @param i the index
- * @throws ArrayIndexOutOfBoundsException if `i < 0` or
- * `length <= i`
+ * Indices start at `0`; `xs.apply(0)` is the first element of array `xs`.
+ * Note the indexing syntax `xs(i)` is a shorthand for `xs.apply(i)`.
+ *
+ * @param i the index
+ * @return the element at the given index
+ * @throws ArrayIndexOutOfBoundsException if `i < 0` or `length <= i`
*/
def apply(i: Int): T = throw new Error()
- /** <p>
- * Update the element at given index.
- * </p>
- * <p>
- * Indices start a `0`; `xs.apply(0)` is the first
- * element of array `xs`.
- * </p>
- * <p>
- * Note the indexing syntax `xs(i) = x` is a shorthand
- * for `xs.update(i, x)`.
- * </p>
+ /** Update the element at given index.
+ *
+ * Indices start at `0`; `xs.apply(0)` is the first element of array `xs`.
+ * Note the indexing syntax `xs(i)` is a shorthand for `xs.apply(i)`.
*
- * @param i the index
- * @param x the value to be written at index `i`
- * @throws ArrayIndexOutOfBoundsException if `i < 0` or
- * `length <= i`
+ * @param i the index
+ * @param x the value to be written at index `i`
+ * @throws ArrayIndexOutOfBoundsException if `i < 0` or `length <= i`
*/
def update(i: Int, x: T) { throw new Error() }
- /** <p>
- * Clone the Array.
- * </p>
+ /** Clone the Array.
*
* @return A clone of the Array.
*/
diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala
index 4936e652b2..0f336dd778 100644
--- a/src/library/scala/collection/SeqLike.scala
+++ b/src/library/scala/collection/SeqLike.scala
@@ -15,110 +15,6 @@ import immutable.{List, Range}
import generic._
import parallel.ParSeq
-/** The companion object for trait `SeqLike`.
- */
-object SeqLike {
-
- /** A KMP implementation, based on the undoubtedly reliable wikipedia entry.
- *
- * @author paulp
- * @since 2.8
- */
- private def KMP[B](S: Seq[B], W: Seq[B]): Option[Int] = {
- // trivial cases
- if (W.isEmpty) return Some(0)
- else if (W drop 1 isEmpty) return (S indexOf W(0)) match {
- case -1 => None
- case x => Some(x)
- }
-
- val T: Array[Int] = {
- val arr = new Array[Int](W.length)
- var pos = 2
- var cnd = 0
- arr(0) = -1
- arr(1) = 0
- while (pos < W.length) {
- if (W(pos - 1) == W(cnd)) {
- arr(pos) = cnd + 1
- pos += 1
- cnd += 1
- }
- else if (cnd > 0) {
- cnd = arr(cnd)
- }
- else {
- arr(pos) = 0
- pos += 1
- }
- }
- arr
- }
-
- var m, i = 0
- def mi = m + i
-
- while (mi < S.length) {
- if (W(i) == S(mi)) {
- i += 1
- if (i == W.length)
- return Some(m)
- }
- else {
- m = mi - T(i)
- if (i > 0)
- i = T(i)
- }
- }
- None
- }
-
- /** Finds a particular index at which one sequence occurs in another sequence.
- * Both the source sequence and the target sequence are expressed in terms
- * other sequences S' and T' with offset and length parameters. This
- * function is designed to wrap the KMP machinery in a sufficiently general
- * way that all library sequence searches can use it. It is unlikely you
- * have cause to call it directly: prefer functions such as StringBuilder#indexOf
- * and Seq#lastIndexOf.
- *
- * @param source the sequence to search in
- * @param sourceOffset the starting offset in source
- * @param sourceCount the length beyond sourceOffset to search
- * @param target the sequence being searched for
- * @param targetOffset the starting offset in target
- * @param targetCount the length beyond targetOffset which makes up the target string
- * @param fromIndex the smallest index at which the target sequence may start
- *
- * @return the applicable index in source where target exists, or -1 if not found
- */
- def indexOf[B](
- source: Seq[B], sourceOffset: Int, sourceCount: Int,
- target: Seq[B], targetOffset: Int, targetCount: Int,
- fromIndex: Int): Int =
- KMP(source.slice(sourceOffset, sourceCount) drop fromIndex, target.slice(targetOffset, targetCount)) match {
- case None => -1
- case Some(x) => x + fromIndex
- }
-
- /** Finds a particular index at which one sequence occurs in another sequence.
- * Like indexOf, but finds the latest occurrence rather than earliest.
- *
- * @see SeqLike#indexOf
- */
- def lastIndexOf[B](
- source: Seq[B], sourceOffset: Int, sourceCount: Int,
- target: Seq[B], targetOffset: Int, targetCount: Int,
- fromIndex: Int): Int = {
- val src = (source.slice(sourceOffset, sourceCount) take fromIndex).reverse
- val tgt = target.slice(targetOffset, targetCount).reverse
-
- KMP(src, tgt) match {
- case None => -1
- case Some(x) => (src.length - tgt.length - x) + sourceOffset
- }
- }
-}
-
/** A template trait for sequences of type `Seq[A]`
* $seqInfo
*
@@ -1038,3 +934,115 @@ trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] with Parallelizable[A, Pa
override def projection = view
}
+/** The companion object for trait `SeqLike`.
+ */
+object SeqLike {
+ /** A KMP implementation, based on the undoubtedly reliable wikipedia entry.
+ *
+ * @author paulp
+ * @since 2.8
+ */
+ private def KMP[B](S: Seq[B], W: Seq[B]): Option[Int] = {
+ // trivial cases
+ if (W.isEmpty) return Some(0)
+ else if (W drop 1 isEmpty) return (S indexOf W(0)) match {
+ case -1 => None
+ case x => Some(x)
+ }
+
+ val T: Array[Int] = {
+ val arr = new Array[Int](W.length)
+ var pos = 2
+ var cnd = 0
+ arr(0) = -1
+ arr(1) = 0
+ while (pos < W.length) {
+ if (W(pos - 1) == W(cnd)) {
+ arr(pos) = cnd + 1
+ pos += 1
+ cnd += 1
+ }
+ else if (cnd > 0) {
+ cnd = arr(cnd)
+ }
+ else {
+ arr(pos) = 0
+ pos += 1
+ }
+ }
+ arr
+ }
+
+ var m, i = 0
+ def mi = m + i
+
+ while (mi < S.length) {
+ if (W(i) == S(mi)) {
+ i += 1
+ if (i == W.length)
+ return Some(m)
+ }
+ else {
+ m = mi - T(i)
+ if (i > 0)
+ i = T(i)
+ }
+ }
+ None
+ }
+
+ /** Finds a particular index at which one sequence occurs in another sequence.
+ * Both the source sequence and the target sequence are expressed in terms
+ * other sequences S' and T' with offset and length parameters. This
+ * function is designed to wrap the KMP machinery in a sufficiently general
+ * way that all library sequence searches can use it. It is unlikely you
+ * have cause to call it directly: prefer functions such as StringBuilder#indexOf
+ * and Seq#lastIndexOf.
+ *
+ * @param source the sequence to search in
+ * @param sourceOffset the starting offset in source
+ * @param sourceCount the length beyond sourceOffset to search
+ * @param target the sequence being searched for
+ * @param targetOffset the starting offset in target
+ * @param targetCount the length beyond targetOffset which makes up the target string
+ * @param fromIndex the smallest index at which the target sequence may start
+ *
+ * @return the applicable index in source where target exists, or -1 if not found
+ */
+ def indexOf[B](
+ source: Seq[B], sourceOffset: Int, sourceCount: Int,
+ target: Seq[B], targetOffset: Int, targetCount: Int,
+ fromIndex: Int): Int = {
+ val toDrop = fromIndex max 0
+ val src = source.slice(sourceOffset, sourceCount) drop toDrop
+ val tgt = target.slice(targetOffset, targetCount)
+
+ KMP(src, tgt) match {
+ case None => -1
+ case Some(x) => x + toDrop
+ }
+ }
+
+ /** Finds a particular index at which one sequence occurs in another sequence.
+ * Like indexOf, but finds the latest occurrence rather than earliest.
+ *
+ * @see SeqLike#indexOf
+ */
+ def lastIndexOf[B](
+ source: Seq[B], sourceOffset: Int, sourceCount: Int,
+ target: Seq[B], targetOffset: Int, targetCount: Int,
+ fromIndex: Int): Int = {
+ if (fromIndex < 0) return -1
+ val toTake = (fromIndex + targetCount) min sourceCount
+ // Given seq 1234567 looking for abc, we need to take an extra
+ // abc.length chars to examine beyond what is dictated by fromIndex.
+ val src = source.slice(sourceOffset, sourceCount) take toTake reverse
+ val tgt = target.slice(targetOffset, targetCount).reverse
+
+ // then we reverse the adjustment here on success.
+ KMP(src, tgt) match {
+ case None => -1
+ case Some(x) => src.length - x - targetCount
+ }
+ }
+}
diff --git a/src/library/scala/collection/immutable/NumericRange.scala b/src/library/scala/collection/immutable/NumericRange.scala
index 4db7d81fa8..e4b539f962 100644
--- a/src/library/scala/collection/immutable/NumericRange.scala
+++ b/src/library/scala/collection/immutable/NumericRange.scala
@@ -48,7 +48,8 @@ extends IndexedSeq[T] with Serializable {
*/
import num._
- private val numRangeElements: Int =
+ // See comment in Range for why this must be lazy.
+ private lazy val numRangeElements: Int =
NumericRange.count(start, end, step, isInclusive)
override def length = numRangeElements
@@ -191,32 +192,44 @@ extends IndexedSeq[T] with Serializable {
/** A companion object for numeric ranges.
*/
object NumericRange {
+ import Ordering.Implicits._
+ import math.Integral.Implicits._
+
/** Calculates the number of elements in a range given start, end, step, and
* whether or not it is inclusive. Throws an exception if step == 0 or
* the number of elements exceeds the maximum Int.
*/
def count[T: Integral](start: T, end: T, step: T, isInclusive: Boolean): Int = {
- val num = implicitly[Integral[T]]
- import num._
+ val zero = implicitly[Integral[T]].zero
+ val upward = start < end
+ val posStep = step > zero
+
+ if (step == zero) throw new IllegalArgumentException("step cannot be 0.")
+ else if (start == end) if (isInclusive) 1 else 0
+ else if (upward != posStep) 0
+ else {
+ val jumps = ((end - start) / step).toLong
+ val remainder = ((end - start) % step).toLong
+ val longCount = jumps + (
+ if (!isInclusive && zero == remainder) 0 else 1
+ )
- if (step == zero)
- throw new IllegalArgumentException("step cannot be 0.")
+ /** The edge cases keep coming. Since e.g.
+ * Long.MaxValue + 1 == Long.MinValue
+ * we do some more improbable seeming checks lest
+ * overflow turn up as an empty range.
+ */
+ // The second condition contradicts an empty result.
+ val isOverflow = longCount == 0 && (start + step < end) == upward
- val longCount: Long =
- if (start == end) { if (isInclusive) 1 else 0 }
- else if (end > start != step > zero) 0
- else {
- val jumps = toLong((end - start) / step)
- val remainder = toLong((end - start) % step)
+ if (longCount > scala.Int.MaxValue || longCount < 0L || isOverflow) {
+ val word = if (isInclusive) "to" else "until"
+ val descr = List(start, word, end, "by", step) mkString " "
- if (!isInclusive && zero == remainder) jumps
- else jumps + 1L
+ throw new IllegalArgumentException(descr + ": seqs cannot contain more than Int.MaxValue elements.")
}
-
- if (longCount > scala.Int.MaxValue || longCount < 0L)
- throw new IllegalArgumentException("Seqs cannot contain more than Int.MaxValue elements.")
-
- longCount.toInt
+ longCount.toInt
+ }
}
class Inclusive[T](start: T, end: T, step: T)(implicit num: Integral[T])
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index 90a1383353..435959a645 100644
--- a/src/library/scala/collection/immutable/Range.scala
+++ b/src/library/scala/collection/immutable/Range.scala
@@ -46,10 +46,14 @@ extends IndexedSeq[Int]
{
override def par = new ParRange(this)
- // Note that this value is calculated eagerly intentionally: it also
- // serves to enforce conditions (step != 0) && (length <= Int.MaxValue)
- private val numRangeElements: Int =
- Range.count(start, end, step, isInclusive)
+ // This member is designed to enforce conditions:
+ // (step != 0) && (length <= Int.MaxValue),
+ // but cannot be evaluated eagerly because we have a pattern where ranges
+ // are constructed like: "x to y by z"
+ // The "x to y" piece should not trigger an exception. So the calculation
+ // is delayed, which means it will not fail fast for those cases where failing
+ // was correct.
+ private lazy val numRangeElements: Int = Range.count(start, end, step, isInclusive)
protected def copy(start: Int, end: Int, step: Int): Range = new Range(start, end, step)
diff --git a/src/library/scala/collection/mutable/Cloneable.scala b/src/library/scala/collection/mutable/Cloneable.scala
index 15c245fde0..28bf2ceb8e 100644
--- a/src/library/scala/collection/mutable/Cloneable.scala
+++ b/src/library/scala/collection/mutable/Cloneable.scala
@@ -18,6 +18,7 @@ package mutable
* @tparam A Type of the elements contained in the collection, covariant and with reference types as upperbound.
*/
@cloneable
-trait Cloneable[+A <: AnyRef] {
+trait Cloneable[+A <: AnyRef] {
+ // !!! why doesn't this extend java.lang.Cloneable?
override def clone: A = super.clone().asInstanceOf[A]
}
diff --git a/src/library/scala/collection/mutable/CloneableCollection.scala b/src/library/scala/collection/mutable/CloneableCollection.scala
deleted file mode 100644
index 8659842b71..0000000000
--- a/src/library/scala/collection/mutable/CloneableCollection.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.collection
-package mutable
-
-/** The J2ME version of the library defined this trait with a `clone`
- * method to substitute for the lack of `Object.clone` there.
- *
- * @since 2.6
- */
-@deprecated("use Cloneable instead")
-trait CloneableCollection {
- override def clone(): AnyRef = super.clone()
-}
diff --git a/src/library/scala/collection/mutable/IndexedSeqView.scala b/src/library/scala/collection/mutable/IndexedSeqView.scala
index 15306b727a..12b0229ae1 100644
--- a/src/library/scala/collection/mutable/IndexedSeqView.scala
+++ b/src/library/scala/collection/mutable/IndexedSeqView.scala
@@ -38,7 +38,6 @@ self =>
trait Transformed[B] extends IndexedSeqView[B, Coll] with super.Transformed[B] {
def update(idx: Int, elem: B): Unit
- override def length = self.length
override def toString = viewToString
}
diff --git a/src/library/scala/math/Fractional.scala b/src/library/scala/math/Fractional.scala
index c6a80d3ee6..de09b184e0 100644
--- a/src/library/scala/math/Fractional.scala
+++ b/src/library/scala/math/Fractional.scala
@@ -20,3 +20,10 @@ trait Fractional[T] extends Numeric[T] {
override implicit def mkNumericOps(lhs: T): FractionalOps =
new FractionalOps(lhs)
}
+
+object Fractional {
+ trait ExtraImplicits {
+ implicit def infixFractionalOps[T](x: T)(implicit num: Fractional[T]): Fractional[T]#FractionalOps = new num.FractionalOps(x)
+ }
+ object Implicits extends ExtraImplicits
+} \ No newline at end of file
diff --git a/src/library/scala/math/Integral.scala b/src/library/scala/math/Integral.scala
index 9c1deaea33..bb364a79b4 100644
--- a/src/library/scala/math/Integral.scala
+++ b/src/library/scala/math/Integral.scala
@@ -24,3 +24,14 @@ trait Integral[T] extends Numeric[T] {
}
override implicit def mkNumericOps(lhs: T): IntegralOps = new IntegralOps(lhs)
}
+
+object Integral {
+ trait ExtraImplicits {
+ /** The regrettable design of Numeric/Integral/Fractional has them all
+ * bumping into one another when searching for this implicit, so they
+ * are exiled into their own companions.
+ */
+ implicit def infixIntegralOps[T](x: T)(implicit num: Integral[T]): Integral[T]#IntegralOps = new num.IntegralOps(x)
+ }
+ object Implicits extends ExtraImplicits
+} \ No newline at end of file