From d1024dd0fda953077da9958135c09916ef078e02 Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Mon, 9 Apr 2018 13:44:34 +0200 Subject: [PATCH 1/4] Refactor before fixing #4272 --- .../tools/dotc/core/OrderingConstraint.scala | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 73ed67a08208..3783c88746d3 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -519,23 +519,15 @@ class OrderingConstraint(private val boundsMap: ParamBounds, def mergeParams(ps1: List[TypeParamRef], ps2: List[TypeParamRef]) = (ps1 /: ps2)((ps1, p2) => if (ps1.contains(p2)) ps1 else p2 :: ps1) - def mergeEntries(e1: Type, e2: Type): Type = e1 match { - case e1: TypeBounds => - e2 match { - case e2: TypeBounds => e1 & e2 - case _ if e1 contains e2 => e2 - case _ => mergeError - } - case tv1: TypeVar => - e2 match { - case tv2: TypeVar if tv1.instanceOpt eq tv2.instanceOpt => e1 - case _ => mergeError - } + def mergeEntries(e1: Type, e2: Type): Type = + (e1, e2) match { + case (e1: TypeBounds, e2: TypeBounds) => e1 & e2 + case (e1: TypeBounds, _) if e1 contains e2 => e2 + case (tv1: TypeVar, tv2: TypeVar) if tv1.instanceOpt eq tv2.instanceOpt => e1 case _ if e1 eq e2 => e1 - case _ => mergeError - } - - def mergeError = throw new AssertionError(i"cannot merge $this with $other") + case _ => + throw new AssertionError(i"cannot merge $this with $other") + } val that = other.asInstanceOf[OrderingConstraint] new OrderingConstraint( From 7919795f2d45c599c572bf0fa05e64486d0af39c Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Mon, 9 Apr 2018 13:48:05 +0200 Subject: [PATCH 2/4] Optimize (possibly) --- compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 3783c88746d3..e324bd349d33 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -521,10 +521,10 @@ class OrderingConstraint(private val boundsMap: ParamBounds, def mergeEntries(e1: Type, e2: Type): Type = (e1, e2) match { + case _ if e1 eq e2 => e1 case (e1: TypeBounds, e2: TypeBounds) => e1 & e2 case (e1: TypeBounds, _) if e1 contains e2 => e2 case (tv1: TypeVar, tv2: TypeVar) if tv1.instanceOpt eq tv2.instanceOpt => e1 - case _ if e1 eq e2 => e1 case _ => throw new AssertionError(i"cannot merge $this with $other") } From c9b97809116cbf495cd64a6ad15b0212596c374d Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Mon, 9 Apr 2018 13:49:22 +0200 Subject: [PATCH 3/4] Improve error message --- compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index e324bd349d33..7257023fad24 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -526,7 +526,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, case (e1: TypeBounds, _) if e1 contains e2 => e2 case (tv1: TypeVar, tv2: TypeVar) if tv1.instanceOpt eq tv2.instanceOpt => e1 case _ => - throw new AssertionError(i"cannot merge $this with $other") + throw new AssertionError(i"cannot merge $this with $other, mergeEntries($e1, $e2) failed") } val that = other.asInstanceOf[OrderingConstraint] From a3aee68d7e085a165f425e0cd2b8313fe959183a Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Mon, 9 Apr 2018 13:51:37 +0200 Subject: [PATCH 4/4] Fix #4272: make OrderingConstraint.&.mergeEntries symmetric Debugging revealed that in the failing testcase `e2: TypeBounds` while `e1: TypeRef`, and it's not clear why it should be otherwise. --- compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala | 2 ++ tests/neg/i4272.scala | 5 +++++ 2 files changed, 7 insertions(+) create mode 100644 tests/neg/i4272.scala diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 7257023fad24..47700da1090b 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -519,11 +519,13 @@ class OrderingConstraint(private val boundsMap: ParamBounds, def mergeParams(ps1: List[TypeParamRef], ps2: List[TypeParamRef]) = (ps1 /: ps2)((ps1, p2) => if (ps1.contains(p2)) ps1 else p2 :: ps1) + // Must be symmetric def mergeEntries(e1: Type, e2: Type): Type = (e1, e2) match { case _ if e1 eq e2 => e1 case (e1: TypeBounds, e2: TypeBounds) => e1 & e2 case (e1: TypeBounds, _) if e1 contains e2 => e2 + case (_, e2: TypeBounds) if e2 contains e1 => e1 case (tv1: TypeVar, tv2: TypeVar) if tv1.instanceOpt eq tv2.instanceOpt => e1 case _ => throw new AssertionError(i"cannot merge $this with $other, mergeEntries($e1, $e2) failed") diff --git a/tests/neg/i4272.scala b/tests/neg/i4272.scala new file mode 100644 index 000000000000..933ba1b27ca0 --- /dev/null +++ b/tests/neg/i4272.scala @@ -0,0 +1,5 @@ +object Main { + def f(m: Map[String, Boolean]) = {} + println(f(Map('a' -> true))) // error + println(this.f(Map('a' -> true))) // error +}