@@ -2230,40 +2230,35 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
2230
2230
else if ! tp2.exists || (tp2 eq WildcardType ) then tp1
2231
2231
else if tp1.isAny && ! tp2.isLambdaSub || tp1.isAnyKind || isBottom(tp2) then tp2
2232
2232
else if tp2.isAny && ! tp1.isLambdaSub || tp2.isAnyKind || isBottom(tp1) then tp1
2233
- else tp2 match
2234
- case tp2 : LazyRef =>
2235
- glb(tp1, tp2.ref)
2236
- case _ =>
2237
- tp1 match
2238
- case tp1 : LazyRef =>
2239
- glb(tp1.ref, tp2)
2240
- case _ =>
2241
- val tp1a = dropIfSuper(tp1, tp2)
2242
- if tp1a ne tp1 then glb(tp1a, tp2)
2243
- else
2244
- val tp2a = dropIfSuper(tp2, tp1)
2245
- if tp2a ne tp2 then glb(tp1, tp2a)
2246
- else tp2 match // normalize to disjunctive normal form if possible.
2247
- case tp2 @ OrType (tp21, tp22) =>
2248
- lub(tp1 & tp21, tp1 & tp22, isSoft = tp2.isSoft)
2249
- case _ =>
2250
- tp1 match
2251
- case tp1 @ OrType (tp11, tp12) =>
2252
- lub(tp11 & tp2, tp12 & tp2, isSoft = tp1.isSoft)
2253
- case tp1 : ConstantType =>
2254
- tp2 match
2255
- case tp2 : ConstantType =>
2256
- // Make use of the fact that the intersection of two constant types
2257
- // types which are not subtypes of each other is known to be empty.
2258
- // Note: The same does not apply to singleton types in general.
2259
- // E.g. we could have a pattern match against `x.type & y.type`
2260
- // which might succeed if `x` and `y` happen to be the same ref
2261
- // at run time. It would not work to replace that with `Nothing`.
2262
- // However, maybe we can still apply the replacement to
2263
- // types which are not explicitly written.
2264
- NothingType
2265
- case _ => andType(tp1, tp2)
2233
+ else
2234
+ def mergedGlb (tp1 : Type , tp2 : Type ): Type =
2235
+ val tp1a = dropIfSuper(tp1, tp2)
2236
+ if tp1a ne tp1 then glb(tp1a, tp2)
2237
+ else
2238
+ val tp2a = dropIfSuper(tp2, tp1)
2239
+ if tp2a ne tp2 then glb(tp1, tp2a)
2240
+ else tp2 match // normalize to disjunctive normal form if possible.
2241
+ case tp2 @ OrType (tp21, tp22) =>
2242
+ lub(tp1 & tp21, tp1 & tp22, isSoft = tp2.isSoft)
2243
+ case _ =>
2244
+ tp1 match
2245
+ case tp1 @ OrType (tp11, tp12) =>
2246
+ lub(tp11 & tp2, tp12 & tp2, isSoft = tp1.isSoft)
2247
+ case tp1 : ConstantType =>
2248
+ tp2 match
2249
+ case tp2 : ConstantType =>
2250
+ // Make use of the fact that the intersection of two constant types
2251
+ // types which are not subtypes of each other is known to be empty.
2252
+ // Note: The same does not apply to singleton types in general.
2253
+ // E.g. we could have a pattern match against `x.type & y.type`
2254
+ // which might succeed if `x` and `y` happen to be the same ref
2255
+ // at run time. It would not work to replace that with `Nothing`.
2256
+ // However, maybe we can still apply the replacement to
2257
+ // types which are not explicitly written.
2258
+ NothingType
2266
2259
case _ => andType(tp1, tp2)
2260
+ case _ => andType(tp1, tp2)
2261
+ mergedGlb(dropExpr(tp1.stripLazyRef), dropExpr(tp2.stripLazyRef))
2267
2262
}
2268
2263
2269
2264
def widenInUnions (using Context ): Boolean =
@@ -2303,7 +2298,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
2303
2298
if ((tp1 ne tp1w) || (tp2 ne tp2w)) lub(tp1w, tp2w, canConstrain = canConstrain, isSoft = isSoft)
2304
2299
else orType(tp1w, tp2w, isSoft = isSoft) // no need to check subtypes again
2305
2300
}
2306
- mergedLub(tp1.stripLazyRef, tp2.stripLazyRef)
2301
+ mergedLub(dropExpr( tp1.stripLazyRef), dropExpr( tp2.stripLazyRef) )
2307
2302
}
2308
2303
2309
2304
/** Try to produce joint arguments for a lub `A[T_1, ..., T_n] | A[T_1', ..., T_n']` using
@@ -2421,6 +2416,19 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
2421
2416
NoType
2422
2417
}
2423
2418
2419
+ /** There's a window of vulnerability between ElimByName and Erasure where some
2420
+ * ExprTypes `=> T` that appear as parameters of function types are not yet converted
2421
+ * to by-name functions `() ?=> T`. These would cause an assertion violation when
2422
+ * used as operands of glb or lub. We fix this on the fly here. As explained in
2423
+ * ElimByName, we can't fix it beforehand by mapping all occurrences of `=> T` to
2424
+ * `() ?=> T` since that could lead to cycles.
2425
+ */
2426
+ private def dropExpr (tp : Type ): Type = tp match
2427
+ case ExprType (rt) if (Phases .elimByNamePhase <= ctx.phase) && ! ctx.erasedTypes =>
2428
+ defn.ByNameFunction (rt)
2429
+ case _ =>
2430
+ tp
2431
+
2424
2432
private def andTypeGen (tp1 : Type , tp2 : Type , op : (Type , Type ) => Type ,
2425
2433
original : (Type , Type ) => Type = _ & _, isErased : Boolean = ctx.erasedTypes): Type = trace(s " andTypeGen( ${tp1.show}, ${tp2.show}) " , subtyping, show = true ) {
2426
2434
val t1 = distributeAnd(tp1, tp2)
0 commit comments