diff options
42 files changed, 371 insertions, 481 deletions
diff --git a/spec/01-lexical-syntax.md b/spec/01-lexical-syntax.md index c37d8f2a0b..945dedf99b 100644 --- a/spec/01-lexical-syntax.md +++ b/spec/01-lexical-syntax.md @@ -326,7 +326,7 @@ Literal ::= [‘-’] integerLiteral integerLiteral ::= (decimalNumeral | hexNumeral) [‘L’ | ‘l’] decimalNumeral ::= ‘0’ | nonZeroDigit {digit} -hexNumeral ::= ‘0’ ‘x’ hexDigit {hexDigit} +hexNumeral ::= ‘0’ (‘x’ | ‘X’) hexDigit {hexDigit} digit ::= ‘0’ | nonZeroDigit nonZeroDigit ::= ‘1’ | … | ‘9’ ``` diff --git a/spec/13-syntax-summary.md b/spec/13-syntax-summary.md index ae941f189e..2b9571cc73 100644 --- a/spec/13-syntax-summary.md +++ b/spec/13-syntax-summary.md @@ -41,7 +41,7 @@ idrest ::= {letter | digit} [‘_’ op] integerLiteral ::= (decimalNumeral | hexNumeral) [‘L’ | ‘l’] decimalNumeral ::= ‘0’ | nonZeroDigit {digit} -hexNumeral ::= ‘0’ ‘x’ hexDigit {hexDigit} +hexNumeral ::= ‘0’ (‘x’ | ‘X’) hexDigit {hexDigit} digit ::= ‘0’ | nonZeroDigit nonZeroDigit ::= ‘1’ | … | ‘9’ diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 9cb4159e60..733664c30a 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -1609,10 +1609,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } } - /** Reset package class to state at typer (not sure what this - * is needed for?) + /** Reset package class to state at typer (not sure what this is needed for?) */ - private def resetPackageClass(pclazz: Symbol) { + private def resetPackageClass(pclazz: Symbol): Unit = if (typerPhase != NoPhase) { enteringPhase(firstPhase) { pclazz.setInfo(enteringPhase(typerPhase)(pclazz.info)) } diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala index d3f495f280..f1517e56a0 100755 --- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala @@ -346,12 +346,11 @@ trait MarkupParsers { // parse more XML ? if (charComingAfter(xSpaceOpt()) == '<') { - xSpaceOpt() - while (ch == '<') { + do { + xSpaceOpt() nextch() ts append element - xSpaceOpt() - } + } while (charComingAfter(xSpaceOpt()) == '<') handle.makeXMLseq(r2p(start, start, curOffset), ts) } else { diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala index d862805a07..22661d6ccf 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala @@ -544,10 +544,17 @@ trait MatchTranslation { // wrong when isSeq, and resultInMonad should always be correct since it comes // directly from the extractor's result type val binder = freshSym(pos, pureType(resultInMonad)) + val potentiallyMutableBinders: Set[Symbol] = + if (extractorApply.tpe.typeSymbol.isNonBottomSubClass(OptionClass) && !aligner.isSeq) + Set.empty + else + // Ensures we capture unstable bound variables eagerly. These can arise under name based patmat or by indexing into mutable Seqs. See run t9003.scala + subPatBinders.toSet ExtractorTreeMaker(extractorApply, lengthGuard(binder), binder)( subPatBinders, subPatRefs(binder), + potentiallyMutableBinders, aligner.isBool, checkedLength, patBinderOrCasted, diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala index 3abec521df..3fd9ce76f8 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala @@ -192,13 +192,14 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { case class ExtractorTreeMaker(extractor: Tree, extraCond: Option[Tree], nextBinder: Symbol)( val subPatBinders: List[Symbol], val subPatRefs: List[Tree], + val potentiallyMutableBinders: Set[Symbol], extractorReturnsBoolean: Boolean, val checkedLength: Option[Int], val prevBinder: Symbol, val ignoredSubPatBinders: Set[Symbol] ) extends FunTreeMaker with PreserveSubPatBinders { - def extraStoredBinders: Set[Symbol] = Set() + def extraStoredBinders: Set[Symbol] = potentiallyMutableBinders debug.patmat(s""" |ExtractorTreeMaker($extractor, $extraCond, $nextBinder) { diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index b13f9e94cc..8c2bc316ec 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -104,7 +104,7 @@ trait Contexts { self: Analyzer => // there must be a scala.xml package when xml literals were parsed in this unit if (unit.hasXml && ScalaXmlPackage == NoSymbol) - reporter.error(unit.firstXmlPos, "To compile XML syntax, the scala.xml package must be on the classpath.\nPlease see http://docs.scala-lang.org/overviews/core/scala-2.11.html#scala-xml.") + reporter.error(unit.firstXmlPos, "To compile XML syntax, the scala.xml package must be on the classpath.\nPlease see https://github.com/scala/scala-xml for details.") // scala-xml needs `scala.xml.TopScope` to be in scope globally as `$scope` // We detect `scala-xml` by looking for `scala.xml.TopScope` and diff --git a/src/library/scala/collection/JavaConverters.scala b/src/library/scala/collection/JavaConverters.scala index a4fa58b13c..875f6e1c02 100755 --- a/src/library/scala/collection/JavaConverters.scala +++ b/src/library/scala/collection/JavaConverters.scala @@ -37,8 +37,8 @@ import convert._ * val sl2 : scala.collection.mutable.Buffer[Int] = jl.asScala * assert(sl eq sl2) * }}} - * The following conversions also are supported, but the - * direction Scala to Java is done my a more specifically named method: + * The following conversions are also supported, but the + * direction from Scala to Java is done by the more specifically named methods: * `asJavaCollection`, `asJavaEnumeration`, `asJavaDictionary`. * * - `scala.collection.Iterable` <=> `java.util.Collection` diff --git a/src/library/scala/collection/LinearSeqLike.scala b/src/library/scala/collection/LinearSeqLike.scala index 3288599221..96e2135fd1 100644 --- a/src/library/scala/collection/LinearSeqLike.scala +++ b/src/library/scala/collection/LinearSeqLike.scala @@ -46,12 +46,18 @@ trait LinearSeqLike[+A, +Repr <: LinearSeqLike[A, Repr]] extends SeqLike[A, Repr val result = these.head; these = these.tail; result } else Iterator.empty.next() - /** Have to clear `these` so the iterator is exhausted like - * it would be without the optimization. - */ override def toList: List[A] = { + /* Have to clear `these` so the iterator is exhausted like + * it would be without the optimization. + * + * Calling "newBuilder.result()" in toList method + * prevents original seq from garbage collection, + * so we use these.take(0) here. + * + * Check SI-8924 for details + */ val xs = these.toList - these = newBuilder.result() + these = these.take(0) xs } } diff --git a/src/library/scala/collection/LinearSeqOptimized.scala b/src/library/scala/collection/LinearSeqOptimized.scala index f834545ec6..64248aa755 100755 --- a/src/library/scala/collection/LinearSeqOptimized.scala +++ b/src/library/scala/collection/LinearSeqOptimized.scala @@ -249,13 +249,16 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea override /*IterableLike*/ def sameElements[B >: A](that: GenIterable[B]): Boolean = that match { case that1: LinearSeq[_] => - var these = this - var those = that1 - while (!these.isEmpty && !those.isEmpty && these.head == those.head) { - these = these.tail - those = those.tail + // Probably immutable, so check reference identity first (it's quick anyway) + (this eq that1) || { + var these = this + var those = that1 + while (!these.isEmpty && !those.isEmpty && these.head == those.head) { + these = these.tail + those = those.tail + } + these.isEmpty && those.isEmpty } - these.isEmpty && those.isEmpty case _ => super.sameElements(that) } diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala index fdfb1f2efc..329273df5b 100644 --- a/src/library/scala/collection/SeqLike.scala +++ b/src/library/scala/collection/SeqLike.scala @@ -140,7 +140,15 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ if (isEmpty) Iterator(repr) else new PermutationsItr - /** Iterates over combinations. + /** Iterates over combinations. A _combination_ of length `n` is a subsequence of + * the original sequence, with the elements taken in order. Thus, `"xy"` and `"yy"` + * are both length-2 combinations of `"xyy"`, but `"yx"` is not. If there is + * more than one way to generate the same subsequence, only one will be returned. + * + * For example, `"xyyy"` has three different ways to generate `"xy"` depending on + * whether the first, second, or third `"y"` is selected. However, since all are + * identical, only one will be chosen. Which of the three will be taken is an + * implementation detail that is not defined. * * @return An Iterator which traverses the possible n-element combinations of this $coll. * @example `"abbbc".combinations(2) = Iterator(ab, ac, bb, bc)` diff --git a/src/library/scala/collection/SeqViewLike.scala b/src/library/scala/collection/SeqViewLike.scala index e719f19c78..ef6d2272cb 100644 --- a/src/library/scala/collection/SeqViewLike.scala +++ b/src/library/scala/collection/SeqViewLike.scala @@ -83,6 +83,7 @@ trait SeqViewLike[+A, } def length = index(self.length) def apply(idx: Int) = { + if (idx < 0 || idx >= self.length) throw new IndexOutOfBoundsException(idx.toString) val row = findRow(idx, 0, self.length - 1) mapping(self(row)).seq.toSeq(idx - index(row)) } diff --git a/src/library/scala/collection/immutable/PagedSeq.scala b/src/library/scala/collection/immutable/PagedSeq.scala index 3a64820be6..f11217d26a 100644 --- a/src/library/scala/collection/immutable/PagedSeq.scala +++ b/src/library/scala/collection/immutable/PagedSeq.scala @@ -158,7 +158,7 @@ extends scala.collection.AbstractSeq[T] * @note Calling this method will force the entire sequence to be read. */ def length: Int = { - while (!latest.isLast) addMore() + while (!latest.isLast && latest.end < end) addMore() (latest.end min end) - start } @@ -175,7 +175,8 @@ extends scala.collection.AbstractSeq[T] */ override def isDefinedAt(index: Int) = index >= 0 && index < end - start && { - val p = page(index + start); index + start < p.end + val absidx = index + start + absidx >= 0 && absidx < page(absidx).end } /** The subsequence from index `start` up to `end -1` if `end` @@ -192,6 +193,9 @@ extends scala.collection.AbstractSeq[T] if (f.next eq null) f.addMore(more) f = f.next } + // Warning -- not refining `more` means that slices can freely request and obtain + // data outside of their slice. This is part of the design of PagedSeq + // (to read pages!) but can be surprising. new PagedSeq(more, f, s, e) } diff --git a/src/library/scala/collection/mutable/MultiMap.scala b/src/library/scala/collection/mutable/MultiMap.scala index 78dfc35268..ac2ebf31d8 100644 --- a/src/library/scala/collection/mutable/MultiMap.scala +++ b/src/library/scala/collection/mutable/MultiMap.scala @@ -65,10 +65,9 @@ trait MultiMap[A, B] extends Map[A, Set[B]] { */ protected def makeSet: Set[B] = new HashSet[B] - /** Assigns the specified `value` to a specified `key`, replacing - * the existing value assigned to that `key` if it is equal to - * the specified value. Otherwise, simply adds another binding to - * the `key`. + /** Assigns the specified `value` to a specified `key`. If the key + * already has a binding to equal to `value`, nothing is changed; + * otherwise a new binding is added for that `key`. * * @param key The key to which to bind the new value. * @param value The value to bind to the key. diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala index 4a9a5d4008..d3c4161e3b 100644 --- a/src/library/scala/collection/mutable/PriorityQueue.scala +++ b/src/library/scala/collection/mutable/PriorityQueue.scala @@ -247,13 +247,6 @@ class PriorityQueue[A](implicit val ord: Ordering[A]) * @return a priority queue with the same elements. */ override def clone(): PriorityQueue[A] = new PriorityQueue[A] ++= this.iterator - - // def printstate() { - // println("-----------------------") - // println("Size: " + resarr.p_size0) - // println("Internal array: " + resarr.p_array.toList) - // println(toString) - // } } diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala index 5a81710986..74a174ea74 100644 --- a/src/library/scala/math/BigDecimal.scala +++ b/src/library/scala/math/BigDecimal.scala @@ -417,7 +417,7 @@ extends ScalaNumber with ScalaNumericConversions with Serializable { private final def computeHashCode(): Unit = { computedHashCode = if (isWhole && (precision - scale) < BigDecimal.maximumHashScale) toBigInt.hashCode - else if (isValidDouble) doubleValue.## + else if (isDecimalDouble) doubleValue.## else { val temp = bigDecimal.stripTrailingZeros scala.util.hashing.MurmurHash3.mixLast( temp.scaleByPowerOfTen(temp.scale).toBigInteger.hashCode, temp.scale ) @@ -477,7 +477,7 @@ extends ScalaNumber with ScalaNumericConversions with Serializable { * `isExactDouble`, `isBinaryDouble`, or `isDecimalDouble`, depending on the intended meaning. * By default, `decimal` creation is used, so `isDecimalDouble` is probably what you want. */ - @deprecated("Validity has two distinct meanings. Use `isExactBinaryDouble` or `equivalentToDouble` instead.", "2.11") + @deprecated("Validity has distinct meanings. Use `isExactDouble`, `isBinaryDouble`, or `isDecimalDouble` instead.", "2.11") def isValidDouble = { val d = toDouble !d.isInfinity && bigDecimal.compareTo(new BigDec(d)) == 0 diff --git a/src/reflect/scala/reflect/api/Constants.scala b/src/reflect/scala/reflect/api/Constants.scala index e73c5ffa91..fbcf7f3e4f 100644 --- a/src/reflect/scala/reflect/api/Constants.scala +++ b/src/reflect/scala/reflect/api/Constants.scala @@ -60,7 +60,7 @@ package api * * object Test extends App { * val jann = typeOf[JavaAnnottee].typeSymbol.annotations(0).javaArgs - * def jarg(name: String) = jann(newTermName(name)).asInstanceOf[LiteralArgument].value + * def jarg(name: String) = jann(TermName(name)).asInstanceOf[LiteralArgument].value * * val classRef = jarg("classRef").typeValue * println(showRaw(classRef)) // TypeRef(ThisType(<empty>), JavaAnnottee, List()) @@ -150,7 +150,7 @@ trait Constants { * * object Test extends App { * val jann = typeOf[JavaAnnottee].typeSymbol.annotations(0).javaArgs - * def jarg(name: String) = jann(newTermName(name)) match { + * def jarg(name: String) = jann(TermName(name)) match { * // Constant is always wrapped into a Literal or LiteralArgument tree node * case LiteralArgument(ct: Constant) => value * case _ => sys.error("Not a constant") diff --git a/src/reflect/scala/reflect/api/Exprs.scala b/src/reflect/scala/reflect/api/Exprs.scala index 3230fdbc67..ad03718898 100644 --- a/src/reflect/scala/reflect/api/Exprs.scala +++ b/src/reflect/scala/reflect/api/Exprs.scala @@ -84,7 +84,7 @@ trait Exprs { self: Universe => * * It is equivalent to * {{{ - * Select( expr.tree, newTermName("foo") ) + * Select( expr.tree, TermName("foo") ) * }}} * * The following example code however does not compile diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala index bf4d6353df..bcad84a3f0 100644 --- a/src/reflect/scala/reflect/api/FlagSets.scala +++ b/src/reflect/scala/reflect/api/FlagSets.scala @@ -20,20 +20,20 @@ import scala.language.implicitConversions * * For example, to create a class named `C` one would write something like: * {{{ - * ClassDef(Modifiers(NoFlags), newTypeName("C"), Nil, ...) + * ClassDef(Modifiers(NoFlags), TypeName("C"), Nil, ...) * }}} * * Here, the flag set is empty. * * To make `C` private, one would write something like: * {{{ - * ClassDef(Modifiers(PRIVATE), newTypeName("C"), Nil, ...) + * ClassDef(Modifiers(PRIVATE), TypeName("C"), Nil, ...) * }}} * * Flags can also be combined with the vertical bar operator (`|`). * For example, a private final class is written something like: * {{{ - * ClassDef(Modifiers(PRIVATE | FINAL), newTypeName("C"), Nil, ...) + * ClassDef(Modifiers(PRIVATE | FINAL), TypeName("C"), Nil, ...) * }}} * * The list of all available flags is defined in [[scala.reflect.api.FlagSets#FlagValues]], available via diff --git a/src/reflect/scala/reflect/api/Mirror.scala b/src/reflect/scala/reflect/api/Mirror.scala index 318fdb369a..96aab48e75 100644 --- a/src/reflect/scala/reflect/api/Mirror.scala +++ b/src/reflect/scala/reflect/api/Mirror.scala @@ -58,7 +58,7 @@ abstract class Mirror[U <: Universe with Singleton] { * scala> cm.staticPackage("scala") * res2: scala.reflect.runtime.universe.ModuleSymbol = package scala * - * scala> res2.moduleClass.info member newTypeName("List") + * scala> res2.moduleClass.info member TypeName("List") * res3: scala.reflect.runtime.universe.Symbol = type List * * scala> res3.fullName diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala index ec420d184c..773c6b6fb4 100644 --- a/src/reflect/scala/reflect/api/Mirrors.scala +++ b/src/reflect/scala/reflect/api/Mirrors.scala @@ -292,7 +292,7 @@ trait Mirrors { self: Universe => * that can be used to create instances of the class, inspect its companion object or perform further reflections. * * To get a class symbol by the name of the class you would like to reflect, - * use `<this mirror>.symbol.info.member(newTypeName(<name of the class>)).asClass`. + * use `<this mirror>.symbol.info.member(TypeName(<name of the class>)).asClass`. * For further information about member lookup refer to `Symbol.info`. * * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility). diff --git a/src/reflect/scala/reflect/api/Names.scala b/src/reflect/scala/reflect/api/Names.scala index fe5f47c25d..03f7b2d218 100644 --- a/src/reflect/scala/reflect/api/Names.scala +++ b/src/reflect/scala/reflect/api/Names.scala @@ -17,11 +17,11 @@ import scala.language.implicitConversions * To search for the `map` method (which is a term) declared in the `List` class, one can do: * * {{{ - * scala> typeOf[List[_]].member(newTermName("map")) + * scala> typeOf[List[_]].member(TermName("map")) * res0: reflect.runtime.universe.Symbol = method map * }}} * - * To search for a type member, one can follow the same procedure, using `newTypeName` instead. + * To search for a type member, one can follow the same procedure, using `TypeName` instead. * * For more information about creating and using `Name`s, see the [[http://docs.scala-lang.org/overviews/reflection/annotations-names-scopes.html Reflection Guide: Annotations, Names, Scopes, and More]] * @@ -30,14 +30,14 @@ import scala.language.implicitConversions */ trait Names { /** An implicit conversion from String to TermName. - * Enables an alternative notation `"map": TermName` as opposed to `newTermName("map")`. + * Enables an alternative notation `"map": TermName` as opposed to `TermName("map")`. * @group Names */ @deprecated("Use explicit `TermName(s)` instead", "2.11.0") implicit def stringToTermName(s: String): TermName = TermName(s) /** An implicit conversion from String to TypeName. - * Enables an alternative notation `"List": TypeName` as opposed to `newTypeName("List")`. + * Enables an alternative notation `"List": TypeName` as opposed to `TypeName("List")`. * @group Names */ @deprecated("Use explicit `TypeName(s)` instead", "2.11.0") diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala index 92ae6d8b44..01b9759c70 100644 --- a/src/reflect/scala/reflect/api/Printers.scala +++ b/src/reflect/scala/reflect/api/Printers.scala @@ -46,15 +46,15 @@ import java.io.{ PrintWriter, StringWriter } * {{{ * scala> showRaw(tree) * res1: String = Block(List( - * ClassDef(Modifiers(FINAL), newTypeName("C"), List(), Template( - * List(Ident(newTypeName("AnyRef"))), + * ClassDef(Modifiers(FINAL), TypeName("C"), List(), Template( + * List(Ident(TypeName("AnyRef"))), * noSelfType, * List( * DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(), * Block(List( * Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), * Literal(Constant(())))), - * DefDef(Modifiers(), newTermName("x"), List(), List(), TypeTree(), + * DefDef(Modifiers(), TermName("x"), List(), List(), TypeTree(), * Literal(Constant(2))))))), * Literal(Constant(()))) * }}} @@ -70,23 +70,23 @@ import java.io.{ PrintWriter, StringWriter } * * scala> showRaw(cm.mkToolBox().typecheck(tree), printTypes = true) * res2: String = Block[1](List( - * ClassDef[2](Modifiers(FINAL), newTypeName("C"), List(), Template[3]( - * List(Ident[4](newTypeName("AnyRef"))), + * ClassDef[2](Modifiers(FINAL), TypeName("C"), List(), Template[3]( + * List(Ident[4](TypeName("AnyRef"))), * noSelfType, * List( * DefDef[2](Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree[3](), * Block[1](List( - * Apply[4](Select[5](Super[6](This[3](newTypeName("C")), tpnme.EMPTY), ...))), + * Apply[4](Select[5](Super[6](This[3](TypeName("C")), tpnme.EMPTY), ...))), * Literal[1](Constant(())))), - * DefDef[2](Modifiers(), newTermName("x"), List(), List(), TypeTree[7](), + * DefDef[2](Modifiers(), TermName("x"), List(), List(), TypeTree[7](), * Literal[8](Constant(2))))))), * Literal[1](Constant(()))) * [1] TypeRef(ThisType(scala), scala.Unit, List()) * [2] NoType - * [3] TypeRef(NoPrefix, newTypeName("C"), List()) + * [3] TypeRef(NoPrefix, TypeName("C"), List()) * [4] TypeRef(ThisType(java.lang), java.lang.Object, List()) * [5] MethodType(List(), TypeRef(ThisType(java.lang), java.lang.Object, List())) - * [6] SuperType(ThisType(newTypeName("C")), TypeRef(... java.lang.Object ...)) + * [6] SuperType(ThisType(TypeName("C")), TypeRef(... java.lang.Object ...)) * [7] TypeRef(ThisType(scala), scala.Int, List()) * [8] ConstantType(Constant(2)) * }}} @@ -112,10 +112,10 @@ import java.io.{ PrintWriter, StringWriter } * // showRaw has already been discussed above * scala> showRaw(tpe) * res1: String = RefinedType( - * List(TypeRef(ThisType(scala), newTypeName("AnyRef"), List())), + * List(TypeRef(ThisType(scala), TypeName("AnyRef"), List())), * Scope( - * newTermName("x"), - * newTermName("y"))) + * TermName("x"), + * TermName("y"))) * }}} * * `printIds` and/or `printKinds` can additionally be supplied as arguments in a call to @@ -124,10 +124,10 @@ import java.io.{ PrintWriter, StringWriter } * {{{ * scala> showRaw(tpe, printIds = true, printKinds = true) * res2: String = RefinedType( - * List(TypeRef(ThisType(scala#2043#PK), newTypeName("AnyRef")#691#TPE, List())), + * List(TypeRef(ThisType(scala#2043#PK), TypeName("AnyRef")#691#TPE, List())), * Scope( - * newTermName("x")#2540#METH, - * newTermName("y")#2541#GET)) + * TermName("x")#2540#METH, + * TermName("y")#2541#GET)) * }}} * * For more details about `Printer`s and other aspects of Scala reflection, see the diff --git a/src/reflect/scala/reflect/api/StandardDefinitions.scala b/src/reflect/scala/reflect/api/StandardDefinitions.scala index 524b7ea14b..bf9cf5e334 100644 --- a/src/reflect/scala/reflect/api/StandardDefinitions.scala +++ b/src/reflect/scala/reflect/api/StandardDefinitions.scala @@ -128,7 +128,7 @@ trait StandardDefinitions { * scala> import scala.reflect.runtime.universe._ * import scala.reflect.runtime.universe._ * - * scala> val m = typeOf[C].member(newTermName("m")).asMethod + * scala> val m = typeOf[C].member(TermName("m")).asMethod * m: reflect.runtime.universe.MethodSymbol = method m * * scala> m.params(0)(0).info @@ -156,7 +156,7 @@ trait StandardDefinitions { * scala> import scala.reflect.runtime.universe._ * import scala.reflect.runtime.universe._ * - * scala> val m = typeOf[C].member(newTermName("m")).asMethod + * scala> val m = typeOf[C].member(TermName("m")).asMethod * m: reflect.runtime.universe.MethodSymbol = method m * * scala> m.params(0)(0).info @@ -181,7 +181,7 @@ trait StandardDefinitions { * scala> import scala.reflect.runtime.universe._ * import scala.reflect.runtime.universe._ * - * scala> val m = typeOf[C].member(newTermName("m")).asMethod + * scala> val m = typeOf[C].member(TermName("m")).asMethod * m: reflect.runtime.universe.MethodSymbol = method m * * scala> m.params(0)(0).info diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala index 42cf600c85..18d185067e 100644 --- a/src/reflect/scala/reflect/api/Symbols.scala +++ b/src/reflect/scala/reflect/api/Symbols.scala @@ -27,7 +27,7 @@ package api * scala> class C[T] { def test[U](x: T)(y: U): Int = ??? } * defined class C * - * scala> val test = typeOf[C[Int]].member(newTermName("test")).asMethod + * scala> val test = typeOf[C[Int]].member(TermName("test")).asMethod * test: reflect.runtime.universe.MethodSymbol = method test * * scala> test.info diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala index ff8926651b..aeaa38c317 100644 --- a/src/reflect/scala/reflect/api/Trees.scala +++ b/src/reflect/scala/reflect/api/Trees.scala @@ -33,7 +33,7 @@ package api * * The following creates an AST representing `print("Hello World")`: * {{{ - * Apply(Select(Select(This(newTypeName("scala")), newTermName("Predef")), newTermName("print")), List(Literal(Constant("Hello World")))) + * Apply(Select(Select(This(TypeName("scala")), TermName("Predef")), TermName("print")), List(Literal(Constant("Hello World")))) * }}} * * The following creates an AST from a literal 5, and then uses `showRaw` to print it in a readable format. @@ -1098,11 +1098,11 @@ trait Trees { self: Universe => * // a dummy node that carries the type of unapplication to patmat * // the <unapply-selector> here doesn't have an underlying symbol * // it only has a type assigned, therefore after `untypecheck` this tree is no longer typeable - * Apply(Select(Ident(Foo), newTermName("unapply")), List(Ident(newTermName("<unapply-selector>")))), + * Apply(Select(Ident(Foo), TermName("unapply")), List(Ident(TermName("<unapply-selector>")))), * // arguments of the unapply => nothing synthetic here - * List(Bind(newTermName("x"), Ident(nme.WILDCARD)))), + * List(Bind(TermName("x"), Ident(nme.WILDCARD)))), * EmptyTree, - * Ident(newTermName("x"))))) + * Ident(TermName("x"))))) * }}} * * Introduced by typer. Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher). diff --git a/src/reflect/scala/reflect/internal/Depth.scala b/src/reflect/scala/reflect/internal/Depth.scala index 357abf765f..a330e0accb 100644 --- a/src/reflect/scala/reflect/internal/Depth.scala +++ b/src/reflect/scala/reflect/internal/Depth.scala @@ -21,8 +21,20 @@ final class Depth private (val depth: Int) extends AnyVal with Ordered[Depth] { object Depth { // A don't care value for the depth parameter in lubs/glbs and related operations. - final val AnyDepth = new Depth(Int.MinValue) + // When passed this value, the recursion budget will be inferred from the shape of + // the `typeDepth` of the list of types. + final val AnyDepthValue = -3 + final val AnyDepth = new Depth(AnyDepthValue) + final val Zero = new Depth(0) - @inline final def apply(depth: Int): Depth = if (depth < 0) AnyDepth else new Depth(depth) + // SI-9018: A negative depth is used to signal that we have breached the recursion limit. + // The LUB/GLB implementation will then truncate to Any/Nothing. + // + // We only really need one of these, but we allow representation of Depth(-1) and Depth(-2) + // to mimic the historical choice of 2.10.4. + @inline final def apply(depth: Int): Depth = { + if (depth < AnyDepthValue) AnyDepth + else new Depth(depth) + } } diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index 9f3f8375b1..4fd5768b79 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -126,22 +126,18 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } /** print a friendly help message */ - def helpCommand(line: String): Result = { - if (line == "") helpSummary() - else uniqueCommand(line) match { - case Some(lc) => echo("\n" + lc.help) - case _ => ambiguousError(line) - } + def helpCommand(line: String): Result = line match { + case "" => helpSummary() + case CommandMatch(cmd) => echo(f"%n${cmd.help}") + case _ => ambiguousError(line) } private def helpSummary() = { - val usageWidth = commands map (_.usageMsg.length) max - val formatStr = "%-" + usageWidth + "s %s" + val usageWidth = commands map (_.usageMsg.length) max + val formatStr = s"%-${usageWidth}s %s" - echo("All commands can be abbreviated, e.g. :he instead of :help.") + echo("All commands can be abbreviated, e.g., :he instead of :help.") - commands foreach { cmd => - echo(formatStr.format(cmd.usageMsg, cmd.help)) - } + for (cmd <- commands) echo(formatStr.format(cmd.usageMsg, cmd.help)) } private def ambiguousError(cmd: String): Result = { matchingCommands(cmd) match { @@ -150,14 +146,14 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } Result(keepRunning = true, None) } + // this lets us add commands willy-nilly and only requires enough command to disambiguate private def matchingCommands(cmd: String) = commands filter (_.name startsWith cmd) - private def uniqueCommand(cmd: String): Option[LoopCommand] = { - // this lets us add commands willy-nilly and only requires enough command to disambiguate - matchingCommands(cmd) match { - case List(x) => Some(x) - // exact match OK even if otherwise appears ambiguous - case xs => xs find (_.name == cmd) - } + private object CommandMatch { + def unapply(name: String): Option[LoopCommand] = + matchingCommands(name) match { + case x :: Nil => Some(x) + case xs => xs find (_.name == name) // accept an exact match + } } /** Show the history */ @@ -701,20 +697,23 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } /** Run one command submitted by the user. Two values are returned: - * (1) whether to keep running, (2) the line to record for replay, - * if any. */ + * (1) whether to keep running, (2) the line to record for replay, if any. + */ def command(line: String): Result = { - if (line startsWith ":") { - val cmd = line.tail takeWhile (x => !x.isWhitespace) - uniqueCommand(cmd) match { - case Some(lc) => lc(line.tail stripPrefix cmd dropWhile (_.isWhitespace)) - case _ => ambiguousError(cmd) - } - } + if (line startsWith ":") colonCommand(line.tail) else if (intp.global == null) Result(keepRunning = false, None) // Notice failure to create compiler else Result(keepRunning = true, interpretStartingWith(line)) } + private val commandish = """(\S+)(?:\s+)?(.*)""".r + + private def colonCommand(line: String): Result = line.trim match { + case "" => helpSummary() + case commandish(CommandMatch(cmd), rest) => cmd(rest) + case commandish(name, _) => ambiguousError(name) + case _ => echo("?") + } + private def readWhile(cond: String => Boolean) = { Iterator continually in.readLine("") takeWhile (x => x != null && cond(x)) } diff --git a/test/files/pos/t7683-stop-after-parser/ThePlugin.scala b/test/files/pos/t7683-stop-after-parser/ThePlugin.scala new file mode 100644 index 0000000000..cd800781dc --- /dev/null +++ b/test/files/pos/t7683-stop-after-parser/ThePlugin.scala @@ -0,0 +1,31 @@ +package scala.test.plugins + +import scala.tools.nsc +import nsc.Global +import nsc.Phase +import nsc.plugins.Plugin +import nsc.plugins.PluginComponent + +class ThePlugin(val global: Global) extends Plugin { + import global._ + + val name = "timebomb" + val description = "Explodes if run. Maybe I haven't implemented it yet." + val components = List[PluginComponent](thePhase1) + + private object thePhase1 extends PluginComponent { + val global = ThePlugin.this.global + + val runsAfter = List[String]("parser") + override val runsBefore = List[String]("namer") + val phaseName = ThePlugin.this.name + + def newPhase(prev: Phase) = new ThePhase(prev) + } + + private class ThePhase(prev: Phase) extends Phase(prev) { + override def name = ThePlugin.this.name + override def run = ??? + } +} + diff --git a/test/files/pos/t7683-stop-after-parser/sample_2.flags b/test/files/pos/t7683-stop-after-parser/sample_2.flags new file mode 100644 index 0000000000..99672cdfd3 --- /dev/null +++ b/test/files/pos/t7683-stop-after-parser/sample_2.flags @@ -0,0 +1 @@ +-Xplugin:. -Xplugin-require:timebomb -Ystop-after:parser diff --git a/test/files/pos/t7683-stop-after-parser/sample_2.scala b/test/files/pos/t7683-stop-after-parser/sample_2.scala new file mode 100644 index 0000000000..7eb11b8204 --- /dev/null +++ b/test/files/pos/t7683-stop-after-parser/sample_2.scala @@ -0,0 +1,6 @@ + +package sample + +// just a sample that is compiled with the explosive plugin disabled +object Sample extends App { +} diff --git a/test/files/pos/t7683-stop-after-parser/scalac-plugin.xml b/test/files/pos/t7683-stop-after-parser/scalac-plugin.xml new file mode 100644 index 0000000000..2558d6fd03 --- /dev/null +++ b/test/files/pos/t7683-stop-after-parser/scalac-plugin.xml @@ -0,0 +1,5 @@ +<plugin> + <name>ignored</name> + <classname>scala.test.plugins.ThePlugin</classname> +</plugin> + diff --git a/test/files/pos/t9018.scala b/test/files/pos/t9018.scala new file mode 100644 index 0000000000..7fb4cf21b3 --- /dev/null +++ b/test/files/pos/t9018.scala @@ -0,0 +1,16 @@ +object TestObject { + + def m(i: Int): AnyRef = i match { + case 0 => new C() + case 1 => Some(E.A).getOrElse("") + } + + class C extends Ordered[C] { + def compare(that: C): Int = ??? + } + + object E extends Enumeration { + type CharacterClass = Value + val A = Value + } +} diff --git a/test/files/run/priorityQueue.scala b/test/files/run/priorityQueue.scala deleted file mode 100644 index 327d8bf137..0000000000 --- a/test/files/run/priorityQueue.scala +++ /dev/null @@ -1,373 +0,0 @@ - - - -import scala.collection.mutable.PriorityQueue - - - - - - -// populate a priority queue a few different ways and make sure they all seem equal -object Test { - - def main(args: Array[String]) { - // testInsertionsAndEqualities - // testIntensiveEnqueueDequeue - // testTails - // testInits - // testFilters - // testDrops - // testEquality - // testMisc - // testReverse - // testToList - // testForeach - } - - // def testInsertionsAndEqualities { - // import scala.util.Random.nextInt - // val pq1 = new PriorityQueue[String] - // val pq2 = new PriorityQueue[String] - // val pq3 = new PriorityQueue[String] - // val pq4 = new PriorityQueue[String] - - // val strings = (1 to 20).toList map (i => List.fill((Math.abs(nextInt % 20)) + 1)("x").mkString) - - // pq1 ++= strings - // pq2 ++= strings.reverse - // for (s <- strings) pq3 += s - // for (s <- strings.reverse) pq4 += s - - // val pqs = List(pq1, pq2, pq3, pq4, pq1.clone, pq2.clone) - - // for (queue1 <- pqs ; queue2 <- pqs) { - // val l1: List[String] = queue1.dequeueAll[String, List[String]] - // val l2: List[String] = queue2.dequeueAll[String, List[String]] - // assert(l1 == l2) - // assert(queue1.max == queue2.max) - // } - - // assertPriorityDestructive(pq1) - // } - - // not a sequence anymore, Mildred - // def testIndexing { - // val pq = new PriorityQueue[Char] - // "The quick brown fox jumps over the lazy dog".foreach(pq += _) - - // // val iter = pq.iterator - // // while (iter.hasNext) println("`" + iter.next + "`") - // assert(pq(0) == 'z') - // assert(pq(1) == 'y') - // assert(pq(2) == 'x') - // assert(pq(3) == 'w') - // assert(pq(4) == 'v') - // assert(pq(5) == 'u') - // assert(pq(7) == 't') - // assert(pq(8) == 's') - // assert(pq(9) == 'r') - // assert(pq(10) == 'r') - - // pq.clear - // "abcdefghijklmnopqrstuvwxyz".foreach(pq += _) - // for (i <- 0 until 26) assert(pq(i) == ('z' - i)) - - // val intpq = new PriorityQueue[Int] - // val intlst = new collection.mutable.ArrayBuffer ++ (0 until 100) - // val random = new util.Random(101) - // while (intlst.nonEmpty) { - // val idx = random.nextInt(intlst.size) - // intpq += intlst(idx) - // intlst.remove(idx) - // } - // for (i <- 0 until 100) assert(intpq(i) == (99 - i)) - // } - - // def testTails { - // val pq = new PriorityQueue[Int] - // for (i <- 0 until 10) pq += i * 4321 % 200 - - // assert(pq.size == 10) - // assert(pq.nonEmpty) - - // val tailpq = pq.tail - // // pq.printstate - // // tailpq.printstate - // assert(tailpq.size == 9) - // assert(tailpq.nonEmpty) - // assertPriorityDestructive(tailpq) - // } - - // def assertPriorityDestructive[A](pq: PriorityQueue[A])(implicit ord: Ordering[A]) { - // import ord._ - // var prev: A = null.asInstanceOf[A] - // while (pq.nonEmpty) { - // val curr = pq.dequeue - // if (prev != null) assert(curr <= prev) - // prev = curr - // } - // } - - // def testInits { - // val pq = new PriorityQueue[Long] - // for (i <- 0 until 20) pq += (i + 313) * 111 % 300 - - // assert(pq.size == 20) - - // val initpq = pq.init - // assert(initpq.size == 19) - // assertPriorityDestructive(initpq) - // } - - // def testFilters { - // val pq = new PriorityQueue[String] - // for (i <- 0 until 100) pq += "Some " + (i * 312 % 200) - - // val filpq = pq.filter(_.indexOf('0') != -1) - // assertPriorityDestructive(filpq) - // } - - // def testIntensiveEnqueueDequeue { - // val pq = new PriorityQueue[Int] - - // testIntensive(1000, pq) - // pq.clear - // testIntensive(200, pq) - // } - - // def testIntensive(sz: Int, pq: PriorityQueue[Int]) { - // val lst = new collection.mutable.ArrayBuffer[Int] ++ (0 until sz) - // val rand = new util.Random(7) - // while (lst.nonEmpty) { - // val idx = rand.nextInt(lst.size) - // pq.enqueue(lst(idx)) - // lst.remove(idx) - // if (rand.nextDouble < 0.25 && pq.nonEmpty) pq.dequeue - // assertPriority(pq) - // } - // } - - // def testDrops { - // val pq = new PriorityQueue[Int] - // pq ++= (0 until 100) - // val droppq = pq.drop(50) - // assertPriority(droppq) - - // pq.clear - // pq ++= droppq - // assertPriorityDestructive(droppq) - // assertPriority(pq) - // assertPriorityDestructive(pq) - // } - - // // your sequence days have ended, foul priority queue - // // def testUpdates { - // // val pq = new PriorityQueue[Int] - // // pq ++= (0 until 36) - // // assertPriority(pq) - - // // pq(0) = 100 - // // assert(pq(0) == 100) - // // assert(pq.dequeue == 100) - // // assertPriority(pq) - - // // pq.clear - - // // pq ++= (1 to 100) - // // pq(5) = 200 - // // assert(pq(0) == 200) - // // assert(pq(1) == 100) - // // assert(pq(2) == 99) - // // assert(pq(3) == 98) - // // assert(pq(4) == 97) - // // assert(pq(5) == 96) - // // assert(pq(6) == 94) - // // assert(pq(7) == 93) - // // assert(pq(98) == 2) - // // assert(pq(99) == 1) - // // assertPriority(pq) - - // // pq(99) = 450 - // // assert(pq(0) == 450) - // // assert(pq(1) == 200) - // // assert(pq(99) == 2) - // // assertPriority(pq) - - // // pq(1) = 0 - // // assert(pq(1) == 100) - // // assert(pq(99) == 0) - // // assertPriority(pq) - // // assertPriorityDestructive(pq) - // // } - - // def testEquality { - // val pq1 = new PriorityQueue[Int] - // val pq2 = new PriorityQueue[Int] - - // pq1 ++= (0 until 50) - // var i = 49 - // while (i >= 0) { - // pq2 += i - // i -= 1 - // } - // assert(pq1 == pq2) - // assertPriority(pq2) - - // pq1 += 100 - // assert(pq1 != pq2) - // pq2 += 100 - // assert(pq1 == pq2) - // pq2 += 200 - // assert(pq1 != pq2) - // pq1 += 200 - // assert(pq1 == pq2) - // assertPriorityDestructive(pq1) - // assertPriorityDestructive(pq2) - // } - - // def testMisc { - // val pq = new PriorityQueue[Int] - // pq ++= (0 until 100) - // assert(pq.size == 100) - - // val (p1, p2) = pq.partition(_ < 50) - // assertPriorityDestructive(p1) - // assertPriorityDestructive(p2) - - // val spq = pq.slice(25, 75) - // assertPriorityDestructive(spq) - - // pq.clear - // pq ++= (0 until 10) - // pq += 5 - // assert(pq.size == 11) - - // val ind = pq.lastIndexWhere(_ == 5) - // assert(ind == 5) - // assertPriorityDestructive(pq) - - // pq.clear - // pq ++= (0 until 10) - // assert(pq.lastIndexWhere(_ == 9) == 0) - // assert(pq.lastIndexOf(8) == 1) - // assert(pq.lastIndexOf(7) == 2) - - // pq += 5 - // pq += 9 - // assert(pq.lastIndexOf(9) == 1) - // assert(pq.lastIndexWhere(_ % 2 == 1) == 10) - // assert(pq.lastIndexOf(5) == 6) - - // val lst = pq.reverseIterator.toList - // for (i <- 0 until 5) assert(lst(i) == i) - // assert(lst(5) == 5) - // assert(lst(6) == 5) - // assert(lst(7) == 6) - // assert(lst(8) == 7) - // assert(lst(9) == 8) - // assert(lst(10) == 9) - // assert(lst(11) == 9) - - // pq.clear - // assert(pq.reverseIterator.toList.isEmpty) - - // pq ++= (50 to 75) - // assert(pq.lastIndexOf(70) == 5) - - // pq += 55 - // pq += 70 - // assert(pq.lastIndexOf(70) == 6) - // assert(pq.lastIndexOf(55) == 22) - // assert(pq.lastIndexOf(55, 21) == 21) - // assert(pq.lastIndexWhere(_ > 54) == 22) - // assert(pq.lastIndexWhere(_ > 54, 21) == 21) - // assert(pq.lastIndexWhere(_ > 69, 5) == 5) - // } - - // def testReverse { - // val pq = new PriorityQueue[(Int, Int)] - // pq ++= (for (i <- 0 until 10) yield (i, i * i % 10)) - - // assert(pq.reverse.size == pq.reverseIterator.toList.size) - // assert((pq.reverse zip pq.reverseIterator.toList).forall(p => p._1 == p._2)) - // assert(pq.reverse.sameElements(pq.reverseIterator.toSeq)) - // assert(pq.reverse(0)._1 == pq(9)._1) - // assert(pq.reverse(1)._1 == pq(8)._1) - // assert(pq.reverse(4)._1 == pq(5)._1) - // assert(pq.reverse(9)._1 == pq(0)._1) - - // pq += ((7, 7)) - // pq += ((7, 9)) - // pq += ((7, 8)) - // assert(pq.reverse.reverse == pq) - // assert(pq.reverse.lastIndexWhere(_._2 == 6) == 6) - // assertPriorityDestructive(pq.reverse.reverse) - - // val iq = new PriorityQueue[Int] - // iq ++= (0 until 50) - // assert(iq.reverse == iq.reverseIterator.toSeq) - // assert(iq.reverse.reverse == iq) - - // iq += 25 - // iq += 40 - // iq += 10 - // assert(iq.reverse == iq.reverseIterator.toList) - // assert(iq.reverse.reverse == iq) - // assert(iq.reverse.lastIndexWhere(_ == 10) == 11) - // assertPriorityDestructive(iq.reverse.reverse) - // } - - // def testToList { - // val pq = new PriorityQueue[Int] - - // pq += 1 - // pq += 4 - // pq += 0 - // pq += 5 - // pq += 3 - // pq += 2 - // assert(pq.toList == pq) - // assert(pq == List(5, 4, 3, 2, 1, 0)) - // assert(pq.reverse == List(0, 1, 2, 3, 4, 5)) - - // pq.clear - // for (i <- -50 until 50) pq += i - // assert(pq.toList == pq) - // assert(pq.toList == (-50 until 50).reverse) - // } - - // def testForeach { - // val pq = new PriorityQueue[Char] - - // pq += 't' - // pq += 'o' - // pq += 'b' - // pq += 'y' - // val sbf = new StringBuilder - // val sbi = new StringBuilder - // pq.foreach(sbf += _) - // pq.iterator.foreach(sbi += _) - // assert(sbf.toString == sbi.toString) - // assert(sbf.toString == "ytob") - // } - -} - - - - - - - - - - - - - - - - - - diff --git a/test/files/run/t9003.flags b/test/files/run/t9003.flags new file mode 100644 index 0000000000..49d036a887 --- /dev/null +++ b/test/files/run/t9003.flags @@ -0,0 +1 @@ +-optimize diff --git a/test/files/run/t9003.scala b/test/files/run/t9003.scala new file mode 100644 index 0000000000..4f24712201 --- /dev/null +++ b/test/files/run/t9003.scala @@ -0,0 +1,71 @@ +object Single { + var i = 0 + def isEmpty = false + def get = i + def unapply(a: Single.type) = this +} + +object Product { + var i = 0 + def _1: Int = i + def _2: String = ??? + def productArity = 2 + def unapply(a: Product.type) = this + def isEmpty = false + def get: this.type = this +} + +object Sequence { + var i = 0 + def apply(n: Int): Int = i + def length = 2 + def unapplySeq(a: Sequence.type) = this + def isEmpty = false + def get = this +} + +object Test { + def main(args: Array[String]): Unit = { + def assertZero(i: Int) = assert(i == 0) + + Single match { + case Single(i) => + Single.i = 1 + assertZero(i) // fails under -optimize + } + + Product match { + case Product(i, _) => + Product.i = 1 + assertZero(i) // fails under -optimize + } + + Sequence match { + case Sequence(i, _ @ _*) => + Sequence.i = 1 + assertZero(i) // okay + } + + Sequence.i = 0 + Sequence match { + case Sequence(_, i) => + Sequence.i = 1 + assertZero(i) // okay + } + + val buffer = collection.mutable.Buffer(0, 0) + buffer match { + case Seq(_, i) => + buffer(1) = 1 + assertZero(i) // failed + } + + case class CaseSequence(as: Int*) + val buffer1 = collection.mutable.Buffer(0, 0) + CaseSequence(buffer1: _*) match { + case CaseSequence(_, i) => + buffer1(1) = 1 + assertZero(i) // failed + } + } +} diff --git a/test/files/run/t9027.check b/test/files/run/t9027.check new file mode 100644 index 0000000000..3429254286 --- /dev/null +++ b/test/files/run/t9027.check @@ -0,0 +1,19 @@ +{ + { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, true)); + $buf.$amp$plus(new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true)); + $buf + }; + println("hello, world.") +} +{ + { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, true)); + $buf.$amp$plus(new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true)); + $buf.$amp$plus(new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true)); + $buf + }; + println("hello, world.") +} diff --git a/test/files/run/t9027.scala b/test/files/run/t9027.scala new file mode 100644 index 0000000000..26238147da --- /dev/null +++ b/test/files/run/t9027.scala @@ -0,0 +1,15 @@ + +// used to be parsed as .println +object Test extends App { + import reflect.runtime._, universe._ + + val trees = List( + q"""<a/><b/> + println("hello, world.")""", + q"""<a/> + <b/> + <c/> + println("hello, world.")""" + ) + trees foreach println +} diff --git a/test/junit/scala/collection/immutable/ListTest.scala b/test/junit/scala/collection/immutable/ListTest.scala new file mode 100644 index 0000000000..1006801029 --- /dev/null +++ b/test/junit/scala/collection/immutable/ListTest.scala @@ -0,0 +1,49 @@ +package scala.collection.immutable + +import org.junit.{Assert, Test} +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.ref.WeakReference + +@RunWith(classOf[JUnit4]) +class ListTest { + /** + * Test that empty iterator does not hold reference + * to complete List + */ + @Test + def testIteratorGC(): Unit = { + var num = 0 + var emptyIterators = Seq.empty[(Iterator[Int], WeakReference[List[Int]])] + + do { + val list = List.fill(10000)(num) + val ref = WeakReference(list) + + val i = list.iterator + + while (i.hasNext) i.next() + + emptyIterators = (i, ref) +: emptyIterators + + num+=1 + } while (emptyIterators.forall(_._2.get.isDefined) && num<1000) + + // check something is result to protect from JIT optimizations + for ((i, _) <- emptyIterators) { + Assert.assertTrue(i.isEmpty) + } + + // await gc up to ~5 seconds + var forceLoops = 50 + while (emptyIterators.forall(_._2.get.isDefined) && forceLoops>0) { + System.gc() + Thread.sleep(100) + forceLoops -= 1 + } + + // real assertion + Assert.assertTrue(emptyIterators.exists(_._2.get.isEmpty)) + } +} diff --git a/test/junit/scala/collection/immutable/PagedSeqTest.scala b/test/junit/scala/collection/immutable/PagedSeqTest.scala index 5f83cf6f31..2b576a3655 100644 --- a/test/junit/scala/collection/immutable/PagedSeqTest.scala +++ b/test/junit/scala/collection/immutable/PagedSeqTest.scala @@ -5,12 +5,24 @@ import org.junit.runners.JUnit4 import org.junit.Test import org.junit.Assert._ -/* Test for SI-6615 */ @RunWith(classOf[JUnit4]) class PagedSeqTest { + // should not NPE, and should equal the given Seq @Test - def rovingDoesNotNPE(): Unit = { - // should not NPE, and should equal the given Seq + def test_SI6615(): Unit = { assertEquals(Seq('a'), PagedSeq.fromStrings(List.fill(5000)("a")).slice(4096, 4097)) } + + // Slices shouldn't read outside where they belong + @Test + def test_SI6519 { + var readAttempt = 0 + val sideEffectingIterator = new Iterator[Int] { + def hasNext = readAttempt < 65536 + def next = { readAttempt += 1; readAttempt } + } + val s = PagedSeq.fromIterator(sideEffectingIterator).slice(0,2).mkString + assertEquals(s, "12") + assert(readAttempt <= 4096) + } } diff --git a/test/junit/scala/math/BigDecimalTest.scala b/test/junit/scala/math/BigDecimalTest.scala index d1ba96fcc8..c7a63da890 100644 --- a/test/junit/scala/math/BigDecimalTest.scala +++ b/test/junit/scala/math/BigDecimalTest.scala @@ -222,4 +222,10 @@ class BigDecimalTest { for (a <- different; b <- different if (a ne b)) assert(a != b, "BigDecimal representations of Double mistakenly conflated") } + + // Make sure hash code agrees with decimal representation of Double + @Test + def test_SI8970() { + assert((0.1).## == BigDecimal(0.1).##) + } } diff --git a/versions.properties b/versions.properties index 454df6b757..d24a3bb952 100644 --- a/versions.properties +++ b/versions.properties @@ -17,7 +17,7 @@ scala.binary.version=2.11 scala.full.version=2.11.2 # external modules shipped with distribution, as specified by scala-library-all's pom -scala-xml.version.number=1.0.2 +scala-xml.version.number=1.0.3 scala-parser-combinators.version.number=1.0.2 scala-continuations-plugin.version.number=1.0.2 scala-continuations-library.version.number=1.0.2 |