Skip to content

Partially fix #1500: Implicit search breaks at a certain depth #1504

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 14, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -801,14 +801,15 @@ class SearchHistory(val searchDepth: Int, val seen: Map[ClassSymbol, Int]) {
def updateMap(csyms: List[ClassSymbol], seen: Map[ClassSymbol, Int]): SearchHistory = csyms match {
case csym :: csyms1 =>
seen get csym match {
// proto complexity is >= than the last time it was seen → diverge
case Some(prevSize) if size >= prevSize => this
case _ => updateMap(csyms1, seen.updated(csym, size))
}
case nil =>
if (csyms.isEmpty) this
else new SearchHistory(searchDepth + 1, seen)
case _ =>
new SearchHistory(searchDepth + 1, seen)
}
updateMap(proto.classSymbols, seen)
if (proto.classSymbols.isEmpty) this
else updateMap(proto.classSymbols, seen)
}
}
}
Expand Down
28 changes: 28 additions & 0 deletions tests/pos/t1500a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
trait Step0
trait Step1
trait Step2
trait Step3
trait Step4
trait Step5
trait Step6

object Steps {
implicit val Step0: Step0 = new Step0 {}
implicit def Step1(implicit p: Step0): Step1 = new Step1 {}
implicit def Step2(implicit p: Step1): Step2 = new Step2 {}
implicit def Step3(implicit p: Step2): Step3 = new Step3 {}
implicit def Step4(implicit p: Step3): Step4 = new Step4 {}
implicit def Step5(implicit p: Step4): Step5 = new Step5 {}
implicit def Step6(implicit p: Step5): Step6 = new Step6 {}
}

object StepsTest {
import Steps._

implicitly[Step0]
implicitly[Step1]
implicitly[Step2]
implicitly[Step3]
implicitly[Step4]
implicitly[Step6]
}
21 changes: 21 additions & 0 deletions tests/run/t1500b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
sealed trait Nat
sealed trait Succ[Prev <: Nat] extends Nat
sealed trait Zero extends Nat

case class ToInt[N <: Nat](value: Int)

object ToInt {
implicit val caseZero: ToInt[Zero] = ToInt(0)
implicit def caseSucc[Prev <: Nat](implicit e: ToInt[Prev]): ToInt[Succ[Prev]] = ToInt(e.value + 1)
}

object Test {
def main(args: Array[String]): Unit = {
assert(implicitly[ToInt[Zero]].value == 0)
assert(implicitly[ToInt[Succ[Zero]]].value == 1)
assert(implicitly[ToInt[Succ[Succ[Zero]]]].value == 2)
assert(implicitly[ToInt[Succ[Succ[Succ[Zero]]]]].value == 3)
assert(implicitly[ToInt[Succ[Succ[Succ[Succ[Zero]]]]]].value == 4)
assert(implicitly[ToInt[Succ[Succ[Succ[Succ[Succ[Zero]]]]]]].value == 5)
}
}
19 changes: 19 additions & 0 deletions tests/run/t1500c.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
sealed trait HList
sealed trait HNil extends HList
sealed trait ::[H, T <: HList] extends HList

case class Size[L <: HList](value: Int)

object Size {
implicit val caseHNil: Size[HNil] = Size(0)
implicit def caseHCons[H, T <: HList](implicit e: Size[T]): Size[H :: T] = Size(e.value + 1)
}

object Test {
def main(args: Array[String]): Unit = {
assert(implicitly[Size[HNil]].value == 0)
assert(implicitly[Size[Int :: HNil]].value == 1)
assert(implicitly[Size[Int :: Int :: HNil]].value == 2)
assert(implicitly[Size[Int :: Int :: Int :: HNil]].value == 3)
}
}