From 3023d3a7136332f571149d12b097d79e0057e62a Mon Sep 17 00:00:00 2001 From: Denis Zolkin Date: Tue, 26 Oct 2021 18:32:55 +0200 Subject: [PATCH] Handles Nothing when synthesizing CanEqual fixes #13739 fixes #13512 --- .../dotty/tools/dotc/typer/Synthesizer.scala | 5 +- tests/pos/i13512.scala | 7 +++ tests/pos/i13739.scala | 46 +++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 tests/pos/i13512.scala create mode 100644 tests/pos/i13739.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala index 75e7c55ada28..2dd088d70671 100644 --- a/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala @@ -102,7 +102,8 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): def canComparePredefinedClasses(cls1: ClassSymbol, cls2: ClassSymbol): Boolean = def cmpWithBoxed(cls1: ClassSymbol, cls2: ClassSymbol) = - cls2 == defn.boxedType(cls1.typeRef).symbol + cls2 == defn.NothingClass + || cls2 == defn.boxedType(cls1.typeRef).symbol || cls1.isNumericValueClass && cls2.derivesFrom(defn.BoxedNumberClass) if cls1.isPrimitiveValueClass then @@ -129,7 +130,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context): else if cls2 == defn.NullClass then cls1.derivesFrom(defn.ObjectClass) else - false + cls1 == defn.NothingClass || cls2 == defn.NothingClass end canComparePredefinedClasses /** Some simulated `CanEqual` instances for predefined types. It's more efficient diff --git a/tests/pos/i13512.scala b/tests/pos/i13512.scala new file mode 100644 index 000000000000..b400809d47b9 --- /dev/null +++ b/tests/pos/i13512.scala @@ -0,0 +1,7 @@ +import scala.language.strictEquality + +class NotEquatable + +def f = List(new NotEquatable) match + case Nil => ??? + case _ => diff --git a/tests/pos/i13739.scala b/tests/pos/i13739.scala new file mode 100644 index 000000000000..418e665f44e8 --- /dev/null +++ b/tests/pos/i13739.scala @@ -0,0 +1,46 @@ +import scala.language.strictEquality + +class Foo(i: Int) extends AnyVal + +val _ = summon[CanEqual[Nothing, Nothing]] + +val _ = summon[CanEqual[Int, Nothing]] +val _ = summon[CanEqual[Nothing, Int]] +val _ = summon[CanEqual[3, Nothing]] +val _ = summon[CanEqual[Nothing, 3]] + +val _ = summon[CanEqual[Byte, Nothing]] +val _ = summon[CanEqual[Nothing, Byte]] +val _ = summon[CanEqual[Short, Nothing]] +val _ = summon[CanEqual[Nothing, Short]] +val _ = summon[CanEqual[Float, Nothing]] +val _ = summon[CanEqual[Nothing, Float]] + +val _ = summon[CanEqual[Double, Nothing]] +val _ = summon[CanEqual[Nothing, Double]] +val _ = summon[CanEqual[3.0, Nothing]] +val _ = summon[CanEqual[Nothing, 3.0]] + +val _ = summon[CanEqual[String, Nothing]] +val _ = summon[CanEqual[Nothing, String]] +val _ = summon[CanEqual["foo", Nothing]] +val _ = summon[CanEqual[Nothing, "foo"]] + +val _ = summon[CanEqual[Char, Nothing]] +val _ = summon[CanEqual[Nothing, Char]] +val _ = summon[CanEqual['f', Nothing]] +val _ = summon[CanEqual[Nothing, 'f']] + +val _ = summon[CanEqual[Boolean, Nothing]] +val _ = summon[CanEqual[Nothing, Boolean]] +val _ = summon[CanEqual[true, Nothing]] +val _ = summon[CanEqual[Nothing, true]] + +val _ = summon[CanEqual[Foo, Nothing]] +val _ = summon[CanEqual[Nothing, Foo]] + +val _ = summon[CanEqual[Option[Int], None.type]] +val _ = summon[CanEqual[Option[Int], Option[Nothing]]] + +val _ = summon[CanEqual[Any & Nothing, Foo]] +val _ = summon[CanEqual[Nothing & Any, Foo]]