Skip to content

Commit 6ac8bcd

Browse files
committed
simplify changes to distributeAnd
1 parent 6544215 commit 6ac8bcd

File tree

1 file changed

+61
-75
lines changed

1 file changed

+61
-75
lines changed

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

Lines changed: 61 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import reporting.trace
2525
import annotation.constructorOnly
2626
import cc.{CapturingType, derivedCapturingType, CaptureSet, stripCapturing, isBoxedCapturing, boxed, boxedUnlessFun, boxedIfTypeParam, isAlwaysPure}
2727
import NameKinds.WildcardParamName
28+
import NullOpsDecorator.stripFlexible
2829

2930
/** Provides methods to compare types.
3031
*/
@@ -2462,15 +2463,18 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
24622463
NoType
24632464
}
24642465

2465-
private def andTypeGen(tp1: Type, tp2: Type, op: (Type, Type) => Type,
2466-
original: (Type, Type) => Type = _ & _, isErased: Boolean = ctx.erasedTypes): Type = trace(s"andTypeGen(${tp1.show}, ${tp2.show})", subtyping, show = true) {
2467-
val t1 = distributeAnd(tp1, tp2)
2468-
if (t1.exists) t1
2469-
else {
2470-
val t2 = distributeAnd(tp2, tp1)
2471-
if (t2.exists) t2
2472-
else if (isErased) erasedGlb(tp1, tp2)
2473-
else liftIfHK(tp1, tp2, op, original, _ | _)
2466+
private def andTypeGen(tp1orig: Type, tp2orig: Type, op: (Type, Type) => Type,
2467+
original: (Type, Type) => Type = _ & _, isErased: Boolean = ctx.erasedTypes): Type = trace(s"andTypeGen(${tp1orig.show}, ${tp2orig.show})", subtyping, show = true) {
2468+
val tp1 = tp1orig.stripFlexible
2469+
val tp2 = tp2orig.stripFlexible
2470+
val ret = {
2471+
val t1 = distributeAnd(tp1, tp2)
2472+
if (t1.exists) t1
2473+
else {
2474+
val t2 = distributeAnd(tp2, tp1)
2475+
if (t2.exists) t2
2476+
else if (isErased) erasedGlb(tp1, tp2)
2477+
else liftIfHK(tp1, tp2, op, original, _ | _)
24742478
// The ` | ` on variances is needed since variances are associated with bounds
24752479
// not lambdas. Example:
24762480
//
@@ -2480,7 +2484,9 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
24802484
//
24812485
// Here, `F` is treated as bivariant in `O`. That is, only bivariant implementation
24822486
// of `F` are allowed. See neg/hk-variance2s.scala test.
2487+
}
24832488
}
2489+
if(tp1orig.isInstanceOf[FlexibleType] && tp2orig.isInstanceOf[FlexibleType]) FlexibleType(ret) else ret
24842490
}
24852491

24862492
/** Form a normalized conjunction of two types.
@@ -2552,73 +2558,53 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
25522558
/** Try to distribute `&` inside type, detect and handle conflicts
25532559
* @pre !(tp1 <: tp2) && !(tp2 <:< tp1) -- these cases were handled before
25542560
*/
2555-
private def distributeAnd(tp1: Type, tp2: Type): Type = {
2556-
var ft1 = false
2557-
var ft2 = false
2558-
def recur(tp1: Type, tp2: Type): Type = tp1 match {
2559-
case tp1 @ FlexibleType(tp) =>
2560-
// Hack -- doesn't generalise to other intersection/union types
2561-
// but covers a common special case for pattern matching
2562-
ft1 = true
2563-
recur(tp, tp2)
2564-
case tp1 @ AppliedType(tycon1, args1) =>
2565-
tp2 match {
2566-
case AppliedType(tycon2, args2)
2567-
if tycon1.typeSymbol == tycon2.typeSymbol && tycon1 =:= tycon2 =>
2568-
val jointArgs = glbArgs(args1, args2, tycon1.typeParams)
2569-
if (jointArgs.forall(_.exists)) (tycon1 & tycon2).appliedTo(jointArgs)
2570-
else {
2571-
NoType
2572-
}
2573-
case FlexibleType(tp) =>
2574-
// Hack from above
2575-
ft2 = true
2576-
recur(tp1, tp)
2577-
case _ =>
2578-
NoType
2579-
}
2580-
2581-
// if result exists and is not notype, maybe wrap result in flex based on whether seen flex on both sides
2582-
case tp1: RefinedType =>
2583-
// opportunistically merge same-named refinements
2584-
// this does not change anything semantically (i.e. merging or not merging
2585-
// gives =:= types), but it keeps the type smaller.
2586-
tp2 match {
2587-
case tp2: RefinedType if tp1.refinedName == tp2.refinedName =>
2588-
val jointInfo = Denotations.infoMeet(tp1.refinedInfo, tp2.refinedInfo, safeIntersection = false)
2589-
if jointInfo.exists then
2590-
tp1.derivedRefinedType(tp1.parent & tp2.parent, tp1.refinedName, jointInfo)
2591-
else
2592-
NoType
2593-
case _ =>
2594-
NoType
2595-
}
2596-
case tp1: RecType =>
2597-
tp1.rebind(recur(tp1.parent, tp2))
2598-
case ExprType(rt1) =>
2599-
tp2 match {
2600-
case ExprType(rt2) =>
2601-
ExprType(rt1 & rt2)
2602-
case _ =>
2561+
private def distributeAnd(tp1: Type, tp2: Type): Type = tp1 match {
2562+
case tp1 @ AppliedType(tycon1, args1) =>
2563+
tp2 match {
2564+
case AppliedType(tycon2, args2)
2565+
if tycon1.typeSymbol == tycon2.typeSymbol && tycon1 =:= tycon2 =>
2566+
val jointArgs = glbArgs(args1, args2, tycon1.typeParams)
2567+
if (jointArgs.forall(_.exists)) (tycon1 & tycon2).appliedTo(jointArgs)
2568+
else NoType
2569+
case _ =>
2570+
NoType
2571+
}
2572+
case tp1: RefinedType =>
2573+
// opportunistically merge same-named refinements
2574+
// this does not change anything semantically (i.e. merging or not merging
2575+
// gives =:= types), but it keeps the type smaller.
2576+
tp2 match {
2577+
case tp2: RefinedType if tp1.refinedName == tp2.refinedName =>
2578+
val jointInfo = Denotations.infoMeet(tp1.refinedInfo, tp2.refinedInfo, safeIntersection = false)
2579+
if jointInfo.exists then
2580+
tp1.derivedRefinedType(tp1.parent & tp2.parent, tp1.refinedName, jointInfo)
2581+
else
26032582
NoType
2604-
}
2605-
case tp1: TypeVar if tp1.isInstantiated =>
2606-
tp1.underlying & tp2
2607-
case CapturingType(parent1, refs1) =>
2608-
if subCaptures(tp2.captureSet, refs1, frozen = true).isOK
2609-
&& tp1.isBoxedCapturing == tp2.isBoxedCapturing
2610-
then
2611-
parent1 & tp2
2612-
else
2613-
tp1.derivedCapturingType(parent1 & tp2, refs1)
2614-
case tp1: AnnotatedType if !tp1.isRefining =>
2615-
tp1.underlying & tp2
2616-
case _ =>
2617-
NoType
2618-
}
2619-
// if flex on both sides, return flex type
2620-
val ret = recur(tp1, tp2)
2621-
if (ft1 && ft2) then FlexibleType(ret) else ret
2583+
case _ =>
2584+
NoType
2585+
}
2586+
case tp1: RecType =>
2587+
tp1.rebind(distributeAnd(tp1.parent, tp2))
2588+
case ExprType(rt1) =>
2589+
tp2 match {
2590+
case ExprType(rt2) =>
2591+
ExprType(rt1 & rt2)
2592+
case _ =>
2593+
NoType
2594+
}
2595+
case tp1: TypeVar if tp1.isInstantiated =>
2596+
tp1.underlying & tp2
2597+
case CapturingType(parent1, refs1) =>
2598+
if subCaptures(tp2.captureSet, refs1, frozen = true).isOK
2599+
&& tp1.isBoxedCapturing == tp2.isBoxedCapturing
2600+
then
2601+
parent1 & tp2
2602+
else
2603+
tp1.derivedCapturingType(parent1 & tp2, refs1)
2604+
case tp1: AnnotatedType if !tp1.isRefining =>
2605+
tp1.underlying & tp2
2606+
case _ =>
2607+
NoType
26222608
}
26232609

26242610
/** Try to distribute `|` inside type, detect and handle conflicts

0 commit comments

Comments
 (0)