Skip to content

Commit 1c87fa5

Browse files
committed
simplify changes to distributeAnd
1 parent 0ad8d59 commit 1c87fa5

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
*/
@@ -2497,15 +2498,18 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
24972498
NoType
24982499
}
24992500

2500-
private def andTypeGen(tp1: Type, tp2: Type, op: (Type, Type) => Type,
2501-
original: (Type, Type) => Type = _ & _, isErased: Boolean = ctx.erasedTypes): Type = trace(s"andTypeGen(${tp1.show}, ${tp2.show})", subtyping, show = true) {
2502-
val t1 = distributeAnd(tp1, tp2)
2503-
if (t1.exists) t1
2504-
else {
2505-
val t2 = distributeAnd(tp2, tp1)
2506-
if (t2.exists) t2
2507-
else if (isErased) erasedGlb(tp1, tp2)
2508-
else liftIfHK(tp1, tp2, op, original, _ | _)
2501+
private def andTypeGen(tp1orig: Type, tp2orig: Type, op: (Type, Type) => Type,
2502+
original: (Type, Type) => Type = _ & _, isErased: Boolean = ctx.erasedTypes): Type = trace(s"andTypeGen(${tp1orig.show}, ${tp2orig.show})", subtyping, show = true) {
2503+
val tp1 = tp1orig.stripFlexible
2504+
val tp2 = tp2orig.stripFlexible
2505+
val ret = {
2506+
val t1 = distributeAnd(tp1, tp2)
2507+
if (t1.exists) t1
2508+
else {
2509+
val t2 = distributeAnd(tp2, tp1)
2510+
if (t2.exists) t2
2511+
else if (isErased) erasedGlb(tp1, tp2)
2512+
else liftIfHK(tp1, tp2, op, original, _ | _)
25092513
// The ` | ` on variances is needed since variances are associated with bounds
25102514
// not lambdas. Example:
25112515
//
@@ -2515,7 +2519,9 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
25152519
//
25162520
// Here, `F` is treated as bivariant in `O`. That is, only bivariant implementation
25172521
// of `F` are allowed. See neg/hk-variance2s.scala test.
2522+
}
25182523
}
2524+
if(tp1orig.isInstanceOf[FlexibleType] && tp2orig.isInstanceOf[FlexibleType]) FlexibleType(ret) else ret
25192525
}
25202526

25212527
/** Form a normalized conjunction of two types.
@@ -2588,73 +2594,53 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
25882594
/** Try to distribute `&` inside type, detect and handle conflicts
25892595
* @pre !(tp1 <: tp2) && !(tp2 <:< tp1) -- these cases were handled before
25902596
*/
2591-
private def distributeAnd(tp1: Type, tp2: Type): Type = {
2592-
var ft1 = false
2593-
var ft2 = false
2594-
def recur(tp1: Type, tp2: Type): Type = tp1 match {
2595-
case tp1 @ FlexibleType(tp) =>
2596-
// Hack -- doesn't generalise to other intersection/union types
2597-
// but covers a common special case for pattern matching
2598-
ft1 = true
2599-
recur(tp, tp2)
2600-
case tp1 @ AppliedType(tycon1, args1) =>
2601-
tp2 match {
2602-
case AppliedType(tycon2, args2)
2603-
if tycon1.typeSymbol == tycon2.typeSymbol && tycon1 =:= tycon2 =>
2604-
val jointArgs = glbArgs(args1, args2, tycon1.typeParams)
2605-
if (jointArgs.forall(_.exists)) (tycon1 & tycon2).appliedTo(jointArgs)
2606-
else {
2607-
NoType
2608-
}
2609-
case FlexibleType(tp) =>
2610-
// Hack from above
2611-
ft2 = true
2612-
recur(tp1, tp)
2613-
case _ =>
2614-
NoType
2615-
}
2616-
2617-
// if result exists and is not notype, maybe wrap result in flex based on whether seen flex on both sides
2618-
case tp1: RefinedType =>
2619-
// opportunistically merge same-named refinements
2620-
// this does not change anything semantically (i.e. merging or not merging
2621-
// gives =:= types), but it keeps the type smaller.
2622-
tp2 match {
2623-
case tp2: RefinedType if tp1.refinedName == tp2.refinedName =>
2624-
val jointInfo = Denotations.infoMeet(tp1.refinedInfo, tp2.refinedInfo, safeIntersection = false)
2625-
if jointInfo.exists then
2626-
tp1.derivedRefinedType(tp1.parent & tp2.parent, tp1.refinedName, jointInfo)
2627-
else
2628-
NoType
2629-
case _ =>
2630-
NoType
2631-
}
2632-
case tp1: RecType =>
2633-
tp1.rebind(recur(tp1.parent, tp2))
2634-
case ExprType(rt1) =>
2635-
tp2 match {
2636-
case ExprType(rt2) =>
2637-
ExprType(rt1 & rt2)
2638-
case _ =>
2597+
private def distributeAnd(tp1: Type, tp2: Type): Type = tp1 match {
2598+
case tp1 @ AppliedType(tycon1, args1) =>
2599+
tp2 match {
2600+
case AppliedType(tycon2, args2)
2601+
if tycon1.typeSymbol == tycon2.typeSymbol && tycon1 =:= tycon2 =>
2602+
val jointArgs = glbArgs(args1, args2, tycon1.typeParams)
2603+
if (jointArgs.forall(_.exists)) (tycon1 & tycon2).appliedTo(jointArgs)
2604+
else NoType
2605+
case _ =>
2606+
NoType
2607+
}
2608+
case tp1: RefinedType =>
2609+
// opportunistically merge same-named refinements
2610+
// this does not change anything semantically (i.e. merging or not merging
2611+
// gives =:= types), but it keeps the type smaller.
2612+
tp2 match {
2613+
case tp2: RefinedType if tp1.refinedName == tp2.refinedName =>
2614+
val jointInfo = Denotations.infoMeet(tp1.refinedInfo, tp2.refinedInfo, safeIntersection = false)
2615+
if jointInfo.exists then
2616+
tp1.derivedRefinedType(tp1.parent & tp2.parent, tp1.refinedName, jointInfo)
2617+
else
26392618
NoType
2640-
}
2641-
case tp1: TypeVar if tp1.isInstantiated =>
2642-
tp1.underlying & tp2
2643-
case CapturingType(parent1, refs1) =>
2644-
if subCaptures(tp2.captureSet, refs1, frozen = true).isOK
2645-
&& tp1.isBoxedCapturing == tp2.isBoxedCapturing
2646-
then
2647-
parent1 & tp2
2648-
else
2649-
tp1.derivedCapturingType(parent1 & tp2, refs1)
2650-
case tp1: AnnotatedType if !tp1.isRefining =>
2651-
tp1.underlying & tp2
2652-
case _ =>
2653-
NoType
2654-
}
2655-
// if flex on both sides, return flex type
2656-
val ret = recur(tp1, tp2)
2657-
if (ft1 && ft2) then FlexibleType(ret) else ret
2619+
case _ =>
2620+
NoType
2621+
}
2622+
case tp1: RecType =>
2623+
tp1.rebind(distributeAnd(tp1.parent, tp2))
2624+
case ExprType(rt1) =>
2625+
tp2 match {
2626+
case ExprType(rt2) =>
2627+
ExprType(rt1 & rt2)
2628+
case _ =>
2629+
NoType
2630+
}
2631+
case tp1: TypeVar if tp1.isInstantiated =>
2632+
tp1.underlying & tp2
2633+
case CapturingType(parent1, refs1) =>
2634+
if subCaptures(tp2.captureSet, refs1, frozen = true).isOK
2635+
&& tp1.isBoxedCapturing == tp2.isBoxedCapturing
2636+
then
2637+
parent1 & tp2
2638+
else
2639+
tp1.derivedCapturingType(parent1 & tp2, refs1)
2640+
case tp1: AnnotatedType if !tp1.isRefining =>
2641+
tp1.underlying & tp2
2642+
case _ =>
2643+
NoType
26582644
}
26592645

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

0 commit comments

Comments
 (0)