Skip to content

Commit 85747b5

Browse files
committed
Redo & organise adaptType in SpaceEngine
Emitting deferred reachability warnings (the previous commit) caused tests/patmat/boxing.scala to start failing, because my logic on boxing and unboxing wasn't actually right. So this fixes how the case type (tp1) gets adapted for the scrutinee type (tp2), with two examples in the comments from that boxing test case. Also organise that constant types are converted if boxing isn't involved.
1 parent f45c11d commit 85747b5

File tree

2 files changed

+44
-21
lines changed

2 files changed

+44
-21
lines changed

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

+38-15
Original file line numberDiff line numberDiff line change
@@ -512,23 +512,46 @@ class SpaceEngine(using Context) extends SpaceLogic {
512512
if converted == null then tp else ConstantType(converted)
513513
case _ => tp
514514

515-
/** Adapt types by performing primitive value boxing. #12805 */
516-
def maybeBox(tp1: Type, tp2: Type): Type =
517-
if tp1.classSymbol.isPrimitiveValueClass && !tp2.classSymbol.isPrimitiveValueClass then
518-
defn.boxedType(tp1).narrow
519-
else tp1
515+
private lazy val defn = ctx.definitions
516+
private lazy val ByteClass = defn.ByteClass
517+
private lazy val ShortClass = defn.ShortClass
518+
private lazy val CharClass = defn.CharClass
519+
private lazy val IntClass = defn.IntClass
520+
private lazy val LongClass = defn.LongClass
521+
private lazy val FloatClass = defn.FloatClass
522+
private lazy val DoubleClass = defn.DoubleClass
523+
private lazy val UnitClass = defn.UnitClass
524+
private lazy val BooleanClass = defn.BooleanClass
525+
526+
/** Adapt types by performing primitive value unboxing or boxing, or numeric constant conversion. #12805 */
527+
def adaptType(tp1: Type, tp2: Type): Type = trace(i"adaptType($tp1, $tp2)", show = true)((tp1.classSymbol, tp2.classSymbol) match {
528+
case ( ByteClass, defn.BoxedByteClass) => defn.BoxedByteClass.typeRef.narrow
529+
case ( ShortClass, defn.BoxedShortClass) => defn.BoxedShortClass.typeRef.narrow
530+
case ( CharClass, defn.BoxedCharClass) => defn.BoxedCharClass.typeRef.narrow
531+
case ( IntClass, defn.BoxedIntClass) => defn.BoxedIntClass.typeRef.narrow // 1 <:< Integer => (<skolem> : Integer) <:< Integer = true
532+
case ( LongClass, defn.BoxedLongClass) => defn.BoxedLongClass.typeRef.narrow
533+
case ( FloatClass, defn.BoxedFloatClass) => defn.BoxedFloatClass.typeRef.narrow
534+
case ( DoubleClass, defn.BoxedDoubleClass) => defn.BoxedDoubleClass.typeRef.narrow
535+
case ( UnitClass, defn.BoxedUnitClass) => defn.BoxedUnitClass.typeRef.narrow
536+
case (BooleanClass, defn.BoxedBooleanClass) => defn.BoxedBooleanClass.typeRef.narrow
537+
538+
case ( defn.BoxedByteClass, ByteClass) => defn.ByteType.narrow
539+
case ( defn.BoxedShortClass, ShortClass) => defn.ShortType.narrow
540+
case ( defn.BoxedCharClass, CharClass) => defn.CharType.narrow
541+
case ( defn.BoxedIntClass, IntClass) => defn.IntType.narrow // ONE <:< Int => (<skolem> : Int) <:< Int = true
542+
case ( defn.BoxedLongClass, LongClass) => defn.LongType.narrow
543+
case ( defn.BoxedFloatClass, FloatClass) => defn.FloatType.narrow
544+
case ( defn.BoxedDoubleClass, DoubleClass) => defn.DoubleType.narrow
545+
case ( defn.BoxedUnitClass, UnitClass) => defn.UnitType.narrow
546+
case (defn.BoxedBooleanClass, BooleanClass) => defn.BooleanType.narrow
547+
548+
case _ => convertConstantType(tp1, tp2)
549+
})
520550

521551
/** Is `tp1` a subtype of `tp2`? */
522-
def isSubType(_tp1: Type, tp2: Type): Boolean = {
523-
val tp1 = maybeBox(convertConstantType(_tp1, tp2), tp2)
524-
//debug.println(TypeComparer.explained(_.isSubType(tp1, tp2)))
525-
val res = if (ctx.explicitNulls) {
526-
tp1 <:< tp2
527-
} else {
528-
(tp1 != constantNullType || tp2 == constantNullType) && tp1 <:< tp2
529-
}
530-
debug.println(i"$tp1 <:< $tp2 = $res")
531-
res
552+
def isSubType(tp1: Type, tp2: Type): Boolean = trace(i"$tp1 <:< $tp2", debug, show = true) {
553+
if tp1 == constantNullType && !ctx.explicitNulls then tp2 == constantNullType
554+
else adaptType(tp1, tp2) <:< tp2
532555
}
533556

534557
def isSameUnapply(tp1: TermRef, tp2: TermRef): Boolean =
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
-- Error: tests/neg-custom-args/fatal-warnings/i8711.scala:7:9 ---------------------------------------------------------
1+
-- [E030] Match case Unreachable Error: tests/neg-custom-args/fatal-warnings/i8711.scala:7:9 ---------------------------
22
7 | case x: B => x // error: this case is unreachable since class A is not a subclass of class B
3-
| ^
4-
| this case is unreachable since type A and class B are unrelated
5-
-- Error: tests/neg-custom-args/fatal-warnings/i8711.scala:12:9 --------------------------------------------------------
3+
| ^^^^
4+
| Unreachable case
5+
-- [E030] Match case Unreachable Error: tests/neg-custom-args/fatal-warnings/i8711.scala:12:9 --------------------------
66
12 | case x: C => x // error
7-
| ^
8-
| this case is unreachable since type A | B and class C are unrelated
7+
| ^^^^
8+
| Unreachable case

0 commit comments

Comments
 (0)