summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala26
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala35
-rw-r--r--src/library/scala/Symbol.scala5
-rw-r--r--src/library/scala/collection/IndexedSeq.scala10
-rw-r--r--src/library/scala/collection/generic/GenTraversableFactory.scala9
-rw-r--r--src/library/scala/collection/generic/IndexedSeqFactory.scala21
-rw-r--r--src/library/scala/collection/immutable/IndexedSeq.scala5
-rw-r--r--src/library/scala/collection/immutable/Vector.scala33
-rw-r--r--src/library/scala/collection/mutable/ListBuffer.scala98
-rw-r--r--src/library/scala/collection/mutable/MultiMap.scala35
-rw-r--r--src/reflect/scala/reflect/internal/StdAttachments.scala17
-rw-r--r--test/files/neg/t6663.check6
-rw-r--r--test/files/neg/t6663.scala19
-rw-r--r--test/files/pos/t6551.scala13
-rw-r--r--test/files/run/t6023.check12
-rw-r--r--test/files/run/t6023.scala17
-rw-r--r--test/files/run/t6150.scala44
-rw-r--r--test/files/run/t6632.check3
-rw-r--r--test/files/run/t6632.scala29
-rw-r--r--test/files/run/t6633.check3
-rw-r--r--test/files/run/t6633.scala33
-rw-r--r--test/files/run/t6634.check31
-rw-r--r--test/files/run/t6634.scala80
-rw-r--r--test/files/run/t6663.check1
-rw-r--r--test/files/run/t6663.scala17
-rw-r--r--test/files/run/t6673.check1
-rw-r--r--test/files/run/t6673.scala5
-rw-r--r--test/files/run/t6695.scala18
-rw-r--r--test/files/run/t6706.scala14
30 files changed, 528 insertions, 113 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index 8dd7e7801e..3ae1210ebf 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -493,28 +493,16 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def inheritanceDiagram = makeInheritanceDiagram(this)
def contentDiagram = makeContentDiagram(this)
- def groupSearch[T](extractor: Comment => T, default: T): T = {
- // query this template
- if (comment.isDefined) {
- val entity = extractor(comment.get)
- if (entity != default) return entity
+ def groupSearch[T](extractor: Comment => Option[T]): Option[T] = {
+ val comments = comment +: linearizationTemplates.collect { case dtpl: DocTemplateImpl => dtpl.comment }
+ comments.flatten.map(extractor).flatten.headOption orElse {
+ Option(inTpl) flatMap (_.groupSearch(extractor))
}
- // query linearization
- if (!sym.isPackage)
- for (tpl <- linearizationTemplates.collect{ case dtpl: DocTemplateImpl if dtpl!=this => dtpl}) {
- val entity = tpl.groupSearch(extractor, default)
- if (entity != default) return entity
- }
- // query inTpl, going up the ownerChain
- if (inTpl != null)
- inTpl.groupSearch(extractor, default)
- else
- default
}
- def groupDescription(group: String): Option[Body] = groupSearch(_.groupDesc.get(group), if (group == defaultGroup) defaultGroupDesc else None)
- def groupPriority(group: String): Int = groupSearch(_.groupPrio.get(group) match { case Some(prio) => prio; case _ => 0 }, if (group == defaultGroup) defaultGroupPriority else 0)
- def groupName(group: String): String = groupSearch(_.groupNames.get(group) match { case Some(name) => name; case _ => group }, if (group == defaultGroup) defaultGroupName else group)
+ def groupDescription(group: String): Option[Body] = groupSearch(_.groupDesc.get(group)) orElse { if (group == defaultGroup) defaultGroupDesc else None }
+ def groupPriority(group: String): Int = groupSearch(_.groupPrio.get(group)) getOrElse { if (group == defaultGroup) defaultGroupPriority else 0 }
+ def groupName(group: String): String = groupSearch(_.groupNames.get(group)) getOrElse { if (group == defaultGroup) defaultGroupName else group }
}
abstract class PackageImpl(sym: Symbol, inTpl: PackageImpl) extends DocTemplateImpl(sym, inTpl) with Package {
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index e8a2c9f43c..acc4f7ff67 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -426,6 +426,7 @@ trait MethodSynthesis {
// spot that brand of them. In other words it's an artifact of the implementation.
val tpt = derivedSym.tpe.finalResultType match {
case ExistentialType(_, _) => TypeTree()
+ case _ if mods.isDeferred => TypeTree()
case tp => TypeTree(tp)
}
tpt setPos derivedSym.pos.focus
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index d3847de894..a2aca45e8f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1100,6 +1100,10 @@ trait Typers extends Modes with Adaptations with Tags {
instantiateToMethodType(mt)
case _ =>
+ def shouldInsertApply(tree: Tree) = inAllModes(mode, EXPRmode | FUNmode) && (tree.tpe match {
+ case _: MethodType | _: OverloadedType | _: PolyType => false
+ case _ => applyPossible
+ })
def applyPossible = {
def applyMeth = member(adaptToName(tree, nme.apply), nme.apply)
dyna.acceptsApplyDynamic(tree.tpe) || (
@@ -1113,14 +1117,12 @@ trait Typers extends Modes with Adaptations with Tags {
adaptType()
else if (
inExprModeButNot(mode, FUNmode) && !tree.isDef && // typechecking application
- tree.symbol != null && tree.symbol.isTermMacro) // of a macro
+ tree.symbol != null && tree.symbol.isTermMacro && // of a macro
+ !tree.attachments.get[SuppressMacroExpansionAttachment.type].isDefined)
macroExpand(this, tree, mode, pt)
else if ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode))
adaptConstrPattern()
- else if (inAllModes(mode, EXPRmode | FUNmode) &&
- !tree.tpe.isInstanceOf[MethodType] &&
- !tree.tpe.isInstanceOf[OverloadedType] &&
- applyPossible)
+ else if (shouldInsertApply(tree))
insertApply()
else if (!context.undetparams.isEmpty && !inPolyMode(mode)) { // (9)
assert(!inHKMode(mode), modeString(mode)) //@M
@@ -3935,9 +3937,14 @@ trait Typers extends Modes with Adaptations with Tags {
case t: ValOrDefDef => t.rhs
case t => t
}
- val (outer, explicitTargs) = cxTree1 match {
+ val cxTree2 = cxTree1 match {
+ case Typed(t, tpe) => t // ignore outer type annotation
+ case t => t
+ }
+ val (outer, explicitTargs) = cxTree2 match {
case TypeApply(fun, targs) => (fun, targs)
case Apply(TypeApply(fun, targs), args) => (Apply(fun, args), targs)
+ case Select(TypeApply(fun, targs), nme) => (Select(fun, nme), targs)
case t => (t, Nil)
}
def hasNamedArg(as: List[Tree]) = as.collectFirst{case AssignOrNamedArg(lhs, rhs) =>}.nonEmpty
@@ -5215,9 +5222,9 @@ trait Typers extends Modes with Adaptations with Tags {
// find out whether the programmer is trying to eta-expand a macro def
// to do that we need to typecheck the tree first (we need a symbol of the eta-expandee)
// that typecheck must not trigger macro expansions, so we explicitly prohibit them
- // Q: "but, " - you may ask - ", `typed1` doesn't call adapt, which does macro expansion, so why explicit check?"
- // A: solely for robustness reasons. this mechanism might change in the future, which might break unprotected code
- val exprTyped = context.withMacrosDisabled(typed1(expr, mode, pt))
+ // however we cannot do `context.withMacrosDisabled`
+ // because `expr` might contain nested macro calls (see SI-6673)
+ val exprTyped = typed1(expr updateAttachment SuppressMacroExpansionAttachment, mode, pt)
exprTyped match {
case macroDef if macroDef.symbol != null && macroDef.symbol.isTermMacro && !macroDef.symbol.isErroneous =>
MacroEtaError(exprTyped)
@@ -5361,8 +5368,14 @@ trait Typers extends Modes with Adaptations with Tags {
}
def typedTypeTree(tree: TypeTree) = {
- if (tree.original != null)
- tree setType typedType(tree.original, mode).tpe
+ if (tree.original != null) {
+ val newTpt = typedType(tree.original, mode)
+ tree setType newTpt.tpe
+ newTpt match {
+ case tt @ TypeTree() => tree setOriginal tt.original
+ case _ => tree
+ }
+ }
else
// we should get here only when something before failed
// and we try again (@see tryTypedApply). In that case we can assign
diff --git a/src/library/scala/Symbol.scala b/src/library/scala/Symbol.scala
index 723c05a30c..4fead7a50c 100644
--- a/src/library/scala/Symbol.scala
+++ b/src/library/scala/Symbol.scala
@@ -69,6 +69,11 @@ private[scala] abstract class UniquenessCache[K, V >: Null]
val res = cached()
if (res != null) res
else {
+ // If we don't remove the old String key from the map, we can
+ // wind up with one String as the key and a different String as
+ // as the name field in the Symbol, which can lead to surprising
+ // GC behavior and duplicate Symbols. See SI-6706.
+ map remove name
val sym = valueFromKey(name)
map.put(name, new WeakReference(sym))
sym
diff --git a/src/library/scala/collection/IndexedSeq.scala b/src/library/scala/collection/IndexedSeq.scala
index e30d2f07bb..63e5adf428 100644
--- a/src/library/scala/collection/IndexedSeq.scala
+++ b/src/library/scala/collection/IndexedSeq.scala
@@ -28,8 +28,14 @@ trait IndexedSeq[+A] extends Seq[A]
* @define coll indexed sequence
* @define Coll `IndexedSeq`
*/
-object IndexedSeq extends SeqFactory[IndexedSeq] {
- implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
+object IndexedSeq extends IndexedSeqFactory[IndexedSeq] {
+ // A single CBF which can be checked against to identify
+ // an indexed collection type.
+ override val ReusableCBF: GenericCanBuildFrom[Nothing] = new GenericCanBuildFrom[Nothing] {
+ override def apply() = newBuilder[Nothing]
+ }
def newBuilder[A]: Builder[A, IndexedSeq[A]] = immutable.IndexedSeq.newBuilder[A]
+ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] =
+ ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
}
diff --git a/src/library/scala/collection/generic/GenTraversableFactory.scala b/src/library/scala/collection/generic/GenTraversableFactory.scala
index d5edf5961e..a43862abaf 100644
--- a/src/library/scala/collection/generic/GenTraversableFactory.scala
+++ b/src/library/scala/collection/generic/GenTraversableFactory.scala
@@ -36,15 +36,12 @@ import scala.language.higherKinds
* @see GenericCanBuildFrom
*/
abstract class GenTraversableFactory[CC[X] <: GenTraversable[X] with GenericTraversableTemplate[X, CC]]
- extends GenericCompanion[CC] {
+extends GenericCompanion[CC] {
- // A default implementation of GenericCanBuildFrom which can be cast
- // to whatever is desired.
- private class ReusableCBF extends GenericCanBuildFrom[Nothing] {
+ private[this] val ReusableCBFInstance: GenericCanBuildFrom[Nothing] = new GenericCanBuildFrom[Nothing] {
override def apply() = newBuilder[Nothing]
}
- // Working around SI-4789 by using a lazy val instead of an object.
- lazy val ReusableCBF: GenericCanBuildFrom[Nothing] = new ReusableCBF
+ def ReusableCBF: GenericCanBuildFrom[Nothing] = ReusableCBFInstance
/** A generic implementation of the `CanBuildFrom` trait, which forwards
* all calls to `apply(from)` to the `genericBuilder` method of
diff --git a/src/library/scala/collection/generic/IndexedSeqFactory.scala b/src/library/scala/collection/generic/IndexedSeqFactory.scala
new file mode 100644
index 0000000000..200d033c2d
--- /dev/null
+++ b/src/library/scala/collection/generic/IndexedSeqFactory.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.collection
+package generic
+
+import language.higherKinds
+
+/** A template for companion objects of IndexedSeq and subclasses thereof.
+ *
+ * @since 2.10
+ */
+abstract class IndexedSeqFactory[CC[X] <: IndexedSeq[X] with GenericTraversableTemplate[X, CC]] extends SeqFactory[CC] {
+ override def ReusableCBF: GenericCanBuildFrom[Nothing] =
+ scala.collection.IndexedSeq.ReusableCBF.asInstanceOf[GenericCanBuildFrom[Nothing]]
+}
diff --git a/src/library/scala/collection/immutable/IndexedSeq.scala b/src/library/scala/collection/immutable/IndexedSeq.scala
index e98df46c9b..bf4ba3a381 100644
--- a/src/library/scala/collection/immutable/IndexedSeq.scala
+++ b/src/library/scala/collection/immutable/IndexedSeq.scala
@@ -31,11 +31,12 @@ trait IndexedSeq[+A] extends Seq[A]
* @define coll indexed sequence
* @define Coll `IndexedSeq`
*/
-object IndexedSeq extends SeqFactory[IndexedSeq] {
+object IndexedSeq extends IndexedSeqFactory[IndexedSeq] {
class Impl[A](buf: ArrayBuffer[A]) extends AbstractSeq[A] with IndexedSeq[A] with Serializable {
def length = buf.length
def apply(idx: Int) = buf.apply(idx)
}
- implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
def newBuilder[A]: Builder[A, IndexedSeq[A]] = Vector.newBuilder[A]
+ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] =
+ ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
}
diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala
index dff221ad05..f083e80175 100644
--- a/src/library/scala/collection/immutable/Vector.scala
+++ b/src/library/scala/collection/immutable/Vector.scala
@@ -18,16 +18,10 @@ import scala.collection.parallel.immutable.ParVector
/** Companion object to the Vector class
*/
-object Vector extends SeqFactory[Vector] {
- private[collection] class VectorReusableCBF extends GenericCanBuildFrom[Nothing] {
- override def apply() = newBuilder[Nothing]
- }
-
- private val VectorReusableCBF: GenericCanBuildFrom[Nothing] = new VectorReusableCBF
-
- implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Vector[A]] =
- VectorReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Vector[A]]]
+object Vector extends IndexedSeqFactory[Vector] {
def newBuilder[A]: Builder[A, Vector[A]] = new VectorBuilder[A]
+ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Vector[A]] =
+ ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
private[immutable] val NIL = new Vector[Nothing](0, 0, 0)
override def empty[A]: Vector[A] = NIL
}
@@ -137,20 +131,17 @@ override def companion: GenericCompanion[Vector] = Vector
// SeqLike api
- override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
- case _: Vector.VectorReusableCBF => updateAt(index, elem).asInstanceOf[That] // just ignore bf
- case _ => super.updated(index, elem)(bf)
- }
+ override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That =
+ if (bf eq IndexedSeq.ReusableCBF) updateAt(index, elem).asInstanceOf[That] // just ignore bf
+ else super.updated(index, elem)(bf)
- override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
- case _: Vector.VectorReusableCBF => appendFront(elem).asInstanceOf[That] // just ignore bf
- case _ => super.+:(elem)(bf)
- }
+ override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That =
+ if (bf eq IndexedSeq.ReusableCBF) appendFront(elem).asInstanceOf[That] // just ignore bf
+ else super.+:(elem)(bf)
- override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
- case _: Vector.VectorReusableCBF => appendBack(elem).asInstanceOf[That] // just ignore bf
- case _ => super.:+(elem)(bf)
- }
+ override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That =
+ if (bf eq IndexedSeq.ReusableCBF) appendBack(elem).asInstanceOf[That] // just ignore bf
+ else super.:+(elem)(bf)
override def take(n: Int): Vector[A] = {
if (n <= 0)
diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala
index 53b2b57f50..67af4a6bd6 100644
--- a/src/library/scala/collection/mutable/ListBuffer.scala
+++ b/src/library/scala/collection/mutable/ListBuffer.scala
@@ -129,29 +129,27 @@ final class ListBuffer[A]
* @throws Predef.IndexOutOfBoundsException if `n` is out of bounds.
*/
def update(n: Int, x: A) {
- try {
- if (exported) copy()
- if (n == 0) {
- val newElem = new :: (x, start.tail);
- if (last0 eq start) {
- last0 = newElem
- }
- start = newElem
- } else {
- var cursor = start
- var i = 1
- while (i < n) {
- cursor = cursor.tail
- i += 1
- }
- val newElem = new :: (x, cursor.tail.tail)
- if (last0 eq cursor.tail) {
- last0 = newElem
- }
- cursor.asInstanceOf[::[A]].tl = newElem
+ // We check the bounds early, so that we don't trigger copying.
+ if (n < 0 || n >= len) throw new IndexOutOfBoundsException(n.toString)
+ if (exported) copy()
+ if (n == 0) {
+ val newElem = new :: (x, start.tail);
+ if (last0 eq start) {
+ last0 = newElem
+ }
+ start = newElem
+ } else {
+ var cursor = start
+ var i = 1
+ while (i < n) {
+ cursor = cursor.tail
+ i += 1
+ }
+ val newElem = new :: (x, cursor.tail.tail)
+ if (last0 eq cursor.tail) {
+ last0 = newElem
}
- } catch {
- case ex: Exception => throw new IndexOutOfBoundsException(n.toString())
+ cursor.asInstanceOf[::[A]].tl = newElem
}
}
@@ -212,34 +210,31 @@ final class ListBuffer[A]
* @throws Predef.IndexOutOfBoundsException if `n` is out of bounds.
*/
def insertAll(n: Int, seq: Traversable[A]) {
- try {
- if (exported) copy()
- var elems = seq.toList.reverse
- len += elems.length
- if (n == 0) {
- while (!elems.isEmpty) {
- val newElem = new :: (elems.head, start)
- if (start.isEmpty) last0 = newElem
- start = newElem
- elems = elems.tail
- }
- } else {
- var cursor = start
- var i = 1
- while (i < n) {
- cursor = cursor.tail
- i += 1
- }
- while (!elems.isEmpty) {
- val newElem = new :: (elems.head, cursor.tail)
- if (cursor.tail.isEmpty) last0 = newElem
- cursor.asInstanceOf[::[A]].tl = newElem
- elems = elems.tail
- }
+ // We check the bounds early, so that we don't trigger copying.
+ if (n < 0 || n > len) throw new IndexOutOfBoundsException(n.toString)
+ if (exported) copy()
+ var elems = seq.toList.reverse
+ len += elems.length
+ if (n == 0) {
+ while (!elems.isEmpty) {
+ val newElem = new :: (elems.head, start)
+ if (start.isEmpty) last0 = newElem
+ start = newElem
+ elems = elems.tail
+ }
+ } else {
+ var cursor = start
+ var i = 1
+ while (i < n) {
+ cursor = cursor.tail
+ i += 1
+ }
+ while (!elems.isEmpty) {
+ val newElem = new :: (elems.head, cursor.tail)
+ if (cursor.tail.isEmpty) last0 = newElem
+ cursor.asInstanceOf[::[A]].tl = newElem
+ elems = elems.tail
}
- } catch {
- case ex: Exception =>
- throw new IndexOutOfBoundsException(n.toString())
}
}
@@ -249,7 +244,12 @@ final class ListBuffer[A]
* @param n the index which refers to the first element to remove.
* @param count the number of elements to remove.
*/
+ @annotation.migration("Invalid input values will be rejected in future releases.", "2.11")
override def remove(n: Int, count: Int) {
+ if (n >= len)
+ return
+ if (count < 0)
+ throw new IllegalArgumentException(s"removing negative number ($count) of elements")
if (exported) copy()
val n1 = n max 0
val count1 = count min (len - n1)
diff --git a/src/library/scala/collection/mutable/MultiMap.scala b/src/library/scala/collection/mutable/MultiMap.scala
index 31c8a50a84..4635bfbe64 100644
--- a/src/library/scala/collection/mutable/MultiMap.scala
+++ b/src/library/scala/collection/mutable/MultiMap.scala
@@ -15,8 +15,36 @@ package mutable
/** A trait for mutable maps with multiple values assigned to a key.
*
* This class is typically used as a mixin. It turns maps which map `A`
- * to `Set[B]` objects into multi maps which map `A` to
- * `B` objects.
+ * to `Set[B]` objects into multimaps that map `A` to `B` objects.
+ *
+ * @example {{{
+ * // first import all necessary types from package `collection.mutable`
+ * import collection.mutable.{ HashMap, MultiMap, Set }
+ *
+ * // to create a `MultiMap` the easiest way is to mixin it into a normal
+ * // `Map` instance
+ * val mm = new HashMap[Int, Set[String]] with MultiMap[Int, String]
+ *
+ * // to add key-value pairs to a multimap it is important to use
+ * // the method `addBinding` because standard methods like `+` will
+ * // overwrite the complete key-value pair instead of adding the
+ * // value to the existing key
+ * mm.addBinding(1, "a")
+ * mm.addBinding(2, "b")
+ * mm.addBinding(1, "c")
+ *
+ * // mm now contains `Map(2 -> Set(b), 1 -> Set(c, a))`
+ *
+ * // to check if the multimap contains a value there is method
+ * // `entryExists`, which allows to traverse the including set
+ * mm.entryExists(1, _ == "a") == true
+ * mm.entryExists(1, _ == "b") == false
+ * mm.entryExists(2, _ == "b") == true
+ *
+ * // to remove a previous added value there is the method `removeBinding`
+ * mm.removeBinding(1, "a")
+ * mm.entryExists(1, _ == "a") == false
+ * }}}
*
* @define coll multimap
* @define Coll `MultiMap`
@@ -57,7 +85,8 @@ trait MultiMap[A, B] extends Map[A, Set[B]] {
this
}
- /** Removes the binding of `value` to `key` if it exists.
+ /** Removes the binding of `value` to `key` if it exists, otherwise this
+ * operation doesn't have any effect.
*
* If this was the last value assigned to the specified key, the
* set assigned to that key will be removed as well.
diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala
index 9fe443bf50..1df91a67b0 100644
--- a/src/reflect/scala/reflect/internal/StdAttachments.scala
+++ b/src/reflect/scala/reflect/internal/StdAttachments.scala
@@ -19,9 +19,26 @@ trait StdAttachments {
def setPos(newpos: Position): this.type = { pos = newpos; this }
}
+ /** When present, indicates that the host `Ident` has been created from a backquoted identifier.
+ */
case object BackquotedIdentifierAttachment
+ /** Stores the trees that give rise to a refined type to be used in reification.
+ * Unfortunately typed `CompoundTypeTree` is lacking essential info, and the reifier cannot use `CompoundTypeTree.tpe`.
+ * Therefore we need this hack (see `Reshape.toPreTyperTypeTree` for a detailed explanation).
+ */
case class CompoundTypeTreeOriginalAttachment(parents: List[Tree], stats: List[Tree])
+ /** Is added by the macro engine to the results of macro expansions.
+ * Stores the original expandee as it entered the `macroExpand` function.
+ */
case class MacroExpansionAttachment(original: Tree)
+
+ /** When present, suppresses macro expansion for the host.
+ * This is occasionally necessary, e.g. to prohibit eta-expansion of macros.
+ *
+ * Does not affect expandability of child nodes, there's context.withMacrosDisabled for that
+ * (but think thrice before using that API - see the discussion at https://github.com/scala/scala/pull/1639).
+ */
+ case object SuppressMacroExpansionAttachment
}
diff --git a/test/files/neg/t6663.check b/test/files/neg/t6663.check
new file mode 100644
index 0000000000..aa4faa4a46
--- /dev/null
+++ b/test/files/neg/t6663.check
@@ -0,0 +1,6 @@
+t6663.scala:16: error: type mismatch;
+ found : String
+ required: Int
+ var v = new C(42).foo[String].get :Int
+ ^
+one error found
diff --git a/test/files/neg/t6663.scala b/test/files/neg/t6663.scala
new file mode 100644
index 0000000000..4a358dfbc5
--- /dev/null
+++ b/test/files/neg/t6663.scala
@@ -0,0 +1,19 @@
+import language.dynamics
+
+class C(v: Any) extends Dynamic {
+ def selectDynamic[T](n: String): Option[T] = Option(v.asInstanceOf[T])
+ def applyDynamic[T](n: String)(): Option[T] = Option(v.asInstanceOf[T])
+}
+
+object Test extends App {
+ // this should be converted to
+ // C(42).selectDynamic[String]("foo").get
+ // causing a compile error.
+
+ // but, before fixing SI-6663, became
+ // C(42).selectDynamic("foo").get, ignoring
+ // the [String] type parameter
+ var v = new C(42).foo[String].get :Int
+ println(v)
+}
+
diff --git a/test/files/pos/t6551.scala b/test/files/pos/t6551.scala
new file mode 100644
index 0000000000..fb68663809
--- /dev/null
+++ b/test/files/pos/t6551.scala
@@ -0,0 +1,13 @@
+import language.dynamics
+
+object Test {
+ def main(args: Array[String]) {
+ class Lenser[T] extends Dynamic {
+ def selectDynamic(propName: String) = ???
+ }
+
+ def lens[T] = new Lenser[T]
+
+ val qq = lens[String]
+ }
+}
diff --git a/test/files/run/t6023.check b/test/files/run/t6023.check
new file mode 100644
index 0000000000..ee93565234
--- /dev/null
+++ b/test/files/run/t6023.check
@@ -0,0 +1,12 @@
+{
+ abstract trait Foo extends AnyRef {
+ <stable> <accessor> def a: Int
+ };
+ ()
+}
+{
+ abstract trait Foo extends AnyRef {
+ <stable> <accessor> def a: Int
+ };
+ ()
+}
diff --git a/test/files/run/t6023.scala b/test/files/run/t6023.scala
new file mode 100644
index 0000000000..07af3685a5
--- /dev/null
+++ b/test/files/run/t6023.scala
@@ -0,0 +1,17 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.tools.reflect.ToolBox
+
+object Test extends App {
+ // test 1: reify
+ val tree = reify{ trait Foo { val a: Int } }.tree
+ println(tree.toString)
+
+ // test 2: import and typecheck
+ val toolbox = cm.mkToolBox()
+ val ttree = toolbox.typeCheck(tree)
+ println(ttree.toString)
+
+ // test 3: import and compile
+ toolbox.eval(tree)
+}
diff --git a/test/files/run/t6150.scala b/test/files/run/t6150.scala
new file mode 100644
index 0000000000..bd8af5d460
--- /dev/null
+++ b/test/files/run/t6150.scala
@@ -0,0 +1,44 @@
+
+
+
+
+object Test {
+ import collection.{ immutable, mutable, generic }
+ def TheOneTrueCBF = collection.IndexedSeq.ReusableCBF
+
+ val cbf1 = implicitly[generic.CanBuildFrom[immutable.Vector[Int], Int, collection.IndexedSeq[Int]]]
+ val cbf2 = implicitly[generic.CanBuildFrom[immutable.IndexedSeq[Int], Int, collection.IndexedSeq[Int]]]
+ val cbf3 = implicitly[generic.CanBuildFrom[collection.IndexedSeq[Int], Int, collection.IndexedSeq[Int]]]
+
+ val cbf4 = implicitly[generic.CanBuildFrom[immutable.Vector[Int], Int, immutable.IndexedSeq[Int]]]
+ val cbf5 = implicitly[generic.CanBuildFrom[immutable.Vector[Int], Int, immutable.Vector[Int]]]
+ val cbf6 = implicitly[generic.CanBuildFrom[immutable.IndexedSeq[Int], Int, immutable.IndexedSeq[Int]]]
+
+ def check[C](v: C) = {
+ assert(v == Vector(1, 2, 3, 4))
+ assert(v.isInstanceOf[Vector[_]])
+ }
+ def checkRealMccoy(x: AnyRef) = {
+ assert(x eq TheOneTrueCBF, cbf1)
+ }
+
+ val v = immutable.Vector(1, 2, 3)
+ val iiv: immutable.IndexedSeq[Int] = immutable.Vector(1, 2, 3)
+ val iv: IndexedSeq[Int] = immutable.Vector(1, 2, 3)
+
+ def main(args: Array[String]): Unit = {
+ List(cbf1, cbf2, cbf3, cbf4, cbf5, cbf6) foreach checkRealMccoy
+ check(v.:+(4)(cbf1))
+ check(v.:+(4)(cbf2))
+ check(v.:+(4)(cbf3))
+
+ check(iiv.:+(4)(cbf2))
+ check(iiv.:+(4)(cbf3))
+
+ check(iv.:+(4)(cbf3))
+ }
+}
+
+
+
+
diff --git a/test/files/run/t6632.check b/test/files/run/t6632.check
new file mode 100644
index 0000000000..1f084b1dac
--- /dev/null
+++ b/test/files/run/t6632.check
@@ -0,0 +1,3 @@
+java.lang.IndexOutOfBoundsException: -1
+java.lang.IndexOutOfBoundsException: -2
+java.lang.IndexOutOfBoundsException: -3
diff --git a/test/files/run/t6632.scala b/test/files/run/t6632.scala
new file mode 100644
index 0000000000..c1c8d4abe0
--- /dev/null
+++ b/test/files/run/t6632.scala
@@ -0,0 +1,29 @@
+object Test extends App {
+ import collection.mutable.ListBuffer
+
+ def newLB = ListBuffer('a, 'b, 'c, 'd, 'e)
+
+ val lb0 = newLB
+
+ try {
+ lb0.insert(-1, 'x)
+ } catch {
+ case ex: IndexOutOfBoundsException => println(ex)
+ }
+
+ val lb1 = newLB
+
+ try {
+ lb1.insertAll(-2, Array('x, 'y, 'z))
+ } catch {
+ case ex: IndexOutOfBoundsException => println(ex)
+ }
+
+ val lb2 = newLB
+
+ try {
+ lb2.update(-3, 'u)
+ } catch {
+ case ex: IndexOutOfBoundsException => println(ex)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6633.check b/test/files/run/t6633.check
new file mode 100644
index 0000000000..1ff8cdbc44
--- /dev/null
+++ b/test/files/run/t6633.check
@@ -0,0 +1,3 @@
+java.lang.IndexOutOfBoundsException: 9
+replStringOf OK
+length OK
diff --git a/test/files/run/t6633.scala b/test/files/run/t6633.scala
new file mode 100644
index 0000000000..bd993c8d88
--- /dev/null
+++ b/test/files/run/t6633.scala
@@ -0,0 +1,33 @@
+object Test extends App {
+ import collection.mutable.ListBuffer
+
+ def newLB = ListBuffer('a, 'b, 'c, 'd, 'e)
+
+ val lb0 = newLB
+
+ try {
+ lb0.insert(9, 'x)
+ } catch {
+ case ex: IndexOutOfBoundsException => println(ex)
+ }
+
+ val lb1 = newLB
+
+ try {
+ lb1.insert(9, 'x)
+ } catch {
+ case ex: IndexOutOfBoundsException =>
+ }
+
+ val replStr = scala.runtime.ScalaRunTime.replStringOf(lb1, 100)
+ if (replStr == "ListBuffer('a, 'b, 'c, 'd, 'e)\n")
+ println("replStringOf OK")
+ else
+ println("replStringOf FAILED: " + replStr)
+
+ val len = lb1.length
+ if (len == 5)
+ println("length OK")
+ else
+ println("length FAILED: " + len)
+} \ No newline at end of file
diff --git a/test/files/run/t6634.check b/test/files/run/t6634.check
new file mode 100644
index 0000000000..f6cbb30c67
--- /dev/null
+++ b/test/files/run/t6634.check
@@ -0,0 +1,31 @@
+Trying lb0 ...
+Checking ...
+String OK.
+Length OK.
+
+Trying lb1 ...
+Checking ...
+String OK.
+Length OK.
+
+Trying lb2 ...
+Checking ...
+String OK.
+Length OK.
+
+Trying lb3 ...
+Checking ...
+String OK.
+Length OK.
+
+Trying lb4 ...
+Checking ...
+String OK.
+Length OK.
+
+Trying lb5 ...
+java.lang.IllegalArgumentException: removing negative number (-1) of elements
+Checking ...
+String OK.
+Length OK.
+
diff --git a/test/files/run/t6634.scala b/test/files/run/t6634.scala
new file mode 100644
index 0000000000..759e6d519d
--- /dev/null
+++ b/test/files/run/t6634.scala
@@ -0,0 +1,80 @@
+import collection.mutable.ListBuffer
+
+object Test extends App {
+ def newLB = ListBuffer('a, 'b, 'c, 'd, 'e)
+
+ val lb0 = newLB
+ println("Trying lb0 ...")
+ try {
+ lb0.remove(5, 0)
+ } catch {
+ // Not thrown in 2.10, will be thrown in 2.11
+ case ex: IndexOutOfBoundsException => println(ex)
+ }
+ checkNotCorrupted(lb0)
+
+ val lb1 = newLB
+ println("Trying lb1 ...")
+ try {
+ lb1.remove(6, 6)
+ } catch {
+ // Not thrown in 2.10, will be thrown in 2.11
+ case ex: IndexOutOfBoundsException => println(ex)
+ }
+ checkNotCorrupted(lb1)
+
+ val lb2 = newLB
+ println("Trying lb2 ...")
+ try {
+ lb2.remove(99, 6)
+ } catch {
+ // Not thrown in 2.10, will be thrown in 2.11
+ case ex: IndexOutOfBoundsException => println(ex)
+ }
+ checkNotCorrupted(lb2)
+
+ val lb3 = newLB
+ println("Trying lb3 ...")
+ try {
+ lb3.remove(1, 9)
+ } catch {
+ // Not thrown in 2.10, will be thrown in 2.11
+ case ex: IllegalArgumentException => println(ex)
+ }
+ checkNotCorrupted(lb3, "ListBuffer('a)", 1)
+
+ val lb4 = newLB
+ println("Trying lb4 ...")
+ try {
+ lb4.remove(-1, 1)
+ } catch {
+ // Not thrown in 2.10, will be thrown in 2.11
+ case ex: IndexOutOfBoundsException => println(ex)
+ }
+ checkNotCorrupted(lb4, "ListBuffer('b, 'c, 'd, 'e)", 4)
+
+ val lb5 = newLB
+ println("Trying lb5 ...")
+ try {
+ lb5.remove(1, -1)
+ } catch {
+ case ex: IllegalArgumentException => println(ex)
+ }
+ checkNotCorrupted(lb5)
+
+ // buffer should neither be changed nor corrupted after calling remove with invalid arguments
+ def checkNotCorrupted(
+ lb: ListBuffer[Symbol],
+ expectedString: String = "ListBuffer('a, 'b, 'c, 'd, 'e)",
+ expectedLength: Int = 5) = {
+ println("Checking ...")
+ val replStr = scala.runtime.ScalaRunTime.replStringOf(lb, 100)
+ if (replStr == expectedString + "\n") println("String OK.")
+ else println("!!! replStringOf FAILED: " + replStr)
+
+ val len = lb.length
+ if (len == expectedLength) println("Length OK.")
+ else println("!!! length FAILED: " + len)
+ println()
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6663.check b/test/files/run/t6663.check
new file mode 100644
index 0000000000..d81cc0710e
--- /dev/null
+++ b/test/files/run/t6663.check
@@ -0,0 +1 @@
+42
diff --git a/test/files/run/t6663.scala b/test/files/run/t6663.scala
new file mode 100644
index 0000000000..6818d286d9
--- /dev/null
+++ b/test/files/run/t6663.scala
@@ -0,0 +1,17 @@
+import language.dynamics
+
+class C(v: Any) extends Dynamic {
+ def selectDynamic[T](n: String): Option[T] = Option(v.asInstanceOf[T])
+ def applyDynamic[T](n: String)(): Option[T] = Option(v.asInstanceOf[T])
+}
+
+object Test extends App {
+ // this should be converted to
+ // C(42).selectDynamic[Int]("foo").get
+ // but, before fixing SI-6663, became
+ // C(42).selectDynamic[Nothing]("foo").get
+ // leading to a ClassCastException
+ var v = new C(42).foo[Int].get
+ println(v)
+}
+
diff --git a/test/files/run/t6673.check b/test/files/run/t6673.check
new file mode 100644
index 0000000000..ef2aa551dc
--- /dev/null
+++ b/test/files/run/t6673.check
@@ -0,0 +1 @@
+List(x)
diff --git a/test/files/run/t6673.scala b/test/files/run/t6673.scala
new file mode 100644
index 0000000000..115bbdf234
--- /dev/null
+++ b/test/files/run/t6673.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ def foo(f: String => Array[String])(s: String) = f(s)
+ val test = foo(Array(_)) _
+ println(test("x").toList)
+} \ No newline at end of file
diff --git a/test/files/run/t6695.scala b/test/files/run/t6695.scala
new file mode 100644
index 0000000000..b527238a51
--- /dev/null
+++ b/test/files/run/t6695.scala
@@ -0,0 +1,18 @@
+object Test extends App {
+ try {
+ Array("a", "b", "c") match {
+ case Array("a", "x", "c") => println("x")
+ case Array("a", "b", "x") => println("a");
+ case Array("a", "d", _*) => println("wrongly positive")
+ }
+ assert(false, "match succeeded")
+ } catch {
+ case _: MatchError => // okay
+ }
+
+ Array("a", "b", "c") match {
+ case Array("a", "x", "c") => println("x")
+ case Array("a", "b", "x") => println("a");
+ case Array("a", "b", _*) => // okay
+ }
+}
diff --git a/test/files/run/t6706.scala b/test/files/run/t6706.scala
new file mode 100644
index 0000000000..905494ca8d
--- /dev/null
+++ b/test/files/run/t6706.scala
@@ -0,0 +1,14 @@
+object Test {
+ var name = "foo" + 1
+ var s1 = Symbol(name)
+ s1 = null
+ System.gc
+ val s2 = Symbol("foo1")
+ name = null
+ System.gc
+ val s3 = Symbol("foo1")
+
+ def main(args: Array[String]): Unit = {
+ assert(s2 eq s3, ((s2, System.identityHashCode(s2), s3, System.identityHashCode(s3))))
+ }
+}