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..bb6668e5a8a5 --- /dev/null +++ b/tests/neg/i5546.scala @@ -0,0 +1,21 @@ +import language.strictEquality + +object O { + + opaque type Meters = Double + 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 = { + println(Feet(3) == Meters(3)) // error: cannot compare + println(Feet(3) == 3.0) // error: cannot compare + } +}