Skip to content

Commit 8abe9da

Browse files
committed
Avoid zip in boundsViolations
1 parent 212b8af commit 8abe9da

File tree

1 file changed

+63
-58
lines changed

1 file changed

+63
-58
lines changed

compiler/src/dotty/tools/dotc/core/TypeOps.scala

Lines changed: 63 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -529,74 +529,79 @@ object TypeOps:
529529
val skolemizedArgTypes = skolemizeWildcardArgs(argTypes, app)
530530
val violations = new mutable.ListBuffer[BoundsViolation]
531531

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)}")
547534

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
554537

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
583543
}
544+
tp.existsPart(isReference, forceLazy = false)
584545
}
585546

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+
}
588553

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)
592582
}
593-
check(using checkCtx)
594583
}
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))
598590
}
591+
check(using checkCtx)
599592
}
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)
600605
violations.toList
601606
}
602607

0 commit comments

Comments
 (0)