From 4d321163d33e8ce4016220fe6598024e15c0dd7b Mon Sep 17 00:00:00 2001 From: Fengyun Liu Date: Mon, 1 May 2023 18:13:14 +0200 Subject: [PATCH] Fix #11541: Specialize ClassTag[T] in exhaustivity check --- .../src/dotty/tools/dotc/core/Definitions.scala | 1 + .../dotty/tools/dotc/transform/patmat/Space.scala | 7 ++++++- tests/patmat/i11541.scala | 13 +++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/patmat/i11541.scala diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 85aac4ce601c..b7211b3ce5e3 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -798,6 +798,7 @@ class Definitions { @tu lazy val ReflectPackageClass: Symbol = requiredPackage("scala.reflect.package").moduleClass @tu lazy val ClassTagClass: ClassSymbol = requiredClass("scala.reflect.ClassTag") + @tu lazy val ClassTagClass_unapply: Symbol = ClassTagClass.requiredMethod("unapply") @tu lazy val ClassTagModule: Symbol = ClassTagClass.companionModule @tu lazy val ClassTagModule_apply: Symbol = ClassTagModule.requiredMethod(nme.apply) diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 3e05310d7249..de2fed48bc5d 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -602,10 +602,15 @@ object SpaceEngine { /** Whether the extractor covers the given type */ def covers(unapp: TermRef, scrutineeTp: Type, argLen: Int)(using Context): Boolean = - SpaceEngine.isIrrefutable(unapp, argLen) || unapp.symbol == defn.TypeTest_unapply && { + SpaceEngine.isIrrefutable(unapp, argLen) + || unapp.symbol == defn.TypeTest_unapply && { val AppliedType(_, _ :: tp :: Nil) = unapp.prefix.widen.dealias: @unchecked scrutineeTp <:< tp } + || unapp.symbol == defn.ClassTagClass_unapply && { + val AppliedType(_, tp :: Nil) = unapp.prefix.widen.dealias: @unchecked + scrutineeTp <:< tp + } /** Decompose a type into subspaces -- assume the type can be decomposed */ def decompose(tp: Type)(using Context): List[Type] = trace(i"decompose($tp)", debug) { diff --git a/tests/patmat/i11541.scala b/tests/patmat/i11541.scala new file mode 100644 index 000000000000..4ac1af08c80b --- /dev/null +++ b/tests/patmat/i11541.scala @@ -0,0 +1,13 @@ +import scala.reflect.ClassTag + +class Test: + type A + + given ClassTag[A] = ??? + + var a: A | Null = null + + a match { //WARNING: match may not be exhaustive. It would fail on pattern case: _: A + case null => + case a: A => + }