@@ -385,7 +385,7 @@ object Denotations {
385
385
*
386
386
* If there is no preferred accessible denotation, return a JointRefDenotation
387
387
* with one of the operand symbols (unspecified which one), and an info which
388
- * is the intersection ( using `&` or `safe_&` if `safeIntersection` is true)
388
+ * is the intersection using `&` or `safe_&` if `safeIntersection` is true)
389
389
* of the infos of the operand denotations.
390
390
*/
391
391
def & (that : Denotation , pre : Type , safeIntersection : Boolean = false )(implicit ctx : Context ): Denotation = {
@@ -542,82 +542,70 @@ object Denotations {
542
542
(for ((name1, name2, idx) <- tp1.paramNames.lazyZip(tp2.paramNames).lazyZip(tp1.paramNames.indices))
543
543
yield if (name1 == name2) name1 else tp1.companion.syntheticParamName(idx)).toList
544
544
545
- /** Normally, `tp1 & tp2`
546
- * Special cases for matching methods and classes, with
547
- * the possibility of returning NoType.
548
- * Special handling of ExprTypes, where mixed intersections widen the ExprType away.
549
- */
545
+ /** Normally, `tp1 & tp2`, with extra care taken to return `tp1` or `tp2` directly if that's
546
+ * a valid answer. Special cases for matching methods and classes, with
547
+ * the possibility of returning NoType. Special handling of ExprTypes, where mixed
548
+ * intersections widen the ExprType away.
549
+ */
550
550
def infoMeet (tp1 : Type , tp2 : Type , safeIntersection : Boolean )(implicit ctx : Context ): Type =
551
- if ( tp1 eq tp2) tp1
552
- else tp1 match {
551
+ if tp1 eq tp2 then tp1
552
+ else tp1 match
553
553
case tp1 : TypeBounds =>
554
- tp2 match {
555
- case tp2 : TypeBounds => if ( safeIntersection) tp1 safe_& tp2 else tp1 & tp2
554
+ tp2 match
555
+ case tp2 : TypeBounds => if safeIntersection then tp1 safe_& tp2 else tp1 & tp2
556
556
case tp2 : ClassInfo => tp2
557
557
case _ => NoType
558
- }
559
558
case tp1 : ClassInfo =>
560
- tp2 match {
559
+ tp2 match
561
560
case tp2 : ClassInfo if tp1.cls eq tp2.cls => tp1.derivedClassInfo(tp1.prefix & tp2.prefix)
562
561
case tp2 : TypeBounds => tp1
563
562
case _ => NoType
564
- }
565
-
566
- // Two remedial strategies:
567
- //
568
- // 1. Prefer method types over poly types. This is necessary to handle
569
- // overloaded definitions like the following
570
- //
571
- // def ++ [B >: A](xs: C[B]): D[B]
572
- // def ++ (xs: C[A]): D[A]
573
- //
574
- // (Code like this is found in the collection strawman)
575
- //
576
- // 2. In the case of two method types or two polytypes with matching
577
- // parameters and implicit status, merge corresponding parameter
578
- // and result types.
579
563
case tp1 : MethodType =>
580
- tp2 match {
564
+ tp2 match
581
565
case tp2 : MethodType
582
566
if ctx.typeComparer.matchingMethodParams(tp1, tp2) && (tp1.companion eq tp2.companion) =>
583
- val resType = infoMeet(tp1.resType, tp2.resType.subst(tp2, tp1), safeIntersection)
584
- if resType.exists then
585
- tp1.derivedLambdaType(mergeParamNames(tp1, tp2), tp1.paramInfos, resType)
586
- else
587
- NoType
567
+ val resType1 = tp1.resType
568
+ val resType2 = tp2.resType.subst(tp2, tp1)
569
+ val resType = infoMeet(resType1, resType2, safeIntersection)
570
+ if resType eq resType1 then tp1
571
+ else if resType eq resType2 then tp2
572
+ else if ! resType.exists then NoType
573
+ else tp1.derivedLambdaType(mergeParamNames(tp1, tp2), tp1.paramInfos, resType)
588
574
case _ =>
589
575
NoType
590
- }
591
576
case tp1 : PolyType =>
592
- tp2 match {
593
- case tp2 : PolyType if ctx.typeComparer.matchingPolyParams(tp1, tp2) =>
594
- val resType = infoMeet(tp1.resType, tp2.resType.subst(tp2, tp1), safeIntersection)
595
- if resType.exists then
577
+ tp2 match
578
+ case tp2 : PolyType if sameLength(tp1.paramNames, tp2.paramNames) =>
579
+ val resType1 = tp1.resType
580
+ val resType2 = tp2.resType.subst(tp2, tp1)
581
+ val resType = infoMeet(resType1, resType2, safeIntersection)
582
+ if (resType eq resType1) && ctx.typeComparer.matchingPolyParams(tp1, tp2) then
583
+ tp1
584
+ else if (resType eq resType2) && ctx.typeComparer.matchingPolyParams(tp2, tp1) then
585
+ tp2
586
+ else if ! resType.exists then
587
+ NoType
588
+ else
596
589
tp1.derivedLambdaType(
597
590
mergeParamNames(tp1, tp2),
598
591
tp1.paramInfos.zipWithConserve(tp2.paramInfos)( _ & _ ),
599
592
resType)
600
- else
601
- NoType
602
593
case _ =>
603
594
NoType
604
- }
605
595
case ExprType (rtp1) =>
606
- tp2 match {
607
- case ExprType (rtp2) => ExprType (rtp1 & rtp2)
608
- case _ => infoMeet(rtp1, tp2, safeIntersection)
609
- }
610
- case _ =>
611
596
tp2 match
612
- case _ : MethodType | _ : PolyType =>
613
- NoType
597
+ case ExprType (rtp2) =>
598
+ val resType = rtp1 & rtp2
599
+ if resType eq rtp1 then tp1
600
+ else if resType eq rtp2 then tp2
601
+ else ExprType (resType)
614
602
case _ =>
615
- try tp1 & tp2.widenExpr
616
- catch
617
- case ex : Throwable =>
618
- println( i " error for meet: $tp1 &&& $tp2 , ${tp1.getClass} , ${tp2.getClass} " )
619
- throw ex
620
- }
603
+ infoMeet(rtp1, tp2, safeIntersection)
604
+ case _ =>
605
+ tp2 match
606
+ case _ : MethodType | _ : PolyType => NoType
607
+ case _ => tp1 & tp2.widenExpr
608
+ end infoMeet
621
609
622
610
/** A non-overloaded denotation */
623
611
abstract class SingleDenotation (symbol : Symbol , initInfo : Type ) extends Denotation (symbol, initInfo) {
0 commit comments