Skip to content

Commit 4b220cc

Browse files
oderskysmarter
authored andcommitted
Compute type params in namer without completing the whole info
Type params should be computed before computing the whole info of a type. Without the patch we get a cyclic reference in the compileMixed test. Note that compileIndexedSeq does not pass with this commit (it passed before), this is fixed in the next commit.
1 parent 29468d6 commit 4b220cc

File tree

6 files changed

+64
-15
lines changed

6 files changed

+64
-15
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,6 +1802,14 @@ object SymDenotations {
18021802
def withModuleClass(moduleClassFn: Context => Symbol): this.type = { myModuleClassFn = moduleClassFn; this }
18031803
}
18041804

1805+
/** A subclass of LazyTypes where type parameters can be completed independently of
1806+
* the info.
1807+
*/
1808+
abstract class TypeParamsCompleter extends LazyType {
1809+
/** The type parameters computed by the completer before completion has finished */
1810+
def completerTypeParams(sym: Symbol): List[TypeSymbol]
1811+
}
1812+
18051813
val NoSymbolFn = (ctx: Context) => NoSymbol
18061814

18071815
/** A missing completer */

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

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package core
44
import Types._
55
import Contexts._
66
import Symbols._
7+
import SymDenotations.TypeParamsCompleter
78
import Decorators._
89
import util.Stats._
910
import util.common._
@@ -240,15 +241,21 @@ class TypeApplications(val self: Type) extends AnyVal {
240241
case self: TypeRef =>
241242
val tsym = self.symbol
242243
if (tsym.isClass) tsym.typeParams
243-
else if (tsym.isAliasType) self.underlying.typeParams
244-
else if (tsym.isCompleting)
245-
// We are facing a problem when computing the type parameters of an uncompleted
246-
// abstract type. We can't access the bounds of the symbol yet because that
247-
// would cause a cause a cyclic reference. So we return `Nil` instead
248-
// and try to make up for it later. The acrobatics in Scala2Unpicker#readType
249-
// for reading a TypeRef show what's neeed.
250-
Nil
251-
else tsym.info.typeParams
244+
else tsym.infoOrCompleter match {
245+
case completer: TypeParamsCompleter =>
246+
val tparams = completer.completerTypeParams(tsym)
247+
if (tsym.isClass) tparams
248+
else defn.LambdaTrait(tparams.map(_.variance)).typeParams
249+
case _ =>
250+
if (!tsym.isCompleting || tsym.isAliasType) tsym.info.typeParams
251+
else
252+
// We are facing a problem when computing the type parameters of an uncompleted
253+
// abstract type. We can't access the bounds of the symbol yet because that
254+
// would cause a cause a cyclic reference. So we return `Nil` instead
255+
// and try to make up for it later. The acrobatics in Scala2Unpicker#readType
256+
// for reading a TypeRef show what's needed.
257+
Nil
258+
}
252259
case self: RefinedType =>
253260
// inlined and optimized version of
254261
// val sym = self.LambdaTrait

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
3535
* Instead we produce an annotated type that marks the prefix as unsafe:
3636
*
3737
* (x: (C @ UnsafeNonvariant)#T)C#T
38-
38+
3939
* We also set a global state flag `unsafeNonvariant` to the current run.
4040
* When typing a Select node, typer will check that flag, and if it
4141
* points to the current run will scan the result type of the select for

src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -478,10 +478,31 @@ class Namer { typer: Typer =>
478478
}
479479

480480
/** The completer of a symbol defined by a member def or import (except ClassSymbols) */
481-
class Completer(val original: Tree)(implicit ctx: Context) extends LazyType {
481+
class Completer(val original: Tree)(implicit ctx: Context) extends TypeParamsCompleter {
482482

483483
protected def localContext(owner: Symbol) = ctx.fresh.setOwner(owner).setTree(original)
484484

485+
private var myTypeParams: List[TypeSymbol] = null
486+
private var nestedCtx: Context = null
487+
488+
def completerTypeParams(sym: Symbol): List[TypeSymbol] = {
489+
if (myTypeParams == null) {
490+
//println(i"completing type params of $sym in ${sym.owner}")
491+
myTypeParams = original match {
492+
case tdef: TypeDef =>
493+
nestedCtx = localContext(sym).setNewScope
494+
locally {
495+
implicit val ctx: Context = nestedCtx
496+
completeParams(tdef.tparams)
497+
tdef.tparams.map(symbolOfTree(_).asType)
498+
}
499+
case _ =>
500+
Nil
501+
}
502+
}
503+
myTypeParams
504+
}
505+
485506
private def typeSig(sym: Symbol): Type = original match {
486507
case original: ValDef =>
487508
if (sym is Module) moduleValSig(sym)
@@ -492,7 +513,7 @@ class Namer { typer: Typer =>
492513
typer1.defDefSig(original, sym)(localContext(sym).setTyper(typer1))
493514
case original: TypeDef =>
494515
assert(!original.isClassDef)
495-
typeDefSig(original, sym)(localContext(sym).setNewScope)
516+
typeDefSig(original, sym, completerTypeParams(sym))(nestedCtx)
496517
case imp: Import =>
497518
try {
498519
val expr1 = typedAheadExpr(imp.expr, AnySelectionProto)
@@ -840,9 +861,7 @@ class Namer { typer: Typer =>
840861
else valOrDefDefSig(ddef, sym, typeParams, paramSymss, wrapMethType)
841862
}
842863

843-
def typeDefSig(tdef: TypeDef, sym: Symbol)(implicit ctx: Context): Type = {
844-
completeParams(tdef.tparams)
845-
val tparamSyms = tdef.tparams map symbolOfTree
864+
def typeDefSig(tdef: TypeDef, sym: Symbol, tparamSyms: List[TypeSymbol])(implicit ctx: Context): Type = {
846865
val isDerived = tdef.rhs.isInstanceOf[untpd.DerivedTypeTree]
847866
//val toParameterize = tparamSyms.nonEmpty && !isDerived
848867
//val needsLambda = sym.allOverriddenSymbols.exists(_ is HigherKinded) && !isDerived

test/dotc/tests.scala

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

188188
@Test def compileStdLib = compileList("compileStdLib", stdlibFiles, "-migration" :: scala2mode)
189+
@Test def compileMixed = compileLine(
190+
"""tests/pos/B.scala
191+
|./scala-scala/src/library/scala/collection/immutable/Seq.scala
192+
|./scala-scala/src/library/scala/package.scala
193+
|./scala-scala/src/library/scala/collection/GenSeqLike.scala
194+
|./scala-scala/src/library/scala/collection/SeqLike.scala
195+
|./scala-scala/src/library/scala/collection/generic/GenSeqFactory.scala""".stripMargin)
196+
// @Test def compileIndexedSeq = compileLine("./scala-scala/src/library/scala/collection/immutable/IndexedSeq.scala")
197+
189198
@Test def dotty = compileDir(dottyDir, ".", List("-deep", "-Ycheck-reentrant"))(allowDeepSubtypes) // note the -deep argument
190199

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

tests/pos/B.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
object B{
2+
def main(args: Array[String]): Unit = {
3+
val s = List(1,2,3)
4+
()
5+
}
6+
}

0 commit comments

Comments
 (0)