Skip to content

Commit 9643055

Browse files
authored
Merge pull request scala#8580 from joroKr21/divergent-implicits
Bug fixes in divergent implicits checker
2 parents be9e4d2 + 75d1360 commit 9643055

File tree

4 files changed

+54
-33
lines changed

4 files changed

+54
-33
lines changed

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

Lines changed: 34 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,27 +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) && (dtor1 =:= dted1 || complexity(dtor1) > complexity(dted1))
505+
506+
overlaps(dtor, dted) && {
507+
complexity(dtor) compareTo complexity(dted) match {
508+
case 0 => dtor =:= dted
509+
case cmp => cmp > 0
510+
}
511+
}
507512
}
508513

509514
private def core(tp: Type): Type = tp.dealiasWiden match {
510-
case RefinedType(parents, defs) => intersectionType(parents map core, tp.typeSymbol.owner)
511-
case AnnotatedType(annots, tp) => core(tp)
515+
case RefinedType(parents, _) => intersectionType(parents map core, tp.typeSymbol.owner)
516+
case AnnotatedType(_, tp) => core(tp)
512517
case ExistentialType(tparams, result) => core(result).subst(tparams, tparams map (t => core(t.info.upperBound)))
513518
case PolyType(tparams, result) => core(result).subst(tparams, tparams map (t => core(t.info.upperBound)))
514519
case TypeRef(pre, sym, args) =>
@@ -543,7 +548,8 @@ trait Implicits {
543548
case _ => loop(tl, hdSym(acc))
544549
}
545550
}
546-
loop(List(tp), Set())
551+
552+
loop(List(tp), Set.empty)
547553
}
548554

549555
/** The expected type with all undetermined type parameters replaced with wildcards. */
@@ -571,31 +577,27 @@ trait Implicits {
571577
// upon receiving `c.abort` the typechecker will decide that the corresponding implicit search has failed
572578
// which will fail the entire stack of implicit searches, producing a nice error message provided by the programmer
573579
val existsDominatedImplicit: Boolean =
574-
if(tree == EmptyTree) false
580+
if (tree == EmptyTree) false
575581
else {
576-
lazy val spt = stripped(core(pt))
577-
lazy val sptSyms = allSymbols(spt)
578-
// Are all the symbols of the stripped core of pt contained in the stripped core of tp?
579-
def coversPt(tp: Type): Boolean = {
580-
val stp = stripped(core(tp))
581-
(stp =:= spt) || (sptSyms == allSymbols(stp))
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)
582589
}
583590

584591
@tailrec
585-
def loop(ois: List[OpenImplicit], belowByName: Boolean): Boolean = {
586-
ois match {
587-
case Nil => false
588-
case (hd@OpenImplicit(info1, tp, tree1)) :: tl =>
589-
(if (!info1.sym.isMacro && tree1.symbol == tree.symbol) {
590-
if(belowByName && (tp =:= pt)) Some(false) // if there is a byname argument between tp and pt we can tie the knot
591-
else if (dominates(pt, tp) && coversPt(tp)) Some(true)
592-
else None
593-
} else None) match {
594-
case Some(res) => res
595-
case None => loop(tl, hd.isByName || belowByName)
596-
}
597-
}
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)
598599
}
600+
599601
loop(context.openImplicits, this.isByNamePt)
600602
}
601603

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
byname-implicits-16.scala:14: error: diverging implicit expansion for type Test.O[Test.Z]
2-
starting with method expande in object Expand
2+
starting with method mkN in object Test
33
implicitly[O[Z]]
44
^
55
1 error

test/files/pos/t10080.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class OC[T1: Ordering, T2: Ordering]() {
2+
val ordering = implicitly[Ordering[((Int, T1), T2)]]
3+
}

test/files/pos/t11768.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
object A {
2+
trait B[T]
3+
implicit def c[T <: Singleton]: B[T] = ???
4+
implicit def d[T1: B, T2: B]: B[Tuple2[T1, T2]] = ???
5+
implicit def e[T: B]: B[Option[T]] = ???
6+
implicit def f[C[_] <: Iterable[_], T](implicit r: B[T]): B[C[T]] = ???
7+
}
8+
9+
object G {
10+
class H[T: A.B, V: A.B](t: Option[(V, T)]){
11+
implicitly[A.B[Option[(V, T)]]]
12+
}
13+
def h[T: A.B, V: A.B](t: Option[(V, T)]){
14+
implicitly[A.B[Option[(V, T)]]]
15+
}
16+
}

0 commit comments

Comments
 (0)