Skip to content
Browse files

SI-7912 Be defensive calling `toString` in `MatchError#getMessage`

Otherwise, objects with exception-throwing `toString` lead to a
cascading error far removed from the originally failed match.
  • Loading branch information...
1 parent 0c92704 commit 006e2f2aadf5d15ff1b9b32f1b7e96960b778933 @retronym retronym committed
Showing with 24 additions and 2 deletions.
  1. +8 −2 src/library/scala/MatchError.scala
  2. +16 −0 test/files/run/t7912.scala
View
10 src/library/scala/MatchError.scala
@@ -23,9 +23,15 @@ final class MatchError(obj: Any) extends RuntimeException {
/** There's no reason we need to call toString eagerly,
* so defer it until getMessage is called.
*/
- private lazy val objString =
+ private lazy val objString = {
+ def ofClass = "of class " + obj.getClass.getName
if (obj == null) "null"
- else obj.toString() + " (of class " + obj.getClass.getName + ")"
+ else try {
+ obj.toString() + " (" + ofClass + ")"
+ } catch {
+ case _: Throwable => "an instance " + ofClass
+ }
+ }
override def getMessage() = objString
}
View
16 test/files/run/t7912.scala
@@ -0,0 +1,16 @@
+case object A { override def toString = ??? }
+
+object Test {
+ def foo: Int = (A: Any) match {
+ case 0 => 0
+ }
+ def main(args: Array[String]): Unit = {
+ try {
+ foo
+ sys.error("no exception")
+ } catch {
+ case me: MatchError => assert(me.getMessage == "an instance of class A$", me.getMessage)
+ case ex: Throwable => sys.error("not a match error: " + ex.getClass)
+ }
+ }
+}

0 comments on commit 006e2f2

Please sign in to comment.
Something went wrong with that request. Please try again.