aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala36
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala9
-rw-r--r--src/dotty/tools/dotc/core/Types.scala8
-rw-r--r--src/dotty/tools/dotc/core/classfile/ClassfileParser.scala4
-rw-r--r--src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala48
5 files changed, 69 insertions, 36 deletions
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 46d93b753..54884a24c 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -1213,15 +1213,25 @@ object SymDenotations {
private[this] var myNamedTypeParams: Set[TypeSymbol] = _
+ /** The type parameters in this class, in the order they appear in the current
+ * scope `decls`. This is might be temporarily the incorrect order when
+ * reading Scala2 pickled info. The problem is fixed by `updateTypeParams`
+ * which is called once an unpickled symbol has been completed.
+ */
+ private def typeParamsFromDecls(implicit ctx: Context) =
+ unforcedDecls.filter(sym =>
+ (sym is TypeParam) && sym.owner == symbol).asInstanceOf[List[TypeSymbol]]
+
/** The type parameters of this class */
override final def typeParams(implicit ctx: Context): List[TypeSymbol] = {
- def computeTypeParams = {
- if (ctx.erasedTypes || is(Module)) Nil // fast return for modules to avoid scanning package decls
- else if (this ne initial) initial.asSymDenotation.typeParams
- else unforcedDecls.filter(sym =>
- (sym is TypeParam) && sym.owner == symbol).asInstanceOf[List[TypeSymbol]]
- }
- if (myTypeParams == null) myTypeParams = computeTypeParams
+ if (myTypeParams == null)
+ myTypeParams =
+ if (ctx.erasedTypes || is(Module)) Nil // fast return for modules to avoid scanning package decls
+ else if (this ne initial) initial.asSymDenotation.typeParams
+ else infoOrCompleter match {
+ case info: TypeParamsCompleter => info.completerTypeParams(symbol)
+ case _ => typeParamsFromDecls
+ }
myTypeParams
}
@@ -1537,16 +1547,16 @@ object SymDenotations {
if (myMemberCache != null) myMemberCache invalidate sym.name
}
- /** Make sure the type parameters of this class are `tparams`, reorder definitions
- * in scope if necessary.
+ /** Make sure the type parameters of this class appear in the order given
+ * by `tparams` in the scope of the class. Reorder definitions in scope if necessary.
* @pre All type parameters in `tparams` are entered in class scope `info.decls`.
*/
def updateTypeParams(tparams: List[Symbol])(implicit ctx: Context): Unit =
- if (!typeParams.corresponds(tparams)(_.name == _.name)) {
+ if (!ctx.erasedTypes && !typeParamsFromDecls.corresponds(typeParams)(_.name == _.name)) {
val decls = info.decls
val decls1 = newScope
for (tparam <- tparams) decls1.enter(decls.lookup(tparam.name))
- for (sym <- decls) if (!typeParams.contains(sym)) decls1.enter(sym)
+ for (sym <- decls) if (!tparams.contains(sym)) decls1.enter(sym)
info = classInfo.derivedClassInfo(decls = decls1)
myTypeParams = null
}
@@ -1868,9 +1878,9 @@ object SymDenotations {
/** A subclass of LazyTypes where type parameters can be completed independently of
* the info.
*/
- abstract class TypeParamsCompleter extends LazyType {
+ trait TypeParamsCompleter extends LazyType {
/** The type parameters computed by the completer before completion has finished */
- def completerTypeParams(sym: Symbol): List[TypeSymbol]
+ def completerTypeParams(sym: Symbol)(implicit ctx: Context): List[TypeSymbol]
}
val NoSymbolFn = (ctx: Context) => NoSymbol
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 94e09eaf0..274fc8ff8 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -4,7 +4,7 @@ package core
import Types._
import Contexts._
import Symbols._
-import SymDenotations.TypeParamsCompleter
+import SymDenotations.{LazyType, TypeParamsCompleter}
import Decorators._
import util.Stats._
import util.common._
@@ -191,7 +191,8 @@ object TypeApplications {
else {
def bounds(tparam: MemberBinding) = tparam match {
case tparam: Symbol => tparam.infoOrCompleter
- case tparam: RefinedType => tparam.memberBounds
+ case tparam: RefinedType if !Config.newHK => tparam.memberBounds
+ case tparam: LambdaParam => tparam.memberBounds
}
args.zipWithConserve(tparams)((arg, tparam) => arg.etaExpandIfHK(bounds(tparam)))
}
@@ -380,7 +381,7 @@ class TypeApplications(val self: Type) extends AnyVal {
case self: WildcardType => self.optBounds.knownHK
case self: PolyParam => self.underlying.knownHK
case self: TypeProxy => self.underlying.knownHK
- case NoType => 0
+ case NoType | _: LazyType => 0
case _ => -1
}
@@ -742,7 +743,7 @@ class TypeApplications(val self: Type) extends AnyVal {
self.derivedTypeBounds(self.lo, self.hi.appliedTo(args))
case self: LazyRef =>
LazyRef(() => self.ref.appliedTo(args, typParams))
- case _ if typParams.nonEmpty && typParams.head.isInstanceOf[LambdaParam] =>
+ case _ if typParams.isEmpty || typParams.head.isInstanceOf[LambdaParam] =>
HKApply(self, args)
case _ =>
matchParams(self, typParams, args) match {
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index c23050c19..593dcb967 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1436,6 +1436,9 @@ object Types {
else computeDenot
}
+ /** Hook for adding debug check code when denotations are assigned */
+ final def checkDenot()(implicit ctx: Context) = {}
+
/** A second fallback to recompute the denotation if necessary */
private def computeDenot(implicit ctx: Context): Denotation = {
val savedEphemeral = ctx.typerState.ephemeral
@@ -1471,6 +1474,7 @@ object Types {
// Don't use setDenot here; double binding checks can give spurious failures after erasure
lastDenotation = d
+ checkDenot()
lastSymbol = d.symbol
checkedPeriod = ctx.period
}
@@ -1542,6 +1546,7 @@ object Types {
// additional checks that intercept `denot` can be added here
lastDenotation = denot
+ checkDenot()
lastSymbol = denot.symbol
checkedPeriod = Nowhere
}
@@ -3462,8 +3467,7 @@ object Types {
protected def derivedSuperType(tp: SuperType, thistp: Type, supertp: Type): Type =
tp.derivedSuperType(thistp, supertp)
protected def derivedAppliedType(tp: HKApply, tycon: Type, args: List[Type]): Type =
- if (tycon.typeParams.isEmpty) tycon
- else tp.derivedAppliedType(tycon, args)
+ tp.derivedAppliedType(tycon, args)
protected def derivedAndOrType(tp: AndOrType, tp1: Type, tp2: Type): Type =
tp.derivedAndOrType(tp1, tp2)
protected def derivedAnnotatedType(tp: AnnotatedType, underlying: Type, annot: Annotation): Type =
diff --git a/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
index 2d7b037b1..813376655 100644
--- a/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
+++ b/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
@@ -389,7 +389,7 @@ class ClassfileParser(
}
index += 1
}
- val ownTypeParams = newTParams.toList
+ val ownTypeParams = newTParams.toList.asInstanceOf[List[TypeSymbol]]
val tpe =
if ((owner == null) || !owner.isClass)
sig2type(tparams, skiptvs = false)
@@ -584,7 +584,7 @@ class ClassfileParser(
* a vararg argument. We solve this by creating two constructors, one with
* an array, the other with a repeated parameter.
*/
- def addAnnotationConstructor(classInfo: Type, tparams: List[Symbol] = Nil)(implicit ctx: Context): Unit = {
+ def addAnnotationConstructor(classInfo: Type, tparams: List[TypeSymbol] = Nil)(implicit ctx: Context): Unit = {
def addDefaultGetter(attr: Symbol, n: Int) =
ctx.newSymbol(
owner = moduleRoot.symbol,
diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
index 2ea911380..1da92d723 100644
--- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
+++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
@@ -31,7 +31,7 @@ object Scala2Unpickler {
/** Exception thrown if classfile is corrupted */
class BadSignature(msg: String) extends RuntimeException(msg)
- case class TempPolyType(tparams: List[Symbol], tpe: Type) extends UncachedGroundType {
+ case class TempPolyType(tparams: List[TypeSymbol], tpe: Type) extends UncachedGroundType {
override def fallbackToText(printer: Printer): Text =
"[" ~ printer.dclsText(tparams, ", ") ~ "]" ~ printer.toText(tpe)
}
@@ -195,8 +195,6 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
case _ => errorBadSignature(s"a runtime exception occurred: $ex", Some(ex))
}
- private var postReadOp: Context => Unit = null
-
def run()(implicit ctx: Context) =
try {
var i = 0
@@ -204,10 +202,11 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
if (entries(i) == null && isSymbolEntry(i)) {
val savedIndex = readIndex
readIndex = index(i)
- entries(i) = readSymbol()
- if (postReadOp != null) {
- postReadOp(ctx)
- postReadOp = null
+ val sym = readSymbol()
+ entries(i) = sym
+ sym.infoOrCompleter match {
+ case info: ClassUnpickler => info.init()
+ case _ =>
}
readIndex = savedIndex
}
@@ -493,20 +492,20 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
}
ctx.newSymbol(owner, name1, flags1, localMemberUnpickler, coord = start)
case CLASSsym =>
- val infoRef = readNat()
- postReadOp = implicit ctx => atReadPos(index(infoRef), readTypeParams) // force reading type params early, so they get entered in the right order.
+ var infoRef = readNat()
+ if (isSymbolRef(infoRef)) infoRef = readNat()
if (isClassRoot)
completeRoot(
- classRoot, rootClassUnpickler(start, classRoot.symbol, NoSymbol))
+ classRoot, rootClassUnpickler(start, classRoot.symbol, NoSymbol, infoRef))
else if (isModuleClassRoot)
completeRoot(
- moduleClassRoot, rootClassUnpickler(start, moduleClassRoot.symbol, moduleClassRoot.sourceModule))
+ moduleClassRoot, rootClassUnpickler(start, moduleClassRoot.symbol, moduleClassRoot.sourceModule, infoRef))
else if (name == tpnme.REFINE_CLASS)
// create a type alias instead
ctx.newSymbol(owner, name, flags, localMemberUnpickler, coord = start)
else {
def completer(cls: Symbol) = {
- val unpickler = new LocalUnpickler() withDecls symScope(cls)
+ val unpickler = new ClassUnpickler(infoRef) withDecls symScope(cls)
if (flags is ModuleClass)
unpickler withSourceModule (implicit ctx =>
cls.owner.info.decls.lookup(cls.name.sourceModuleName)
@@ -589,8 +588,27 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
object localMemberUnpickler extends LocalUnpickler
- def rootClassUnpickler(start: Coord, cls: Symbol, module: Symbol) =
- (new LocalUnpickler with SymbolLoaders.SecondCompleter {
+ class ClassUnpickler(infoRef: Int) extends LocalUnpickler with TypeParamsCompleter {
+ private def readTypeParams()(implicit ctx: Context): List[TypeSymbol] = {
+ val tag = readByte()
+ val end = readNat() + readIndex
+ if (tag == POLYtpe) {
+ val unusedRestperef = readNat()
+ until(end, readSymbolRef).asInstanceOf[List[TypeSymbol]]
+ } else Nil
+ }
+ private def loadTypeParams(implicit ctx: Context) =
+ atReadPos(index(infoRef), readTypeParams)
+
+ /** Force reading type params early, we need them in setClassInfo of subclasses. */
+ def init()(implicit ctx: Context) = loadTypeParams
+
+ def completerTypeParams(sym: Symbol)(implicit ctx: Context): List[TypeSymbol] =
+ loadTypeParams
+ }
+
+ def rootClassUnpickler(start: Coord, cls: Symbol, module: Symbol, infoRef: Int) =
+ (new ClassUnpickler(infoRef) with SymbolLoaders.SecondCompleter {
override def startCoord(denot: SymDenotation): Coord = start
}) withDecls symScope(cls) withSourceModule (_ => module)
@@ -756,7 +774,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
case POLYtpe =>
val restpe = readTypeRef()
val typeParams = until(end, readSymbolRef)
- if (typeParams.nonEmpty) TempPolyType(typeParams, restpe.widenExpr)
+ if (typeParams.nonEmpty) TempPolyType(typeParams.asInstanceOf[List[TypeSymbol]], restpe.widenExpr)
else ExprType(restpe)
case EXISTENTIALtpe =>
val restpe = readTypeRef()