Skip to content

Commit a07dda6

Browse files
committed
Beta reduce #Apply applications over classes
Through substitutions we might end up with code like C[hk0 = T] # Apply where C is a non-lambda class. This case has to be handled specially. If we don't do that, we get a stackoverflow when compiling IndexedSeq.
1 parent aceb060 commit a07dda6

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,35 @@ object Types {
942942
NoType
943943
}
944944

945-
loop(this)
945+
/** Reduce C[hki = Argi] # Apply where C is a non-lambda class
946+
* to C[Argi], renaming references as necessary */
947+
def betaReduceCls(cls: Symbol, tp: Type): Type = tp.stripTypeVar match {
948+
case tp @ RefinedType(parent, rname) =>
949+
val parent1 = betaReduceCls(cls, parent)
950+
def paramName(hkArgName: TypeName): TypeName =
951+
cls.typeParams.apply(rname.hkArgIndex).name
952+
def mapArg(rt: RefinedType) = new TypeMap {
953+
def apply(t: Type): Type = t match {
954+
case TypeRef(RefinedThis(`tp`), name) if name.isHkArgName =>
955+
TypeRef(RefinedThis(rt), paramName(name))
956+
case _ =>
957+
mapOver(t)
958+
}
959+
}
960+
if (rname.isHkArgName)
961+
RefinedType(parent1, paramName(rname.asTypeName), mapArg(_)(tp.refinedInfo))
962+
else parent1
963+
case _ =>
964+
tp
965+
}
966+
967+
if (name == tpnme.hkApply) {
968+
val cref = underlyingClassRef(refinementOK = true)
969+
val cls = cref.typeSymbol
970+
if (cref.isEtaExpandable && !defn.isBottomClass(cls)) betaReduceCls(cls, this)
971+
else loop(this)
972+
}
973+
else loop(this)
946974
}
947975

948976
/** The type <this . name> , reduced if possible */

test/dotc/tests.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ class tests extends CompilerTest {
186186
.toList
187187

188188
@Test def compileStdLib = compileList("compileStdLib", stdlibFiles, "-migration" :: scala2mode)
189+
@Test def compileIndexedSeq = compileLine("./scala-scala/src/library/scala/collection/immutable/IndexedSeq.scala")
190+
189191
@Test def dotty = compileDir(dottyDir, ".", List("-deep", "-Ycheck-reentrant"))(allowDeepSubtypes) // note the -deep argument
190192

191193
@Test def dotc_ast = compileDir(dotcDir, "ast")

0 commit comments

Comments
 (0)