Skip to content

Commit 48790dd

Browse files
committed
Restore adaptType, with expanded docs & tests
1 parent b9ecea2 commit 48790dd

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

+14
Original file line numberDiff line numberDiff line change
@@ -1731,6 +1731,20 @@ class Definitions {
17311731
else sys.error(s"Not a primitive value type: $tp")
17321732
}.typeRef
17331733

1734+
def unboxedType(tp: Type)(using Context): TypeRef = {
1735+
val cls = tp.classSymbol
1736+
if (cls eq BoxedByteClass) ByteType
1737+
else if (cls eq BoxedShortClass) ShortType
1738+
else if (cls eq BoxedCharClass) CharType
1739+
else if (cls eq BoxedIntClass) IntType
1740+
else if (cls eq BoxedLongClass) LongType
1741+
else if (cls eq BoxedFloatClass) FloatType
1742+
else if (cls eq BoxedDoubleClass) DoubleType
1743+
else if (cls eq BoxedUnitClass) UnitType
1744+
else if (cls eq BoxedBooleanClass) BooleanType
1745+
else sys.error(s"Not a boxed primitive value type: $tp")
1746+
}
1747+
17341748
/** The JVM tag for `tp` if it's a primitive, `java.lang.Object` otherwise. */
17351749
def typeTag(tp: Type)(using Context): Name = typeTags(scalaClassName(tp))
17361750

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

+16-3
Original file line numberDiff line numberDiff line change
@@ -515,12 +515,25 @@ class SpaceEngine(using Context) extends SpaceLogic {
515515
def isPrimToBox(tp: Type, pt: Type) =
516516
tp.classSymbol.isPrimitiveValueClass && (defn.boxedType(tp).classSymbol eq pt.classSymbol)
517517

518+
/** Adapt types by performing primitive value unboxing or boxing, or numeric constant conversion. #12805
519+
*
520+
* This makes these isSubType cases work like this:
521+
* {{{
522+
* 1 <:< Integer => (<skolem> : Integer) <:< Integer = true
523+
* ONE <:< Int => (<skolem> : Int) <:< Int = true
524+
* Integer <:< (1: Int) => (<skolem> : Int) <:< (1: Int) = false
525+
* }}}
526+
*/
527+
def adaptType(tp1: Type, tp2: Type): Type = trace(i"adaptType($tp1, $tp2)", show = true) {
528+
if isPrimToBox(tp1, tp2) then defn.boxedType(tp1).narrow
529+
else if isPrimToBox(tp2, tp1) then defn.unboxedType(tp1).narrow
530+
else convertConstantType(tp1, tp2)
531+
}
532+
518533
/** Is `tp1` a subtype of `tp2`? */
519534
def isSubType(tp1: Type, tp2: Type): Boolean = trace(i"$tp1 <:< $tp2", debug, show = true) {
520535
if tp1 == constantNullType && !ctx.explicitNulls then tp2 == constantNullType
521-
else
522-
isPrimToBox(tp1, tp2) || isPrimToBox(tp2, tp1) ||
523-
convertConstantType(tp1, tp2) <:< tp2
536+
else adaptType(tp1, tp2) <:< tp2
524537
}
525538

526539
def isSameUnapply(tp1: TermRef, tp2: TermRef): Boolean =

compiler/test/dotty/tools/dotc/transform/SpaceEngineTest.scala

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package transform
44

55
import org.junit.*, Assert.*
66

7-
import core.*, Contexts.*, Decorators.*, Symbols.*, Types.*
7+
import core.*, Constants.*, Contexts.*, Decorators.*, Symbols.*, Types.*
88

99
class SpaceEngineTest extends DottyTest:
1010
@Test def testAdaptTest(): Unit =
@@ -14,6 +14,12 @@ class SpaceEngineTest extends DottyTest:
1414
val e = patmat.SpaceEngine()
1515

1616
val BoxedIntType = BoxedIntClass.typeRef
17+
val ConstOneType = ConstantType(Constant(1))
1718

1819
assertTrue(e.isPrimToBox(IntType, BoxedIntType))
1920
assertFalse(e.isPrimToBox(BoxedIntType, IntType))
21+
assertTrue(e.isPrimToBox(ConstOneType, BoxedIntType))
22+
23+
assertEquals(BoxedIntType, e.adaptType(IntType, BoxedIntType).widenSingleton)
24+
assertEquals(IntType, e.adaptType(BoxedIntType, IntType).widenSingleton)
25+
assertEquals(IntType, e.adaptType(BoxedIntType, ConstOneType).widenSingleton)

0 commit comments

Comments
 (0)