From d48786cedf2e97cd45ae45203c58bcdd174289e7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 16 Dec 2018 18:34:51 +0100 Subject: [PATCH 1/2] Fix #5546: Disallow comparing opaque types under -language:strictEquality Disallow comparing different opaque types under -language:strictEquality --- .../src/dotty/tools/dotc/typer/Implicits.scala | 4 +++- tests/neg/i5546.scala | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i5546.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 40ca41a0c58c..e9a18e09380a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -831,11 +831,13 @@ trait Implicits { self: Typer => (other ne NoType) && !other.derivesFrom(defn.AnyValClass) } + // Map all non-opaque abstract types to their upper bound. + // This is done to check whether such types might plausibly be comparable to each other. val lift = new TypeMap { def apply(t: Type): Type = t match { case t: TypeRef => t.info match { - case TypeBounds(lo, hi) if lo ne hi => apply(hi) + case TypeBounds(lo, hi) if lo.ne(hi) && !t.symbol.is(Opaque) => apply(hi) case _ => t } case t: RefinedType => diff --git a/tests/neg/i5546.scala b/tests/neg/i5546.scala new file mode 100644 index 000000000000..7668825ff1d5 --- /dev/null +++ b/tests/neg/i5546.scala @@ -0,0 +1,16 @@ +import language.strictEquality + +object O { + + opaque type Meters = Double + object Meters { def apply(d: Double): Meters = d } + implicit def eqM: Eq[Meters, Meters] = Eq + + opaque type Feet = Double + object Feet { def apply(d: Double): Feet = d } + implicit def eqF: Eq[Feet, Feet] = Eq + + def main(args: Array[String]): Unit = + println(Feet(3) == Meters(3)) // error: cannot compare + +} From 8e77ed869978934a701fbb9d33c2494ad17dd7ac Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 17 Dec 2018 14:59:28 +0100 Subject: [PATCH 2/2] Add to test case --- tests/neg/i5546.scala | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/neg/i5546.scala b/tests/neg/i5546.scala index 7668825ff1d5..bb6668e5a8a5 100644 --- a/tests/neg/i5546.scala +++ b/tests/neg/i5546.scala @@ -3,14 +3,19 @@ import language.strictEquality object O { opaque type Meters = Double - object Meters { def apply(d: Double): Meters = d } + object Meters { + def apply(d: Double): Meters = d + val m: Meters = 1.0 + assert(m == 1.0) // OK + } implicit def eqM: Eq[Meters, Meters] = Eq opaque type Feet = Double object Feet { def apply(d: Double): Feet = d } implicit def eqF: Eq[Feet, Feet] = Eq - def main(args: Array[String]): Unit = + def main(args: Array[String]): Unit = { println(Feet(3) == Meters(3)) // error: cannot compare - + println(Feet(3) == 3.0) // error: cannot compare + } }