summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala2
-rw-r--r--src/library/scala/collection/convert/Wrappers.scala9
-rwxr-xr-xtest/files/neg/t6446-additional.check2
-rwxr-xr-xtest/files/neg/t6446-missing.check2
-rw-r--r--test/files/neg/t6446-show-phases.check2
-rw-r--r--test/files/neg/t7494-no-options.check2
-rw-r--r--test/files/run/programmatic-main.check2
-rw-r--r--test/junit/scala/collection/convert/MapWrapperTest.scala49
8 files changed, 64 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 1c5354502b..e765c9165a 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -688,7 +688,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
uncurry -> "uncurry, translate function values to anonymous classes",
tailCalls -> "replace tail calls by jumps",
specializeTypes -> "@specialized-driven class and method specialization",
- explicitOuter -> "this refs to outer pointers, translate patterns",
+ explicitOuter -> "this refs to outer pointers",
erasure -> "erase types, add interfaces for traits",
postErasure -> "clean up erased inline classes",
lazyVals -> "allocate bitmaps, translate lazy vals into lazified defs",
diff --git a/src/library/scala/collection/convert/Wrappers.scala b/src/library/scala/collection/convert/Wrappers.scala
index 4410ddc7d8..56f1802509 100644
--- a/src/library/scala/collection/convert/Wrappers.scala
+++ b/src/library/scala/collection/convert/Wrappers.scala
@@ -212,6 +212,15 @@ private[collection] trait Wrappers {
}
}
}
+
+ override def containsKey(key: AnyRef): Boolean = try {
+ // Note: Subclass of collection.Map with specific key type may redirect generic
+ // contains to specific contains, which will throw a ClassCastException if the
+ // wrong type is passed. This is why we need a type cast to A inside a try/catch.
+ underlying.contains(key.asInstanceOf[A])
+ } catch {
+ case ex: ClassCastException => false
+ }
}
case class MutableMapWrapper[A, B](underlying: mutable.Map[A, B]) extends MapWrapper[A, B](underlying) {
diff --git a/test/files/neg/t6446-additional.check b/test/files/neg/t6446-additional.check
index 6dfe072913..c91333830a 100755
--- a/test/files/neg/t6446-additional.check
+++ b/test/files/neg/t6446-additional.check
@@ -12,7 +12,7 @@ superaccessors 6 add super accessors in traits and nested classes
uncurry 10 uncurry, translate function values to anonymous classes
tailcalls 11 replace tail calls by jumps
specialize 12 @specialized-driven class and method specialization
- explicitouter 13 this refs to outer pointers, translate patterns
+ explicitouter 13 this refs to outer pointers
erasure 14 erase types, add interfaces for traits
posterasure 15 clean up erased inline classes
lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs
diff --git a/test/files/neg/t6446-missing.check b/test/files/neg/t6446-missing.check
index ba5e30dc05..b2d5ddd686 100755
--- a/test/files/neg/t6446-missing.check
+++ b/test/files/neg/t6446-missing.check
@@ -13,7 +13,7 @@ superaccessors 6 add super accessors in traits and nested classes
uncurry 10 uncurry, translate function values to anonymous classes
tailcalls 11 replace tail calls by jumps
specialize 12 @specialized-driven class and method specialization
- explicitouter 13 this refs to outer pointers, translate patterns
+ explicitouter 13 this refs to outer pointers
erasure 14 erase types, add interfaces for traits
posterasure 15 clean up erased inline classes
lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs
diff --git a/test/files/neg/t6446-show-phases.check b/test/files/neg/t6446-show-phases.check
index 10a9e08b86..48d4f37b3e 100644
--- a/test/files/neg/t6446-show-phases.check
+++ b/test/files/neg/t6446-show-phases.check
@@ -12,7 +12,7 @@ superaccessors 6 add super accessors in traits and nested classes
uncurry 10 uncurry, translate function values to anonymous classes
tailcalls 11 replace tail calls by jumps
specialize 12 @specialized-driven class and method specialization
- explicitouter 13 this refs to outer pointers, translate patterns
+ explicitouter 13 this refs to outer pointers
erasure 14 erase types, add interfaces for traits
posterasure 15 clean up erased inline classes
lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs
diff --git a/test/files/neg/t7494-no-options.check b/test/files/neg/t7494-no-options.check
index 0bde84c96c..b5dc0e3d4f 100644
--- a/test/files/neg/t7494-no-options.check
+++ b/test/files/neg/t7494-no-options.check
@@ -13,7 +13,7 @@ superaccessors 6 add super accessors in traits and nested classes
uncurry 10 uncurry, translate function values to anonymous classes
tailcalls 11 replace tail calls by jumps
specialize 12 @specialized-driven class and method specialization
- explicitouter 13 this refs to outer pointers, translate patterns
+ explicitouter 13 this refs to outer pointers
erasure 14 erase types, add interfaces for traits
posterasure 15 clean up erased inline classes
lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs
diff --git a/test/files/run/programmatic-main.check b/test/files/run/programmatic-main.check
index 10d2ed5af7..cfa3ed3fb4 100644
--- a/test/files/run/programmatic-main.check
+++ b/test/files/run/programmatic-main.check
@@ -12,7 +12,7 @@ superaccessors 6 add super accessors in traits and nested classes
uncurry 10 uncurry, translate function values to anonymous classes
tailcalls 11 replace tail calls by jumps
specialize 12 @specialized-driven class and method specialization
- explicitouter 13 this refs to outer pointers, translate patterns
+ explicitouter 13 this refs to outer pointers
erasure 14 erase types, add interfaces for traits
posterasure 15 clean up erased inline classes
lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs
diff --git a/test/junit/scala/collection/convert/MapWrapperTest.scala b/test/junit/scala/collection/convert/MapWrapperTest.scala
new file mode 100644
index 0000000000..060b6b5937
--- /dev/null
+++ b/test/junit/scala/collection/convert/MapWrapperTest.scala
@@ -0,0 +1,49 @@
+package scala.collection.convert
+
+import org.junit.Assert._
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(classOf[JUnit4])
+class MapWrapperTest {
+
+ /* Test for SI-7883 */
+ @Test
+ def testContains() {
+ import scala.collection.JavaConverters.mapAsJavaMapConverter
+ import scala.language.reflectiveCalls // for accessing containsCounter
+
+ // A HashMap which throws an exception when the iterator() method is called.
+ // Before the fix for SI-7883, calling MapWrapper.containsKey() used to
+ // iterate through every element of the wrapped Map, and thus would crash
+ // in this case.
+ val scalaMap = new scala.collection.mutable.HashMap[String, String] {
+ var containsCounter = 0 // keep track of how often contains() has been called.
+ override def iterator = throw new UnsupportedOperationException
+
+ override def contains(key: String): Boolean = {
+ containsCounter += 1
+ super.contains(key)
+ }
+ }
+
+ val javaMap = scalaMap.asJava
+
+ scalaMap("hello") = "world"
+ scalaMap(null) = "null's value"
+
+ assertEquals(0, scalaMap.containsCounter)
+ assertTrue(javaMap.containsKey("hello")) // positive test
+ assertTrue(javaMap.containsKey(null)) // positive test, null key
+
+ assertFalse(javaMap.containsKey("goodbye")) // negative test
+ // Note: this case does NOT make it to scalaMap's contains() method because the runtime
+ // cast fails in MapWrapper, so the containsCounter is not incremented in this case.
+ assertFalse(javaMap.containsKey(42)) // negative test, wrong key type
+
+ assertEquals(Some("null's value"), scalaMap.remove(null))
+ assertFalse(javaMap.containsKey(null)) // negative test, null key
+ assertEquals(4, scalaMap.containsCounter)
+ }
+}