Skip to content

Fix #10085: check if enum case confirms to scrutinee type #10094

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions compiler/src/dotty/tools/dotc/core/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -633,8 +633,6 @@ object TypeOps:
* returned. Otherwise, `NoType` is returned.
*/
def refineUsingParent(parent: Type, child: Symbol)(using Context): Type = {
if (child.isTerm && child.is(Case, butNot = Module)) return child.termRef // enum vals always match

// <local child> is a place holder from Scalac, it is hopeless to instantiate it.
//
// Quote from scalac (from nsc/symtab/classfile/Pickler.scala):
Expand Down
12 changes: 2 additions & 10 deletions compiler/src/dotty/tools/dotc/transform/patmat/Space.scala
Original file line number Diff line number Diff line change
Expand Up @@ -527,15 +527,9 @@ class SpaceEngine(using Context) extends SpaceLogic {
/** Parameter types of the case class type `tp`. Adapted from `unapplyPlan` in patternMatcher */
def signature(unapp: TermRef, scrutineeTp: Type, argLen: Int): List[Type] = {
val unappSym = unapp.symbol
def caseClass = unappSym.owner.linkedClass

// println("scrutineeTp = " + scrutineeTp.show)

lazy val caseAccessors = caseClass.caseAccessors.filter(_.is(Method))

def isSyntheticScala2Unapply(sym: Symbol) =
sym.isAllOf(SyntheticCase) && sym.owner.is(Scala2x)

val mt: MethodType = unapp.widen match {
case mt: MethodType => mt
case pt: PolyType =>
Expand Down Expand Up @@ -564,9 +558,7 @@ class SpaceEngine(using Context) extends SpaceLogic {
val resTp = mt.finalResultType

val sig =
if (isSyntheticScala2Unapply(unappSym) && caseAccessors.length == argLen)
caseAccessors.map(_.info.asSeenFrom(mt.paramInfos.head, caseClass).widenExpr)
else if (resTp.isRef(defn.BooleanClass))
if (resTp.isRef(defn.BooleanClass))
List()
else {
val isUnapplySeq = unappSym.name == nme.unapplySeq
Expand All @@ -584,7 +576,7 @@ class SpaceEngine(using Context) extends SpaceLogic {
if (arity > 0)
productSelectorTypes(resTp, unappSym.srcPos)
else {
val getTp = resTp.select(nme.get).finalResultType.widen
val getTp = resTp.select(nme.get).finalResultType.widenTermRefExpr
if (argLen == 1) getTp :: Nil
else productSelectorTypes(getTp, unappSym.srcPos)
}
Expand Down
14 changes: 14 additions & 0 deletions tests/patmat/i10085.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
enum Bool:
case True
case False

import Bool._

enum SBool[B <: Bool]:
case STrue extends SBool[True.type]
case SFalse extends SBool[False.type]

import SBool._

def f(b: SBool[True.type]): Unit = b match
case STrue => ()
23 changes: 23 additions & 0 deletions tests/patmat/i9190.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Test {
case object X; type X = X.type
case object Y; type Y = Y.type

type XorY = X | Y

val testee1: XorY = X
testee1 match {
case value: XorY => println(value)
}

val testee2: Tuple1[XorY] = Tuple1(X)
testee2 match {
case Tuple1(value: XorY) => println(value)
}

type IntOrString = Int | String

val testee3: Tuple1[IntOrString] = Tuple1(42)
testee3 match {
case Tuple1(value: IntOrString) => println(value)
}
}