Skip to content

Commit e748f2e

Browse files
committed
Merge pull request scala#2928 from retronym/merge/2.10.x-to-master
merge 2.10.x to master
2 parents 5f7d725 + c3042e1 commit e748f2e

File tree

16 files changed

+302
-178
lines changed

16 files changed

+302
-178
lines changed

build.xml

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,14 @@ TODO:
12811281
<target name="quick.swing" depends="quick.actors, quick.lib" if="has.java6">
12821282
<staged-build with="locker" stage="quick" project="swing"/> </target>
12831283

1284+
<target name="quick.partest-extras"
1285+
depends="quick.comp">
1286+
<!-- compile compiler-specific parts of partest -->
1287+
<staged-build with="starr" stage="quick" project="partest-extras" />
1288+
<staged-build with="starr" stage="quick" project="partest-javaagent" />
1289+
</target>
1290+
1291+
12841292
<target name="quick.plugins" depends="quick.comp">
12851293
<staged-uptodate stage="quick" project="plugins">
12861294
<check><srcfiles dir="${src.dir}/continuations"/></check>
@@ -1308,7 +1316,7 @@ TODO:
13081316
</staged-uptodate>
13091317
</target>
13101318

1311-
<target name="quick.bin" depends="quick.lib, quick.reflect, quick.comp, quick.repl, quick.scalap, quick.interactive, quick.swing, quick.plugins, quick.scaladoc">
1319+
<target name="quick.bin" depends="quick.lib, quick.reflect, quick.comp, quick.repl, quick.scalap, quick.interactive, quick.swing, quick.plugins, quick.scaladoc, quick.partest-extras">
13121320
<staged-bin stage="quick" classpathref="quick.bin.tool.path"/>
13131321
</target>
13141322

@@ -1325,6 +1333,11 @@ TODO:
13251333
<target name="pack.actors" depends="quick.lib"> <staged-pack project="actors"/> </target>
13261334
<target name="pack.swing" if="has.java6" depends="quick.swing"> <staged-pack project="swing"/> </target>
13271335
<target name="pack.reflect" depends="quick.reflect"> <staged-pack project="reflect"/> </target>
1336+
<target name="pack.partest-extras" depends="quick.partest-extras">
1337+
<staged-pack project="partest-extras"/>
1338+
<staged-pack project="partest-javaagent"
1339+
manifest="${src.dir}/partest-javaagent/scala/tools/partest/javaagent/MANIFEST.MF"/>
1340+
</target>
13281341

13291342
<target name="pack.comp" depends="quick.comp, quick.scaladoc, quick.interactive, quick.repl, asm.done">
13301343
<staged-pack project="compiler" manifest="${build-pack.dir}/META-INF/MANIFEST.MF">
@@ -1357,7 +1370,7 @@ TODO:
13571370

13581371
<target name="pack.scalap" depends="quick.scalap"> <staged-pack project="scalap" targetjar="scalap.jar"/> </target>
13591372

1360-
<target name="pack.bin" depends="pack.comp, pack.lib, pack.actors, pack.plugins, pack.reflect, pack.scalap, pack.swing">
1373+
<target name="pack.bin" depends="pack.comp, pack.lib, pack.actors, pack.plugins, pack.reflect, pack.scalap, pack.swing, pack.partest-extras">
13611374
<copy todir="${build-pack.dir}/lib">
13621375
<path refid="external-modules-nocore" />
13631376
<mapper type="flatten" />
@@ -1606,18 +1619,12 @@ TODO:
16061619
</target>
16071620

16081621
<!-- See test/build-partest.xml for the macro(s) being used here. -->
1609-
<target name="partest.task" depends="init">
1622+
<target name="partest.task" depends="init,pack.done">
16101623
<!-- note the classpathref! this is the classpath used to run partest,
16111624
so it must have the new compiler.... -->
16121625
<taskdef
16131626
classpathref="partest.compilation.path"
16141627
resource="scala/tools/partest/antlib.xml"/>
1615-
1616-
<!-- compile compiler-specific parts of partest -->
1617-
<staged-build with="starr" stage="quick" project="partest-extras" />
1618-
<staged-build with="starr" stage="quick" project="partest-javaagent" />
1619-
<staged-pack project="partest-extras"/>
1620-
<staged-pack project="partest-javaagent" manifest="${src.dir}/partest-javaagent/scala/tools/partest/javaagent/MANIFEST.MF"/>
16211628
</target>
16221629

16231630
<target name="test.suite.init" depends="pack.done, partest.task">

src/compiler/scala/tools/nsc/ast/parser/Parsers.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,6 +2818,8 @@ self =>
28182818
case tdef @ TypeDef(mods, name, tparams, rhs) =>
28192819
deprecationWarning(tdef.pos.point, "early type members are deprecated. Move them to the regular body: the semantics are the same.")
28202820
treeCopy.TypeDef(tdef, mods | Flags.PRESUPER, name, tparams, rhs)
2821+
case docdef @ DocDef(comm, rhs) =>
2822+
treeCopy.DocDef(docdef, comm, rhs)
28212823
case stat if !stat.isEmpty =>
28222824
syntaxError(stat.pos, "only concrete field definitions allowed in early object initialization section", skipIt = false)
28232825
EmptyTree

src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,14 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
230230
.changeOwner(origMeth -> extensionMeth)
231231
new SubstututeRecursion(origMeth, extensionMeth, unit).transform(tree)
232232
}
233+
val castBody =
234+
if (extensionBody.tpe <:< extensionMono.finalResultType)
235+
extensionBody
236+
else
237+
gen.mkCastPreservingAnnotations(extensionBody, extensionMono.finalResultType) // SI-7818 e.g. mismatched existential skolems
233238

234239
// Record the extension method. Later, in `Extender#transformStats`, these will be added to the companion object.
235-
extensionDefs(companion) += atPos(tree.pos)(DefDef(extensionMeth, extensionBody))
240+
extensionDefs(companion) += atPos(tree.pos)(DefDef(extensionMeth, castBody))
236241

237242
// These three lines are assembling Foo.bar$extension[T1, T2, ...]($this)
238243
// which leaves the actual argument application for extensionCall.

src/library/scala/collection/mutable/MapLike.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,8 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
208208
* @param p The test predicate
209209
*/
210210
def retain(p: (A, B) => Boolean): this.type = {
211-
for ((k, v) <- this.seq ; if !p(k, v))
212-
this -= k
211+
for ((k, v) <- this.toList) // SI-7269 toList avoids ConcurrentModificationException
212+
if (!p(k, v)) this -= k
213213

214214
this
215215
}

src/library/scala/collection/mutable/SetLike.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]]
121121
* which `p` returns `true` are retained in the set; all others
122122
* are removed.
123123
*/
124-
def retain(p: A => Boolean): Unit = for (elem <- this.toList) if (!p(elem)) this -= elem
124+
def retain(p: A => Boolean): Unit =
125+
for (elem <- this.toList) // SI-7269 toList avoids ConcurrentModificationException
126+
if (!p(elem)) this -= elem
125127

126128
/** Removes all elements from the set. After this operation is completed,
127129
* the set will be empty.

src/library/scala/runtime/ScalaRunTime.scala

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,13 @@ object ScalaRunTime {
3232
clazz.isArray && (atLevel == 1 || isArrayClass(clazz.getComponentType, atLevel - 1))
3333

3434
def isValueClass(clazz: jClass[_]) = clazz.isPrimitive()
35-
def isTuple(x: Any) = x != null && tupleNames(x.getClass.getName)
35+
36+
// includes specialized subclasses and future proofed against hypothetical TupleN (for N > 22)
37+
def isTuple(x: Any) = x != null && x.getClass.getName.startsWith("scala.Tuple")
3638
def isAnyVal(x: Any) = x match {
3739
case _: Byte | _: Short | _: Char | _: Int | _: Long | _: Float | _: Double | _: Boolean | _: Unit => true
3840
case _ => false
3941
}
40-
// Avoiding boxing which messes up the specialized tests. Don't ask.
41-
private val tupleNames = {
42-
var i = 22
43-
var names: List[String] = Nil
44-
while (i >= 1) {
45-
names ::= ("scala.Tuple" + String.valueOf(i))
46-
i -= 1
47-
}
48-
names.toSet
49-
}
5042

5143
// A helper method to make my life in the pattern matcher a lot easier.
5244
def drop[Repr](coll: Repr, num: Int)(implicit traversable: IsTraversableLike[Repr]): Repr =
@@ -77,33 +69,37 @@ object ScalaRunTime {
7769
classTag[T].runtimeClass.asInstanceOf[jClass[T]]
7870

7971
/** Retrieve generic array element */
80-
def array_apply(xs: AnyRef, idx: Int): Any = xs match {
81-
case x: Array[AnyRef] => x(idx).asInstanceOf[Any]
82-
case x: Array[Int] => x(idx).asInstanceOf[Any]
83-
case x: Array[Double] => x(idx).asInstanceOf[Any]
84-
case x: Array[Long] => x(idx).asInstanceOf[Any]
85-
case x: Array[Float] => x(idx).asInstanceOf[Any]
86-
case x: Array[Char] => x(idx).asInstanceOf[Any]
87-
case x: Array[Byte] => x(idx).asInstanceOf[Any]
88-
case x: Array[Short] => x(idx).asInstanceOf[Any]
89-
case x: Array[Boolean] => x(idx).asInstanceOf[Any]
90-
case x: Array[Unit] => x(idx).asInstanceOf[Any]
91-
case null => throw new NullPointerException
72+
def array_apply(xs: AnyRef, idx: Int): Any = {
73+
xs match {
74+
case x: Array[AnyRef] => x(idx).asInstanceOf[Any]
75+
case x: Array[Int] => x(idx).asInstanceOf[Any]
76+
case x: Array[Double] => x(idx).asInstanceOf[Any]
77+
case x: Array[Long] => x(idx).asInstanceOf[Any]
78+
case x: Array[Float] => x(idx).asInstanceOf[Any]
79+
case x: Array[Char] => x(idx).asInstanceOf[Any]
80+
case x: Array[Byte] => x(idx).asInstanceOf[Any]
81+
case x: Array[Short] => x(idx).asInstanceOf[Any]
82+
case x: Array[Boolean] => x(idx).asInstanceOf[Any]
83+
case x: Array[Unit] => x(idx).asInstanceOf[Any]
84+
case null => throw new NullPointerException
85+
}
9286
}
9387

9488
/** update generic array element */
95-
def array_update(xs: AnyRef, idx: Int, value: Any): Unit = xs match {
96-
case x: Array[AnyRef] => x(idx) = value.asInstanceOf[AnyRef]
97-
case x: Array[Int] => x(idx) = value.asInstanceOf[Int]
98-
case x: Array[Double] => x(idx) = value.asInstanceOf[Double]
99-
case x: Array[Long] => x(idx) = value.asInstanceOf[Long]
100-
case x: Array[Float] => x(idx) = value.asInstanceOf[Float]
101-
case x: Array[Char] => x(idx) = value.asInstanceOf[Char]
102-
case x: Array[Byte] => x(idx) = value.asInstanceOf[Byte]
103-
case x: Array[Short] => x(idx) = value.asInstanceOf[Short]
104-
case x: Array[Boolean] => x(idx) = value.asInstanceOf[Boolean]
105-
case x: Array[Unit] => x(idx) = value.asInstanceOf[Unit]
106-
case null => throw new NullPointerException
89+
def array_update(xs: AnyRef, idx: Int, value: Any): Unit = {
90+
xs match {
91+
case x: Array[AnyRef] => x(idx) = value.asInstanceOf[AnyRef]
92+
case x: Array[Int] => x(idx) = value.asInstanceOf[Int]
93+
case x: Array[Double] => x(idx) = value.asInstanceOf[Double]
94+
case x: Array[Long] => x(idx) = value.asInstanceOf[Long]
95+
case x: Array[Float] => x(idx) = value.asInstanceOf[Float]
96+
case x: Array[Char] => x(idx) = value.asInstanceOf[Char]
97+
case x: Array[Byte] => x(idx) = value.asInstanceOf[Byte]
98+
case x: Array[Short] => x(idx) = value.asInstanceOf[Short]
99+
case x: Array[Boolean] => x(idx) = value.asInstanceOf[Boolean]
100+
case x: Array[Unit] => x(idx) = value.asInstanceOf[Unit]
101+
case null => throw new NullPointerException
102+
}
107103
}
108104

109105
/** Get generic array length */

test/files/pos/t7818.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class Observable1[+T](val asJava: JObservable[_ <: T]) extends AnyVal {
2+
private def foo[X](a: JObservable[X]): JObservable[X] = ???
3+
// was generating a type error as the type of the RHS included an existential
4+
// skolem based on the class type parameter `T`, which did not conform
5+
// to the typer parameter of the extension method into which the RHS is
6+
// transplanted.
7+
def synchronize: Observable1[T] = new Observable1(foo(asJava))
8+
}
9+
10+
class JObservable[T]

test/files/run/predef-cycle.scala

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
class Force {
2+
val t1 = new Thread {
3+
override def run() {
4+
scala.`package`
5+
}
6+
}
7+
val t2 = new Thread {
8+
override def run() {
9+
scala.Predef
10+
}
11+
}
12+
t1.start()
13+
t2.start()
14+
t1.join()
15+
t2.join()
16+
}
17+
18+
object Test {
19+
def main(args: Array[String]) {
20+
new Force()
21+
}
22+
}
23+
24+
/* Was deadlocking:
25+
"Thread-2" prio=5 tid=7f9637268000 nid=0x119601000 in Object.wait() [119600000]
26+
java.lang.Thread.State: RUNNABLE
27+
at scala.Predef$.<init>(Predef.scala:90)
28+
at scala.Predef$.<clinit>(Predef.scala)
29+
at Force$$anon$2.run(predef-cycle.scala:10)
30+
31+
"Thread-1" prio=5 tid=7f9637267800 nid=0x1194fe000 in Object.wait() [1194fb000]
32+
java.lang.Thread.State: RUNNABLE
33+
at scala.collection.immutable.Set$Set4.$plus(Set.scala:127)
34+
at scala.collection.immutable.Set$Set4.$plus(Set.scala:121)
35+
at scala.collection.mutable.SetBuilder.$plus$eq(SetBuilder.scala:24)
36+
at scala.collection.mutable.SetBuilder.$plus$eq(SetBuilder.scala:22)
37+
at scala.collection.generic.Growable$$anonfun$$plus$plus$eq$1.apply(Growable.scala:48)
38+
at scala.collection.generic.Growable$$anonfun$$plus$plus$eq$1.apply(Growable.scala:48)
39+
at scala.collection.immutable.List.foreach(List.scala:318)
40+
at scala.collection.generic.Growable$class.$plus$plus$eq(Growable.scala:48)
41+
at scala.collection.mutable.SetBuilder.$plus$plus$eq(SetBuilder.scala:22)
42+
at scala.collection.TraversableLike$class.to(TraversableLike.scala:629)
43+
at scala.collection.AbstractTraversable.to(Traversable.scala:105)
44+
at scala.collection.TraversableOnce$class.toSet(TraversableOnce.scala:267)
45+
at scala.collection.AbstractTraversable.toSet(Traversable.scala:105)
46+
at scala.runtime.ScalaRunTime$.<init>(ScalaRunTime.scala:50)
47+
at scala.runtime.ScalaRunTime$.<clinit>(ScalaRunTime.scala)
48+
at scala.collection.mutable.HashTable$HashUtils$class.elemHashCode(HashTable.scala)
49+
at scala.collection.mutable.HashMap.elemHashCode(HashMap.scala:39)
50+
at scala.collection.mutable.HashTable$class.findOrAddEntry(HashTable.scala:161)
51+
at scala.collection.mutable.HashMap.findOrAddEntry(HashMap.scala:39)
52+
at scala.collection.mutable.HashMap.put(HashMap.scala:75)
53+
at scala.collection.mutable.HashMap.update(HashMap.scala:80)
54+
at scala.sys.SystemProperties$.addHelp(SystemProperties.scala:64)
55+
at scala.sys.SystemProperties$.bool(SystemProperties.scala:68)
56+
at scala.sys.SystemProperties$.noTraceSupression$lzycompute(SystemProperties.scala:80)
57+
- locked <7b8b0e228> (a scala.sys.SystemProperties$)
58+
at scala.sys.SystemProperties$.noTraceSupression(SystemProperties.scala:80)
59+
at scala.util.control.NoStackTrace$.<init>(NoStackTrace.scala:31)
60+
at scala.util.control.NoStackTrace$.<clinit>(NoStackTrace.scala)
61+
at scala.util.control.NoStackTrace$class.fillInStackTrace(NoStackTrace.scala:22)
62+
at scala.util.control.BreakControl.fillInStackTrace(Breaks.scala:93)
63+
at java.lang.Throwable.<init>(Throwable.java:181)
64+
at scala.util.control.BreakControl.<init>(Breaks.scala:93)
65+
at scala.util.control.Breaks.<init>(Breaks.scala:28)
66+
at scala.collection.Traversable$.<init>(Traversable.scala:96)
67+
at scala.collection.Traversable$.<clinit>(Traversable.scala)
68+
at scala.package$.<init>(package.scala:46)
69+
at scala.package$.<clinit>(package.scala)
70+
at Force$$anon$1.run(predef-cycle.scala:4)
71+
*/

test/files/run/t7269.scala

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import scala.collection.JavaConversions._
2+
import scala.collection.mutable
3+
4+
object Test extends App {
5+
6+
def testMap(): Unit = {
7+
val mapJ = new java.util.HashMap[Int, String]
8+
val mapS: mutable.Map[Int, String] = mapJ
9+
10+
(10 to 20).foreach(i => mapS += ((i, i.toString)))
11+
assert(11 == mapS.size)
12+
13+
// ConcurrentModificationException thrown in the following line
14+
mapS.retain((i, str) => i % 2 == 0)
15+
assert(6 == mapS.size)
16+
}
17+
18+
def testSet(): Unit = {
19+
val mapJ = new java.util.HashSet[Int]
20+
val mapS: mutable.Set[Int] = mapJ
21+
22+
(10 to 20).foreach(i => mapS += i)
23+
assert(11 == mapS.size)
24+
25+
// ConcurrentModificationException thrown in the following line
26+
mapS.retain((i) => i % 2 == 0)
27+
assert(6 == mapS.size)
28+
}
29+
30+
testSet()
31+
testMap()
32+
}

test/instrumented/boxes.patch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
9c9
2-
<
2+
<
33
---
44
> /* INSTRUMENTED VERSION */
55
51a52,59

0 commit comments

Comments
 (0)