Skip to content

Commit 75d1360

Browse files
committed
Simplify and micro-optimize divergent implicits checker
* Don't allocate `Option[Boolean]` in `existsDominatedImplicit` * Eliminate redundant calls to `stripped(core(tp))` in `dominates` and `coversPt` Also removed some unused pattern bindings in the area.
1 parent 98c16e8 commit 75d1360

File tree

1 file changed

+32
-32
lines changed

1 file changed

+32
-32
lines changed

src/compiler/scala/tools/nsc/typechecker/Implicits.scala

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -469,10 +469,9 @@ trait Implicits {
469469
def isPlausiblyCompatible(tp: Type, pt: Type) = checkCompatibility(fast = true, tp, pt)
470470
def normSubType(tp: Type, pt: Type) = checkCompatibility(fast = false, tp, pt)
471471

472-
/** Does type `dtor` dominate type `dted`?
473-
* This is the case if the stripped cores `dtor1` and `dted1` of both types are
474-
* the same wrt `=:=`, or if they overlap and the complexity of `dtor1` is higher
475-
* than the complexity of `dted1`.
472+
/** Does stripped core type `dtor` dominate the stripped core type `dted`?
473+
* This is the case if both types are the same wrt `=:=`, or if they overlap
474+
* and the complexity of `dtor` is higher than the complexity of `dted`.
476475
* The _stripped core_ of a type is the type where
477476
* - all refinements and annotations are dropped,
478477
* - all universal and existential quantification is eliminated
@@ -488,32 +487,33 @@ trait Implicits {
488487
case h :: t => sumComplexity(acc + complexity(h), t)
489488
case _: Nil.type => acc
490489
}
490+
491491
def complexity(tp: Type): Int = tp.dealias match {
492492
case NoPrefix => 0
493-
case SingleType(pre, sym) => if (sym.hasPackageFlag) 0 else complexity(tp.dealiasWiden)
493+
case SingleType(_, sym) => if (sym.hasPackageFlag) 0 else complexity(tp.dealiasWiden)
494494
case ThisType(sym) => if (sym.hasPackageFlag) 0 else 1
495-
case TypeRef(pre, sym, args) => 1 + complexity(pre) + sumComplexity(0, args)
495+
case TypeRef(pre, _, args) => 1 + complexity(pre) + sumComplexity(0, args)
496496
case RefinedType(parents, _) => 1 + sumComplexity(0, parents)
497497
case _ => 1
498498
}
499+
499500
def overlaps(tp1: Type, tp2: Type): Boolean = (tp1, tp2) match {
500501
case (RefinedType(parents, _), _) => parents exists (overlaps(_, tp2))
501502
case (_, RefinedType(parents, _)) => parents exists (overlaps(tp1, _))
502503
case _ => tp1.typeSymbol == tp2.typeSymbol
503504
}
504-
val dtor1 = stripped(core(dtor))
505-
val dted1 = stripped(core(dted))
506-
overlaps(dtor1, dted1) && {
507-
complexity(dtor1) compareTo complexity(dted1) match {
508-
case 0 => dtor1 =:= dted1
505+
506+
overlaps(dtor, dted) && {
507+
complexity(dtor) compareTo complexity(dted) match {
508+
case 0 => dtor =:= dted
509509
case cmp => cmp > 0
510510
}
511511
}
512512
}
513513

514514
private def core(tp: Type): Type = tp.dealiasWiden match {
515-
case RefinedType(parents, defs) => intersectionType(parents map core, tp.typeSymbol.owner)
516-
case AnnotatedType(annots, tp) => core(tp)
515+
case RefinedType(parents, _) => intersectionType(parents map core, tp.typeSymbol.owner)
516+
case AnnotatedType(_, tp) => core(tp)
517517
case ExistentialType(tparams, result) => core(result).subst(tparams, tparams map (t => core(t.info.upperBound)))
518518
case PolyType(tparams, result) => core(result).subst(tparams, tparams map (t => core(t.info.upperBound)))
519519
case TypeRef(pre, sym, args) =>
@@ -548,7 +548,8 @@ trait Implicits {
548548
case _ => loop(tl, hdSym(acc))
549549
}
550550
}
551-
loop(List(tp), Set())
551+
552+
loop(List(tp), Set.empty)
552553
}
553554

554555
/** The expected type with all undetermined type parameters replaced with wildcards. */
@@ -576,28 +577,27 @@ trait Implicits {
576577
// upon receiving `c.abort` the typechecker will decide that the corresponding implicit search has failed
577578
// which will fail the entire stack of implicit searches, producing a nice error message provided by the programmer
578579
val existsDominatedImplicit: Boolean =
579-
if(tree == EmptyTree) false
580+
if (tree == EmptyTree) false
580581
else {
581-
lazy val spt = stripped(core(pt))
582-
lazy val sptSyms = allSymbols(spt)
583-
// Are all the symbols of the stripped core of pt contained in the stripped core of tp?
584-
def coversPt(tp: Type): Boolean = sptSyms == allSymbols(stripped(core(tp)))
582+
lazy val ptStripped = stripped(core(pt))
583+
lazy val ptStrippedSyms = allSymbols(ptStripped)
584+
585+
// Are all the symbols of the stripped core of dominating pt contained in the stripped core of tp?
586+
def coversDominatingPt(tp: Type): Boolean = {
587+
val tpStripped = stripped(core(tp))
588+
dominates(ptStripped, tpStripped) && ptStrippedSyms == allSymbols(tpStripped)
589+
}
585590

586591
@tailrec
587-
def loop(ois: List[OpenImplicit], belowByName: Boolean): Boolean = {
588-
ois match {
589-
case Nil => false
590-
case (hd@OpenImplicit(info1, tp, tree1)) :: tl =>
591-
(if (!info1.sym.isMacro && tree1.symbol == tree.symbol) {
592-
if(belowByName && (tp =:= pt)) Some(false) // if there is a byname argument between tp and pt we can tie the knot
593-
else if (dominates(pt, tp) && coversPt(tp)) Some(true)
594-
else None
595-
} else None) match {
596-
case Some(res) => res
597-
case None => loop(tl, hd.isByName || belowByName)
598-
}
599-
}
592+
def loop(ois: List[OpenImplicit], belowByName: Boolean): Boolean = ois match {
593+
case Nil => false
594+
case (hd @ OpenImplicit(info1, tp, tree1)) :: tl =>
595+
val possiblyDominated = !info1.sym.isMacro && tree1.symbol == tree.symbol
596+
if (possiblyDominated && belowByName && tp =:= pt) false
597+
else if (possiblyDominated && coversDominatingPt(tp)) true
598+
else loop(tl, hd.isByName || belowByName)
600599
}
600+
601601
loop(context.openImplicits, this.isByNamePt)
602602
}
603603

0 commit comments

Comments
 (0)