aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-01-15 17:39:15 +0100
committerGuillaume Martres <smarter@ubuntu.com>2016-01-16 21:26:57 +0100
commit9a378b10a706f283a7337a1debe02e586d08c5ed (patch)
treeace7c1e83e7f994a9f820131216b5eec448f5788 /src/dotty/tools
parent8e84133598f879c1cb0ad4b9faf2a90c0403536f (diff)
downloaddotty-9a378b10a706f283a7337a1debe02e586d08c5ed.tar.gz
dotty-9a378b10a706f283a7337a1debe02e586d08c5ed.tar.bz2
dotty-9a378b10a706f283a7337a1debe02e586d08c5ed.zip
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.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala8
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala25
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala29
4 files changed, 49 insertions, 15 deletions
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 8016c57f3..d384bd5c4 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -1802,6 +1802,14 @@ object SymDenotations {
def withModuleClass(moduleClassFn: Context => Symbol): this.type = { myModuleClassFn = moduleClassFn; this }
}
+ /** A subclass of LazyTypes where type parameters can be completed independently of
+ * the info.
+ */
+ abstract class TypeParamsCompleter extends LazyType {
+ /** The type parameters computed by the completer before completion has finished */
+ def completerTypeParams(sym: Symbol): List[TypeSymbol]
+ }
+
val NoSymbolFn = (ctx: Context) => NoSymbol
/** A missing completer */
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index aab327ce9..e09328205 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -4,6 +4,7 @@ package core
import Types._
import Contexts._
import Symbols._
+import SymDenotations.TypeParamsCompleter
import Decorators._
import util.Stats._
import util.common._
@@ -240,15 +241,21 @@ class TypeApplications(val self: Type) extends AnyVal {
case self: TypeRef =>
val tsym = self.symbol
if (tsym.isClass) tsym.typeParams
- else if (tsym.isAliasType) self.underlying.typeParams
- else if (tsym.isCompleting)
- // We are facing a problem when computing the type parameters of an uncompleted
- // abstract type. We can't access the bounds of the symbol yet because that
- // would cause a cause a cyclic reference. So we return `Nil` instead
- // and try to make up for it later. The acrobatics in Scala2Unpicker#readType
- // for reading a TypeRef show what's neeed.
- Nil
- else tsym.info.typeParams
+ else tsym.infoOrCompleter match {
+ case completer: TypeParamsCompleter =>
+ val tparams = completer.completerTypeParams(tsym)
+ if (tsym.isClass) tparams
+ else defn.LambdaTrait(tparams.map(_.variance)).typeParams
+ case _ =>
+ if (!tsym.isCompleting || tsym.isAliasType) tsym.info.typeParams
+ else
+ // We are facing a problem when computing the type parameters of an uncompleted
+ // abstract type. We can't access the bounds of the symbol yet because that
+ // would cause a cause a cyclic reference. So we return `Nil` instead
+ // and try to make up for it later. The acrobatics in Scala2Unpicker#readType
+ // for reading a TypeRef show what's needed.
+ Nil
+ }
case self: RefinedType =>
// inlined and optimized version of
// val sym = self.LambdaTrait
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index 04cd2249d..6896468ba 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -35,7 +35,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
* Instead we produce an annotated type that marks the prefix as unsafe:
*
* (x: (C @ UnsafeNonvariant)#T)C#T
-
+
* We also set a global state flag `unsafeNonvariant` to the current run.
* When typing a Select node, typer will check that flag, and if it
* points to the current run will scan the result type of the select for
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index b24916be8..406e7378f 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -478,10 +478,31 @@ class Namer { typer: Typer =>
}
/** The completer of a symbol defined by a member def or import (except ClassSymbols) */
- class Completer(val original: Tree)(implicit ctx: Context) extends LazyType {
+ class Completer(val original: Tree)(implicit ctx: Context) extends TypeParamsCompleter {
protected def localContext(owner: Symbol) = ctx.fresh.setOwner(owner).setTree(original)
+ private var myTypeParams: List[TypeSymbol] = null
+ private var nestedCtx: Context = null
+
+ def completerTypeParams(sym: Symbol): List[TypeSymbol] = {
+ if (myTypeParams == null) {
+ //println(i"completing type params of $sym in ${sym.owner}")
+ myTypeParams = original match {
+ case tdef: TypeDef =>
+ nestedCtx = localContext(sym).setNewScope
+ locally {
+ implicit val ctx: Context = nestedCtx
+ completeParams(tdef.tparams)
+ tdef.tparams.map(symbolOfTree(_).asType)
+ }
+ case _ =>
+ Nil
+ }
+ }
+ myTypeParams
+ }
+
private def typeSig(sym: Symbol): Type = original match {
case original: ValDef =>
if (sym is Module) moduleValSig(sym)
@@ -492,7 +513,7 @@ class Namer { typer: Typer =>
typer1.defDefSig(original, sym)(localContext(sym).setTyper(typer1))
case original: TypeDef =>
assert(!original.isClassDef)
- typeDefSig(original, sym)(localContext(sym).setNewScope)
+ typeDefSig(original, sym, completerTypeParams(sym))(nestedCtx)
case imp: Import =>
try {
val expr1 = typedAheadExpr(imp.expr, AnySelectionProto)
@@ -840,9 +861,7 @@ class Namer { typer: Typer =>
else valOrDefDefSig(ddef, sym, typeParams, paramSymss, wrapMethType)
}
- def typeDefSig(tdef: TypeDef, sym: Symbol)(implicit ctx: Context): Type = {
- completeParams(tdef.tparams)
- val tparamSyms = tdef.tparams map symbolOfTree
+ def typeDefSig(tdef: TypeDef, sym: Symbol, tparamSyms: List[TypeSymbol])(implicit ctx: Context): Type = {
val isDerived = tdef.rhs.isInstanceOf[untpd.DerivedTypeTree]
//val toParameterize = tparamSyms.nonEmpty && !isDerived
//val needsLambda = sym.allOverriddenSymbols.exists(_ is HigherKinded) && !isDerived