Skip to content

Commit ef438e8

Browse files
authored
Merge pull request #6329 from milessabin/topic/i6300
Fix inductive implicits performance regression
2 parents 6f89125 + d4c80fa commit ef438e8

File tree

4 files changed

+53
-26
lines changed

4 files changed

+53
-26
lines changed

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

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4966,34 +4966,51 @@ object Types {
49664966
}
49674967

49684968
class TypeSizeAccumulator(implicit ctx: Context) extends TypeAccumulator[Int] {
4969-
def apply(n: Int, tp: Type): Int = tp match {
4970-
case tp: AppliedType =>
4971-
foldOver(n + 1, tp)
4972-
case tp: RefinedType =>
4973-
foldOver(n + 1, tp)
4974-
case tp: TypeRef if tp.info.isTypeAlias =>
4975-
apply(n, tp.superType)
4976-
case _ =>
4977-
foldOver(n, tp)
4969+
val seen = new java.util.IdentityHashMap[Type, Type]
4970+
def apply(n: Int, tp: Type): Int =
4971+
if (seen.get(tp) != null) n
4972+
else {
4973+
seen.put(tp, tp)
4974+
tp match {
4975+
case tp: AppliedType =>
4976+
foldOver(n + 1, tp)
4977+
case tp: RefinedType =>
4978+
foldOver(n + 1, tp)
4979+
case tp: TypeRef if tp.info.isTypeAlias =>
4980+
apply(n, tp.superType)
4981+
case tp: TypeParamRef =>
4982+
apply(n, ctx.typeComparer.bounds(tp))
4983+
case _ =>
4984+
foldOver(n, tp)
4985+
}
49784986
}
49794987
}
49804988

49814989
class CoveringSetAccumulator(implicit ctx: Context) extends TypeAccumulator[Set[Symbol]] {
4990+
val seen = new java.util.IdentityHashMap[Type, Type]
49824991
def apply(cs: Set[Symbol], tp: Type): Set[Symbol] = {
4983-
val sym = tp.typeSymbol
4984-
tp match {
4985-
case tp if tp.isTopType || tp.isBottomType =>
4986-
cs
4987-
case tp: AppliedType =>
4988-
foldOver(cs + sym, tp)
4989-
case tp: RefinedType =>
4990-
foldOver(cs + sym, tp)
4991-
case tp: TypeRef if tp.info.isTypeAlias =>
4992-
apply(cs, tp.superType)
4993-
case tp: TypeBounds =>
4994-
foldOver(cs, tp)
4995-
case other =>
4996-
foldOver(cs + sym, tp)
4992+
if (seen.get(tp) != null) cs
4993+
else {
4994+
seen.put(tp, tp)
4995+
tp match {
4996+
case tp if tp.isTopType || tp.isBottomType =>
4997+
cs
4998+
case tp: AppliedType =>
4999+
foldOver(cs + tp.typeSymbol, tp)
5000+
case tp: RefinedType =>
5001+
foldOver(cs + tp.typeSymbol, tp)
5002+
case tp: TypeRef if tp.info.isTypeAlias =>
5003+
apply(cs, tp.superType)
5004+
case tp: TypeRef if tp.typeSymbol.isClass =>
5005+
foldOver(cs + tp.typeSymbol, tp)
5006+
case tp: TermRef =>
5007+
val tsym = if (tp.termSymbol.is(Param)) tp.underlying.typeSymbol else tp.termSymbol
5008+
foldOver(cs + tsym, tp)
5009+
case tp: TypeParamRef =>
5010+
apply(cs, ctx.typeComparer.bounds(tp))
5011+
case other =>
5012+
foldOver(cs, tp)
5013+
}
49975014
}
49985015
}
49995016
}

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,9 +1413,10 @@ abstract class SearchHistory { outer =>
14131413
if (cand1.ref == cand.ref) {
14141414
val wideTp = tp.widenExpr
14151415
lazy val wildTp = wildApprox(wideTp)
1416+
lazy val tpSize = wideTp.typeSize
14161417
if (belowByname && (wildTp <:< wildPt)) false
1417-
else if ((wideTp.typeSize < ptSize && wideTp.coveringSet == ptCoveringSet) || (wildTp =:= wildPt)) true
1418-
else loop(tl, isByname(tp) || belowByname)
1418+
else if (tpSize > ptSize || wideTp.coveringSet != ptCoveringSet) loop(tl, isByname(tp) || belowByname)
1419+
else tpSize < ptSize || wildTp =:= wildPt || loop(tl, isByname(tp) || belowByname)
14191420
}
14201421
else loop(tl, isByname(tp) || belowByname)
14211422
}

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ class CompilationTests extends ParallelTesting {
171171
compileList("duplicate source", List(
172172
"tests/neg-custom-args/toplevel-samesource/S.scala",
173173
"tests/neg-custom-args/toplevel-samesource/nested/S.scala"),
174-
defaultOptions)
174+
defaultOptions) +
175+
compileFile("tests/neg-custom-args/i6300.scala", allowDeepSubtypes)
175176
}.checkExpectedErrors()
176177

177178
@Test def fuzzyAll: Unit = {

tests/neg-custom-args/i6300.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
object Test {
2+
class Foo[T <: Foo[T]]
3+
class Bar extends Foo[Bar]
4+
5+
implicit def i[T <: Foo[T]](implicit t: Foo[Foo[T]]): Foo[T] = ???
6+
7+
implicitly[Foo[Bar]] // error
8+
}

0 commit comments

Comments
 (0)