Skip to content

Commit cae7b78

Browse files
committed
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"
1 parent 7749866 commit cae7b78

File tree

4 files changed

+53
-4
lines changed

4 files changed

+53
-4
lines changed

src/dotty/DottyPredef.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,35 @@ package dotty
33
import scala.reflect.runtime.universe.TypeTag
44
import scala.reflect.ClassTag
55
import scala.Predef.???
6+
import scala.collection.Seq
67

78
/** unimplemented implicit for TypeTag */
89
object DottyPredef {
910
implicit def typeTag[T]: TypeTag[T] = ???
1011

1112
implicit def arrayTag[T](implicit ctag: ClassTag[T]): ClassTag[Array[T]] =
1213
ctag.wrap
14+
15+
implicit def eqNumber : Eq[Number, Number] = Eq
16+
implicit def eqString : Eq[String, String] = Eq
17+
18+
// true asymmetry, modeling the (somewhat problematic) nature of equals on Proxies
19+
implicit def eqProxy : Eq[Proxy, Any] = Eq
20+
21+
implicit def eqSeq[T, U](implicit eq: Eq[T, U]): Eq[Seq[T], Seq[U]] = Eq
22+
23+
implicit def eqByteNum : Eq[Byte, Number] = Eq
24+
implicit def eqNumByte : Eq[Number, Byte] = Eq
25+
implicit def eqCharNum : Eq[Char, Number] = Eq
26+
implicit def eqNumChar : Eq[Number, Char] = Eq
27+
implicit def eqShortNum : Eq[Short, Number] = Eq
28+
implicit def eqNumShort : Eq[Number, Short] = Eq
29+
implicit def eqIntNum : Eq[Int, Number] = Eq
30+
implicit def eqNumInt : Eq[Number, Int] = Eq
31+
implicit def eqLongNum : Eq[Long, Number] = Eq
32+
implicit def eqNumLong : Eq[Number, Long] = Eq
33+
implicit def eqFloatNum : Eq[Float, Number] = Eq
34+
implicit def eqNumFloat : Eq[Number, Float] = Eq
35+
implicit def eqDoubleNum: Eq[Double, Number] = Eq
36+
implicit def eqNumDouble: Eq[Number, Double] = Eq
1337
}

src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,8 +472,20 @@ trait Implicits { self: Typer =>
472472
EmptyTree
473473
}
474474

475-
private def assumedCanEqual(ltp: Type, rtp: Type)(implicit ctx: Context) =
476-
ltp.isError || rtp.isError || ltp <:< rtp || rtp <:< ltp
475+
private def assumedCanEqual(ltp: Type, rtp: Type)(implicit ctx: Context) = {
476+
val lift = new TypeMap {
477+
def apply(t: Type) = t match {
478+
case t: TypeRef =>
479+
t.info match {
480+
case TypeBounds(lo, hi) if lo ne hi => hi
481+
case _ => t
482+
}
483+
case _ =>
484+
if (variance > 0) mapOver(t) else t
485+
}
486+
}
487+
ltp.isError || rtp.isError || ltp <:< lift(rtp) || rtp <:< lift(ltp)
488+
}
477489

478490
/** Check that equality tests between types `ltp` and `rtp` make sense */
479491
def checkCanEqual(ltp: Type, rtp: Type, pos: Position)(implicit ctx: Context): Unit =

test/test/CompilerTest.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,13 @@ abstract class CompilerTest {
238238

239239
val nerrors = reporter.errorCount
240240
val xerrors = (expectedErrorsPerFile map {_.totalErrors}).sum
241+
def expectedErrorFiles =
242+
expectedErrorsPerFile.collect{
243+
case er if er.totalErrors > 0 => er.fileName
244+
}
241245
assert(nerrors == xerrors,
242246
s"""Wrong # of errors. Expected: $xerrors, found: $nerrors
243-
|Files with expected errors: ${expectedErrorsPerFile.collect{ case er if er.totalErrors > 0 => er.fileName} }
247+
|Files with expected errors: $expectedErrorFiles%, %
244248
""".stripMargin)
245249
// NEG TEST
246250
if (xerrors > 0) {

tests/neg/equality.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@ object equality {
1414
implicit def eqNum: Eq[Num, Num] = Eq
1515
implicit def eqOption[T, U](implicit e: Eq[T, U]): Eq[Option[T], Option[U]] = Eq
1616

17+
case class PString(a: String) extends Proxy {
18+
def self = a
19+
}
20+
21+
/*
1722
implicit def eqString: Eq[String, String] = Eq
1823
implicit def eqInt: Eq[Int, Int] = Eq
1924
implicit def eqNumber: Eq[Number, Number] = Eq
2025
implicit def eqIntNumber: Eq[Int, Number] = Eq
2126
implicit def eqNumberInt: Eq[Number, Int] = Eq
22-
27+
*/
2328
def main(args: Array[String]): Unit = {
2429
Some(Other(3)) == None
2530

@@ -73,6 +78,9 @@ object equality {
7378
i == bi
7479
bi == i
7580

81+
val ps = PString("hello")
82+
ps == "world"
83+
7684
n match {
7785
case None => // error
7886
}
@@ -96,5 +104,6 @@ object equality {
96104
1 == "abc" // error
97105
"abc" == bi // error
98106
bi == "abc" // error
107+
"world" == ps // error
99108
}
100109
}

0 commit comments

Comments
 (0)