Skip to content

Commit 64fe532

Browse files
committed
Fix #10108: Keep an isSoft flag in OrTypes
It turned out that it's generally clear whether an OrType should be soft or hard, so this is a good first step to solve the problem.
1 parent ac4e29d commit 64fe532

File tree

9 files changed

+33
-27
lines changed

9 files changed

+33
-27
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ class Definitions {
440440
def AnyKindType: TypeRef = AnyKindClass.typeRef
441441

442442
@tu lazy val andType: TypeSymbol = enterBinaryAlias(tpnme.AND, AndType(_, _))
443-
@tu lazy val orType: TypeSymbol = enterBinaryAlias(tpnme.OR, OrType(_, _))
443+
@tu lazy val orType: TypeSymbol = enterBinaryAlias(tpnme.OR, OrType(_, _, soft = false))
444444

445445
/** Marker method to indicate an argument to a call-by-name parameter.
446446
* Created by byNameClosures and elimByName, eliminated by Erasure,

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

+3
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ trait Hashable {
9393
protected final def doHash(bs: Binders, x1: Int, tp2: Type): Int =
9494
finishHash(bs, hashing.mix(hashSeed, x1), 1, tp2)
9595

96+
protected final def doHash(bs: Binders, x1: Int, tp2: Type, tp3: Type): Int =
97+
finishHash(bs, hashing.mix(hashSeed, x1), 1, tp2, tp3)
98+
9699
protected final def doHash(bs: Binders, tp1: Type, tp2: Type): Int =
97100
finishHash(bs, hashSeed, 0, tp1, tp2)
98101

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
614614
}
615615
}
616616
compareTypeLambda
617-
case OrType(tp21, tp22) =>
617+
case tp2 as OrType(tp21, tp22) =>
618618
compareAtoms(tp1, tp2) match
619619
case Some(b) => return b
620620
case _ =>
@@ -646,12 +646,12 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
646646
// solutions. The rewriting delays the point where we have to choose.
647647
tp21 match {
648648
case AndType(tp211, tp212) =>
649-
return recur(tp1, OrType(tp211, tp22)) && recur(tp1, OrType(tp212, tp22))
649+
return recur(tp1, OrType(tp211, tp22, tp2.isSoft)) && recur(tp1, OrType(tp212, tp22, tp2.isSoft))
650650
case _ =>
651651
}
652652
tp22 match {
653653
case AndType(tp221, tp222) =>
654-
return recur(tp1, OrType(tp21, tp221)) && recur(tp1, OrType(tp21, tp222))
654+
return recur(tp1, OrType(tp21, tp221, tp2.isSoft)) && recur(tp1, OrType(tp21, tp222, tp2.isSoft))
655655
case _ =>
656656
}
657657
either(recur(tp1, tp21), recur(tp1, tp22)) || fourthTry
@@ -2121,7 +2121,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
21212121
val t2 = distributeOr(tp2, tp1)
21222122
if (t2.exists) t2
21232123
else if (isErased) erasedLub(tp1, tp2)
2124-
else liftIfHK(tp1, tp2, OrType(_, _), _ | _, _ & _)
2124+
else liftIfHK(tp1, tp2, OrType(_, _, soft = true), _ | _, _ & _)
21252125
}
21262126
}
21272127

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

+17-14
Original file line numberDiff line numberDiff line change
@@ -1040,7 +1040,7 @@ object Types {
10401040
def safe_& (that: Type)(using Context): Type = (this, that) match {
10411041
case (TypeBounds(lo1, hi1), TypeBounds(lo2, hi2)) =>
10421042
TypeBounds(
1043-
OrType.makeHk(lo1.stripLazyRef, lo2.stripLazyRef),
1043+
OrType.makeHk(lo1.stripLazyRef, lo2.stripLazyRef),
10441044
AndType.makeHk(hi1.stripLazyRef, hi2.stripLazyRef))
10451045
case _ =>
10461046
this & that
@@ -2907,8 +2907,9 @@ object Types {
29072907

29082908
def derivedAndOrType(tp1: Type, tp2: Type)(using Context) =
29092909
if ((tp1 eq this.tp1) && (tp2 eq this.tp2)) this
2910-
else if (isAnd) AndType.make(tp1, tp2, checkValid = true)
2911-
else OrType.make(tp1, tp2)
2910+
else this match
2911+
case tp: OrType => OrType.make(tp1, tp2, tp.isSoft)
2912+
case tp: AndType => AndType.make(tp1, tp2, checkValid = true)
29122913
}
29132914

29142915
abstract case class AndType(tp1: Type, tp2: Type) extends AndOrType {
@@ -2982,6 +2983,7 @@ object Types {
29822983

29832984
abstract case class OrType(tp1: Type, tp2: Type) extends AndOrType {
29842985
def isAnd: Boolean = false
2986+
def isSoft: Boolean
29852987
private var myBaseClassesPeriod: Period = Nowhere
29862988
private var myBaseClasses: List[ClassSymbol] = _
29872989
/** Base classes of are the intersection of the operand base classes. */
@@ -3044,30 +3046,31 @@ object Types {
30443046

30453047
def derivedOrType(tp1: Type, tp2: Type)(using Context): Type =
30463048
if ((tp1 eq this.tp1) && (tp2 eq this.tp2)) this
3047-
else OrType.make(tp1, tp2)
3049+
else OrType.make(tp1, tp2, isSoft)
30483050

3049-
override def computeHash(bs: Binders): Int = doHash(bs, tp1, tp2)
3051+
override def computeHash(bs: Binders): Int =
3052+
doHash(bs, if isSoft then 0 else 1, tp1, tp2)
30503053

30513054
override def eql(that: Type): Boolean = that match {
3052-
case that: OrType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
3055+
case that: OrType => tp1.eq(that.tp1) && tp2.eq(that.tp2) && isSoft == that.isSoft
30533056
case _ => false
30543057
}
30553058
}
30563059

3057-
final class CachedOrType(tp1: Type, tp2: Type) extends OrType(tp1, tp2)
3060+
final class CachedOrType(tp1: Type, tp2: Type, override val isSoft: Boolean) extends OrType(tp1, tp2)
30583061

30593062
object OrType {
3060-
def apply(tp1: Type, tp2: Type)(using Context): OrType = {
3063+
def apply(tp1: Type, tp2: Type, soft: Boolean)(using Context): OrType = {
30613064
assertUnerased()
3062-
unique(new CachedOrType(tp1, tp2))
3065+
unique(new CachedOrType(tp1, tp2, soft))
30633066
}
3064-
def make(tp1: Type, tp2: Type)(using Context): Type =
3067+
def make(tp1: Type, tp2: Type, soft: Boolean)(using Context): Type =
30653068
if (tp1 eq tp2) tp1
3066-
else apply(tp1, tp2)
3069+
else apply(tp1, tp2, soft)
30673070

30683071
/** Like `make`, but also supports higher-kinded types as argument */
30693072
def makeHk(tp1: Type, tp2: Type)(using Context): Type =
3070-
TypeComparer.liftIfHK(tp1, tp2, OrType(_, _), makeHk, _ & _)
3073+
TypeComparer.liftIfHK(tp1, tp2, OrType(_, _, soft = true), makeHk, _ & _)
30713074
}
30723075

30733076
/** An extractor object to pattern match against a nullable union.
@@ -3079,7 +3082,7 @@ object Types {
30793082
*/
30803083
object OrNull {
30813084
def apply(tp: Type)(using Context) =
3082-
OrType(tp, defn.NullType)
3085+
OrType(tp, defn.NullType, soft = false)
30833086
def unapply(tp: Type)(using Context): Option[Type] =
30843087
if (ctx.explicitNulls) {
30853088
val tp1 = tp.stripNull()
@@ -3097,7 +3100,7 @@ object Types {
30973100
*/
30983101
object OrUncheckedNull {
30993102
def apply(tp: Type)(using Context) =
3100-
OrType(tp, defn.UncheckedNullAliasType)
3103+
OrType(tp, defn.UncheckedNullAliasType, soft = false)
31013104
def unapply(tp: Type)(using Context): Option[Type] =
31023105
if (ctx.explicitNulls) {
31033106
val tp1 = tp.stripUncheckedNull

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ class TreeUnpickler(reader: TastyReader,
368368
case ANDtype =>
369369
AndType(readType(), readType())
370370
case ORtype =>
371-
OrType(readType(), readType())
371+
OrType(readType(), readType(), soft = false)
372372
case SUPERtype =>
373373
SuperType(readType(), readType())
374374
case MATCHtype =>
@@ -1222,7 +1222,7 @@ class TreeUnpickler(reader: TastyReader,
12221222
val args = until(end)(readTpt())
12231223
val ownType =
12241224
if (tycon.symbol == defn.andType) AndType(args(0).tpe, args(1).tpe)
1225-
else if (tycon.symbol == defn.orType) OrType(args(0).tpe, args(1).tpe)
1225+
else if (tycon.symbol == defn.orType) OrType(args(0).tpe, args(1).tpe, soft = false)
12261226
else tycon.tpe.safeAppliedTo(args.tpes)
12271227
untpd.AppliedTypeTree(tycon, args).withType(ownType)
12281228
case ANNOTATEDtpt =>

compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1823,7 +1823,7 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext:
18231823
end OrTypeTypeTest
18241824

18251825
object OrType extends OrTypeModule:
1826-
def apply(lhs: TypeRepr, rhs: TypeRepr): OrType = Types.OrType(lhs, rhs)
1826+
def apply(lhs: TypeRepr, rhs: TypeRepr): OrType = Types.OrType(lhs, rhs, soft = false)
18271827
def unapply(x: OrType): Option[(TypeRepr, TypeRepr)] = Some((x.left, x.right))
18281828
end OrType
18291829

compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ object TypeTestsCasts {
7070
case tref: TypeRef if tref.typeSymbol.isPatternBound =>
7171
if (variance == 1) tref.info.hiBound
7272
else if (variance == -1) tref.info.loBound
73-
else OrType(defn.AnyType, defn.NothingType)
73+
else OrType(defn.AnyType, defn.NothingType, soft = true)
7474
case _ => mapOver(tp)
7575
}
7676
}.apply(tp)

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -477,8 +477,8 @@ class SpaceEngine(using Context) extends SpaceLogic {
477477
else args.map(arg => erase(arg, inArray = false))
478478
tp.derivedAppliedType(erase(tycon, inArray), args2)
479479

480-
case OrType(tp1, tp2) =>
481-
OrType(erase(tp1, inArray), erase(tp2, inArray))
480+
case tp as OrType(tp1, tp2) =>
481+
OrType(erase(tp1, inArray), erase(tp2, inArray), tp.isSoft)
482482

483483
case AndType(tp1, tp2) =>
484484
AndType(erase(tp1, inArray), erase(tp2, inArray))
@@ -870,7 +870,7 @@ class SpaceEngine(using Context) extends SpaceLogic {
870870
if (ctx.explicitNulls || selTyp.classSymbol.isPrimitiveValueClass)
871871
project(selTyp)
872872
else
873-
project(OrType(selTyp, constantNullType))
873+
project(OrType(selTyp, constantNullType, soft = false))
874874

875875
// in redundancy check, take guard as false in order to soundly approximate
876876
def projectPrevCases(cases: List[CaseDef]): Space =

compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ trait TypeAssigner {
463463
val ownType =
464464
if (sameLength(tparams, args))
465465
if (tycon.symbol == defn.andType) AndType(args(0).tpe, args(1).tpe)
466-
else if (tycon.symbol == defn.orType) OrType(args(0).tpe, args(1).tpe)
466+
else if (tycon.symbol == defn.orType) OrType(args(0).tpe, args(1).tpe, soft = false)
467467
else tycon.tpe.appliedTo(args.tpes)
468468
else wrongNumberOfTypeArgs(tycon.tpe, tparams, args, tree.srcPos)
469469
tree.withType(ownType)

0 commit comments

Comments
 (0)