From cae7b7828934f5b31bfc6b506ca2b5bac8dcde05 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 10 May 2016 14:46:43 +0200 Subject: Add Eq instances of standard types to Predef To make tests pass, this required a looser specification of `assumedCanEquals`, so that an abstract type T can be compared to arbitrary values, as long as its upper bound can be compared. E.g. T == null T == "abc" --- src/dotty/DottyPredef.scala | 24 ++++++++++++++++++++++++ src/dotty/tools/dotc/typer/Implicits.scala | 16 ++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/dotty/DottyPredef.scala b/src/dotty/DottyPredef.scala index 9170da476..9e1f2102c 100644 --- a/src/dotty/DottyPredef.scala +++ b/src/dotty/DottyPredef.scala @@ -3,6 +3,7 @@ package dotty import scala.reflect.runtime.universe.TypeTag import scala.reflect.ClassTag import scala.Predef.??? +import scala.collection.Seq /** unimplemented implicit for TypeTag */ object DottyPredef { @@ -10,4 +11,27 @@ object DottyPredef { implicit def arrayTag[T](implicit ctag: ClassTag[T]): ClassTag[Array[T]] = ctag.wrap + + implicit def eqNumber : Eq[Number, Number] = Eq + implicit def eqString : Eq[String, String] = Eq + + // true asymmetry, modeling the (somewhat problematic) nature of equals on Proxies + implicit def eqProxy : Eq[Proxy, Any] = Eq + + implicit def eqSeq[T, U](implicit eq: Eq[T, U]): Eq[Seq[T], Seq[U]] = Eq + + implicit def eqByteNum : Eq[Byte, Number] = Eq + implicit def eqNumByte : Eq[Number, Byte] = Eq + implicit def eqCharNum : Eq[Char, Number] = Eq + implicit def eqNumChar : Eq[Number, Char] = Eq + implicit def eqShortNum : Eq[Short, Number] = Eq + implicit def eqNumShort : Eq[Number, Short] = Eq + implicit def eqIntNum : Eq[Int, Number] = Eq + implicit def eqNumInt : Eq[Number, Int] = Eq + implicit def eqLongNum : Eq[Long, Number] = Eq + implicit def eqNumLong : Eq[Number, Long] = Eq + implicit def eqFloatNum : Eq[Float, Number] = Eq + implicit def eqNumFloat : Eq[Number, Float] = Eq + implicit def eqDoubleNum: Eq[Double, Number] = Eq + implicit def eqNumDouble: Eq[Number, Double] = Eq } diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index bbad799e0..a5d415d97 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -472,8 +472,20 @@ trait Implicits { self: Typer => EmptyTree } - private def assumedCanEqual(ltp: Type, rtp: Type)(implicit ctx: Context) = - ltp.isError || rtp.isError || ltp <:< rtp || rtp <:< ltp + private def assumedCanEqual(ltp: Type, rtp: Type)(implicit ctx: Context) = { + val lift = new TypeMap { + def apply(t: Type) = t match { + case t: TypeRef => + t.info match { + case TypeBounds(lo, hi) if lo ne hi => hi + case _ => t + } + case _ => + if (variance > 0) mapOver(t) else t + } + } + ltp.isError || rtp.isError || ltp <:< lift(rtp) || rtp <:< lift(ltp) + } /** Check that equality tests between types `ltp` and `rtp` make sense */ def checkCanEqual(ltp: Type, rtp: Type, pos: Position)(implicit ctx: Context): Unit = -- cgit v1.2.3