@@ -529,74 +529,79 @@ object TypeOps:
529
529
val skolemizedArgTypes = skolemizeWildcardArgs(argTypes, app)
530
530
val violations = new mutable.ListBuffer [BoundsViolation ]
531
531
532
- for ((arg, bounds) <- args zip boundss) {
533
- def checkOverlapsBounds (lo : Type , hi : Type ): Unit = {
534
- // println(i" = ${instantiate(bounds.hi, argTypes)}")
535
-
536
- var checkCtx = ctx // the context to be used for bounds checking
537
- if (argTypes ne skolemizedArgTypes) { // some of the arguments are wildcards
538
-
539
- /** Is there a `LazyRef(TypeRef(_, sym))` reference in `tp`? */
540
- def isLazyIn (sym : Symbol , tp : Type ): Boolean = {
541
- def isReference (tp : Type ) = tp match {
542
- case tp : LazyRef => tp.ref.isInstanceOf [TypeRef ] && tp.ref.typeSymbol == sym
543
- case _ => false
544
- }
545
- tp.existsPart(isReference, forceLazy = false )
546
- }
532
+ def checkOverlapsBounds (lo : Type , hi : Type , arg : Tree , bounds : TypeBounds ): Unit = {
533
+ // println(i" = ${instantiate(bounds.hi, argTypes)}")
547
534
548
- /** The argument types of the form `TypeRef(_, sym)` which appear as a LazyRef in `bounds`.
549
- * This indicates that the application is used as an F-bound for the symbol referred to in the LazyRef.
550
- */
551
- val lazyRefs = skolemizedArgTypes collect {
552
- case tp : TypeRef if isLazyIn(tp.symbol, bounds) => tp.symbol
553
- }
535
+ var checkCtx = ctx // the context to be used for bounds checking
536
+ if (argTypes ne skolemizedArgTypes) { // some of the arguments are wildcards
554
537
555
- for (sym <- lazyRefs) {
556
-
557
- // If symbol `S` has an F-bound such as `C[?, S]` that contains wildcards,
558
- // add a modifieed bound where wildcards are skolemized as a GADT bound for `S`.
559
- // E.g. for `C[?, S]` we would add `C[C[?, S]#T0, S]` where `T0` is the first
560
- // type parameter of `C`. The new bound is added as a GADT bound for `S` in
561
- // `checkCtx`.
562
- // This mirrors what we do for the bounds that are checked and allows us thus
563
- // to bounds-check F-bounds with wildcards. A test case is pos/i6146.scala.
564
-
565
- def massage (tp : Type ): Type = tp match {
566
- case tp @ AppliedType (tycon, args) =>
567
- tp.derivedAppliedType(tycon, skolemizeWildcardArgs(args, tp))
568
- case tp : AndOrType =>
569
- tp.derivedAndOrType(massage(tp.tp1), massage(tp.tp2))
570
- case _ => tp
571
- }
572
- def narrowBound (bound : Type , fromBelow : Boolean ): Unit = {
573
- val bound1 = massage(bound)
574
- if (bound1 ne bound) {
575
- if (checkCtx eq ctx) checkCtx = ctx.fresh.setFreshGADTBounds
576
- if (! checkCtx.gadt.contains(sym)) checkCtx.gadt.addToConstraint(sym)
577
- checkCtx.gadt.addBound(sym, bound1, fromBelow)
578
- typr.println(" install GADT bound $bound1 for when checking F-bounded $sym" )
579
- }
580
- }
581
- narrowBound(sym.info.loBound, fromBelow = true )
582
- narrowBound(sym.info.hiBound, fromBelow = false )
538
+ /** Is there a `LazyRef(TypeRef(_, sym))` reference in `tp`? */
539
+ def isLazyIn (sym : Symbol , tp : Type ): Boolean = {
540
+ def isReference (tp : Type ) = tp match {
541
+ case tp : LazyRef => tp.ref.isInstanceOf [TypeRef ] && tp.ref.typeSymbol == sym
542
+ case _ => false
583
543
}
544
+ tp.existsPart(isReference, forceLazy = false )
584
545
}
585
546
586
- val hiBound = instantiate(bounds.hi, skolemizedArgTypes)
587
- val loBound = instantiate(bounds.lo, skolemizedArgTypes)
547
+ /** The argument types of the form `TypeRef(_, sym)` which appear as a LazyRef in `bounds`.
548
+ * This indicates that the application is used as an F-bound for the symbol referred to in the LazyRef.
549
+ */
550
+ val lazyRefs = skolemizedArgTypes collect {
551
+ case tp : TypeRef if isLazyIn(tp.symbol, bounds) => tp.symbol
552
+ }
588
553
589
- def check (using Context ) = {
590
- if (! (lo <:< hiBound)) violations += ((arg, " upper" , hiBound))
591
- if (! (loBound <:< hi)) violations += ((arg, " lower" , loBound))
554
+ for (sym <- lazyRefs) {
555
+
556
+ // If symbol `S` has an F-bound such as `C[?, S]` that contains wildcards,
557
+ // add a modifieed bound where wildcards are skolemized as a GADT bound for `S`.
558
+ // E.g. for `C[?, S]` we would add `C[C[?, S]#T0, S]` where `T0` is the first
559
+ // type parameter of `C`. The new bound is added as a GADT bound for `S` in
560
+ // `checkCtx`.
561
+ // This mirrors what we do for the bounds that are checked and allows us thus
562
+ // to bounds-check F-bounds with wildcards. A test case is pos/i6146.scala.
563
+
564
+ def massage (tp : Type ): Type = tp match {
565
+ case tp @ AppliedType (tycon, args) =>
566
+ tp.derivedAppliedType(tycon, skolemizeWildcardArgs(args, tp))
567
+ case tp : AndOrType =>
568
+ tp.derivedAndOrType(massage(tp.tp1), massage(tp.tp2))
569
+ case _ => tp
570
+ }
571
+ def narrowBound (bound : Type , fromBelow : Boolean ): Unit = {
572
+ val bound1 = massage(bound)
573
+ if (bound1 ne bound) {
574
+ if (checkCtx eq ctx) checkCtx = ctx.fresh.setFreshGADTBounds
575
+ if (! checkCtx.gadt.contains(sym)) checkCtx.gadt.addToConstraint(sym)
576
+ checkCtx.gadt.addBound(sym, bound1, fromBelow)
577
+ typr.println(" install GADT bound $bound1 for when checking F-bounded $sym" )
578
+ }
579
+ }
580
+ narrowBound(sym.info.loBound, fromBelow = true )
581
+ narrowBound(sym.info.hiBound, fromBelow = false )
592
582
}
593
- check(using checkCtx)
594
583
}
595
- arg.tpe match {
596
- case TypeBounds (lo, hi) => checkOverlapsBounds(lo, hi)
597
- case tp => checkOverlapsBounds(tp, tp)
584
+ val hiBound = instantiate(bounds.hi, skolemizedArgTypes)
585
+ val loBound = instantiate(bounds.lo, skolemizedArgTypes)
586
+
587
+ def check (using Context ) = {
588
+ if (! (lo <:< hiBound)) violations += ((arg, " upper" , hiBound))
589
+ if (! (loBound <:< hi)) violations += ((arg, " lower" , loBound))
598
590
}
591
+ check(using checkCtx)
599
592
}
593
+
594
+ def loop (args : List [Tree ], boundss : List [TypeBounds ]): Unit = args match
595
+ case arg :: args1 => boundss match
596
+ case bounds :: boundss1 =>
597
+ arg.tpe match
598
+ case TypeBounds (lo, hi) => checkOverlapsBounds(lo, hi, arg, bounds)
599
+ case tp => checkOverlapsBounds(tp, tp, arg, bounds)
600
+ loop(args1, boundss1)
601
+ case _ =>
602
+ case _ =>
603
+
604
+ loop(args, boundss)
600
605
violations.toList
601
606
}
602
607
0 commit comments