@@ -2318,40 +2318,35 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
23182318 else if ! tp2.exists || (tp2 eq WildcardType ) then tp1
23192319 else if tp1.isAny && ! tp2.isLambdaSub || tp1.isAnyKind || isBottom(tp2) then tp2
23202320 else if tp2.isAny && ! tp1.isLambdaSub || tp2.isAnyKind || isBottom(tp1) then tp1
2321- else tp2 match
2322- case tp2 : LazyRef =>
2323- glb(tp1, tp2.ref)
2324- case _ =>
2325- tp1 match
2326- case tp1 : LazyRef =>
2327- glb(tp1.ref, tp2)
2328- case _ =>
2329- val tp1a = dropIfSuper(tp1, tp2)
2330- if tp1a ne tp1 then glb(tp1a, tp2)
2331- else
2332- val tp2a = dropIfSuper(tp2, tp1)
2333- if tp2a ne tp2 then glb(tp1, tp2a)
2334- else tp2 match // normalize to disjunctive normal form if possible.
2335- case tp2 @ OrType (tp21, tp22) =>
2336- lub(tp1 & tp21, tp1 & tp22, isSoft = tp2.isSoft)
2337- case _ =>
2338- tp1 match
2339- case tp1 @ OrType (tp11, tp12) =>
2340- lub(tp11 & tp2, tp12 & tp2, isSoft = tp1.isSoft)
2341- case tp1 : ConstantType =>
2342- tp2 match
2343- case tp2 : ConstantType =>
2344- // Make use of the fact that the intersection of two constant types
2345- // types which are not subtypes of each other is known to be empty.
2346- // Note: The same does not apply to singleton types in general.
2347- // E.g. we could have a pattern match against `x.type & y.type`
2348- // which might succeed if `x` and `y` happen to be the same ref
2349- // at run time. It would not work to replace that with `Nothing`.
2350- // However, maybe we can still apply the replacement to
2351- // types which are not explicitly written.
2352- NothingType
2353- case _ => andType(tp1, tp2)
2321+ else
2322+ def mergedGlb (tp1 : Type , tp2 : Type ): Type =
2323+ val tp1a = dropIfSuper(tp1, tp2)
2324+ if tp1a ne tp1 then glb(tp1a, tp2)
2325+ else
2326+ val tp2a = dropIfSuper(tp2, tp1)
2327+ if tp2a ne tp2 then glb(tp1, tp2a)
2328+ else tp2 match // normalize to disjunctive normal form if possible.
2329+ case tp2 @ OrType (tp21, tp22) =>
2330+ lub(tp1 & tp21, tp1 & tp22, isSoft = tp2.isSoft)
2331+ case _ =>
2332+ tp1 match
2333+ case tp1 @ OrType (tp11, tp12) =>
2334+ lub(tp11 & tp2, tp12 & tp2, isSoft = tp1.isSoft)
2335+ case tp1 : ConstantType =>
2336+ tp2 match
2337+ case tp2 : ConstantType =>
2338+ // Make use of the fact that the intersection of two constant types
2339+ // types which are not subtypes of each other is known to be empty.
2340+ // Note: The same does not apply to singleton types in general.
2341+ // E.g. we could have a pattern match against `x.type & y.type`
2342+ // which might succeed if `x` and `y` happen to be the same ref
2343+ // at run time. It would not work to replace that with `Nothing`.
2344+ // However, maybe we can still apply the replacement to
2345+ // types which are not explicitly written.
2346+ NothingType
23542347 case _ => andType(tp1, tp2)
2348+ case _ => andType(tp1, tp2)
2349+ mergedGlb(dropExpr(tp1.stripLazyRef), dropExpr(tp2.stripLazyRef))
23552350 }
23562351
23572352 def widenInUnions (using Context ): Boolean =
@@ -2390,7 +2385,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
23902385 if ((tp1 ne tp1w) || (tp2 ne tp2w)) lub(tp1w, tp2w, canConstrain = canConstrain, isSoft = isSoft)
23912386 else orType(tp1w, tp2w, isSoft = isSoft) // no need to check subtypes again
23922387 }
2393- mergedLub(tp1.stripLazyRef, tp2.stripLazyRef)
2388+ mergedLub(dropExpr( tp1.stripLazyRef), dropExpr( tp2.stripLazyRef) )
23942389 }
23952390
23962391 /** Try to produce joint arguments for a lub `A[T_1, ..., T_n] | A[T_1', ..., T_n']` using
@@ -2508,6 +2503,19 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
25082503 NoType
25092504 }
25102505
2506+ /** There's a window of vulnerability between ElimByName and Erasure where some
2507+ * ExprTypes `=> T` that appear as parameters of function types are not yet converted
2508+ * to by-name functions `() ?=> T`. These would cause an assertion violation when
2509+ * used as operands of glb or lub. We fix this on the fly here. As explained in
2510+ * ElimByName, we can't fix it beforehand by mapping all occurrences of `=> T` to
2511+ * `() ?=> T` since that could lead to cycles.
2512+ */
2513+ private def dropExpr (tp : Type ): Type = tp match
2514+ case ExprType (rt) if (Phases .elimByNamePhase <= ctx.phase) && ! ctx.erasedTypes =>
2515+ defn.ByNameFunction (rt)
2516+ case _ =>
2517+ tp
2518+
25112519 private def andTypeGen (tp1 : Type , tp2 : Type , op : (Type , Type ) => Type ,
25122520 original : (Type , Type ) => Type = _ & _, isErased : Boolean = ctx.erasedTypes): Type = trace(s " andTypeGen( ${tp1.show}, ${tp2.show}) " , subtyping, show = true ) {
25132521 val t1 = distributeAnd(tp1, tp2)
0 commit comments