aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-03-05 13:22:00 +0100
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2015-03-18 11:14:15 +0100
commit321563940dee1716c19600efd57acb9ed83a7687 (patch)
tree9053dfcff007d16ceb6dbaa7256889455a7a07a7 /src/dotty/tools
parent7fd242f2f1b1d2f536e73ec0fdb92a34b27b2a89 (diff)
downloaddotty-321563940dee1716c19600efd57acb9ed83a7687.tar.gz
dotty-321563940dee1716c19600efd57acb9ed83a7687.tar.bz2
dotty-321563940dee1716c19600efd57acb9ed83a7687.zip
Compute PureInterface flag after pickling.
ElimLocals becomes a slightly less trivial transform: NormalizeFlags. It also computes PureInterface flag, thus relieving Namer and Unpickler from doing the same in two different ways. Besides, the computation in Namer/TreeInfo was flawed because it did not take into account that nested non-static classes are not allowed in an interface (only static classes are, but these would not be members of the interface in the Scala sense).
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/Compiler.scala2
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala11
-rw-r--r--src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala27
-rw-r--r--src/dotty/tools/dotc/transform/ElimLocals.scala22
-rw-r--r--src/dotty/tools/dotc/transform/NormalizeFlags.scala30
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala6
6 files changed, 46 insertions, 52 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index dea619a52..e051e16c8 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -44,7 +44,7 @@ class Compiler {
List(new Pickler), // Pickler needs to come last in a group since it should not pickle trees generated later
List(new RefChecks,
new ElimRepeated,
- new ElimLocals,
+ new NormalizeFlags,
new ExtensionMethods),
List(new TailRec), // TailRec needs to be in its own group for now.
// Otherwise it produces -Ycheck incorrect code for
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index 5338297e8..0abd25f51 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -24,19 +24,14 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
case _ => false
}
- /** Is tree legal as a member definition of an interface?
+ /** Does tree contain an initialization part when seen as a member of a class or trait?
*/
- def isPureInterfaceMember(tree: Tree): Boolean = unsplice(tree) match {
+ def isNoInitMember(tree: Tree): Boolean = unsplice(tree) match {
case EmptyTree | Import(_, _) | TypeDef(_, _) => true
- case defn: ValOrDefDef => defn.unforcedRhs == EmptyTree
+ case tree: ValDef => tree.unforcedRhs == EmptyTree
case _ => false
}
- /** Is tree legal as a member definition of a no-init trait?
- */
- def isNoInitMember(tree: Tree): Boolean =
- isPureInterfaceMember(tree) || unsplice(tree).isInstanceOf[DefDef]
-
def isOpAssign(tree: Tree) = unsplice(tree) match {
case Apply(fn, _ :: Nil) =>
unsplice(fn) match {
diff --git a/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala b/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala
index 4890e14ef..7b2a8fdc4 100644
--- a/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala
@@ -286,9 +286,9 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
}
/** Create symbol of definition node and enter in symAtAddr map
- * @return flag set over PureInterface | NoInits according to form of definition
+ * @return true iff the definition does not contain initialization code
*/
- def createSymbol()(implicit ctx: Context): FlagSet = {
+ def createSymbol()(implicit ctx: Context): Boolean = {
val start = currentAddr
val tag = readByte()
val end = readEnd()
@@ -340,11 +340,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
completer.withDecls(newScope)
forkAt(templateStart).indexTemplateParams()(localContext(sym))
}
-
- var resultFlags: FlagSet = EmptyFlags
- if (tag != VALDEF || rhsIsEmpty) resultFlags |= NoInits
- if (tag != VALDEF && tag != DEFDEF || rhsIsEmpty) resultFlags |= PureInterface
- resultFlags
+ tag != VALDEF || rhsIsEmpty
}
/** Read modifier list into triplet of flags, annotations and a privateWithin
@@ -409,18 +405,18 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
/** Create symbols for a definitions in statement sequence between
* current address and `end`.
- * @return flag set over PureInterface | NoInits according to forms of statements
+ * @return true iff none of the statements contains initialization code
*/
- def indexStats(end: Addr)(implicit ctx: Context): FlagSet = {
- val statFlags =
+ def indexStats(end: Addr)(implicit ctx: Context): Boolean = {
+ val noInitss =
until(end) {
nextByte match {
case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM => createSymbol()
- case EMPTYTREE | IMPORT => skipTree(); PureInterface | NoInits
- case _ => skipTree(); EmptyFlags
+ case EMPTYTREE | IMPORT => skipTree(); true
+ case _ => skipTree(); false
}
}
- ((PureInterface | NoInits) /: statFlags) (_ & _)
+ noInitss.forall(_ == true)
}
/** Create symbols the longest consecutive sequence of parameters with given
@@ -506,7 +502,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
setClsInfo(
ctx.normalizeToClassRefs(impl.parents.map(_.tpe), cls, cls.unforcedDecls),
if (impl.self.isEmpty) NoType else impl.self.tpt.tpe)
- if (!cls.is(Trait)) cls.resetFlag(PureInterface)
ta.assignType(untpd.TypeDef(sym.name.asTypeName, impl), sym)
}
else {
@@ -549,8 +544,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
untpd.ValDef(readName(), readTpt(), EmptyTree).withType(NoType)
}
else EmptyValDef
- val additionalFlags = fork.indexStats(end) // PureInterface or NoInits
- cls.setFlag(additionalFlags) // PureInterface will be reset later if cls is not a trait
+ val noInits = fork.indexStats(end)
+ if (noInits) cls.setFlag(NoInits)
val constr = readIndexedDef().asInstanceOf[DefDef]
def mergeTypeParamsAndAliases(tparams: List[TypeDef], stats: List[Tree]): (List[Tree], List[Tree]) =
diff --git a/src/dotty/tools/dotc/transform/ElimLocals.scala b/src/dotty/tools/dotc/transform/ElimLocals.scala
deleted file mode 100644
index d18ad0288..000000000
--- a/src/dotty/tools/dotc/transform/ElimLocals.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package dotty.tools.dotc
-package transform
-
-import core._
-import DenotTransformers.SymTransformer
-import Phases.Phase
-import Contexts.Context
-import SymDenotations.SymDenotation
-import TreeTransforms.MiniPhaseTransform
-import Flags.Local
-
-/** Widens all private[this] and protected[this] qualifiers to just private/protected */
-class ElimLocals extends MiniPhaseTransform with SymTransformer { thisTransformer =>
- override def phaseName = "elimLocals"
-
- def transformSym(ref: SymDenotation)(implicit ctx: Context) =
- dropLocal(ref)
-
- private def dropLocal(ref: SymDenotation)(implicit ctx: Context) =
- if (ref.flags is Local) ref.copySymDenotation(initFlags = ref.flags &~ Local)
- else ref
-}
diff --git a/src/dotty/tools/dotc/transform/NormalizeFlags.scala b/src/dotty/tools/dotc/transform/NormalizeFlags.scala
new file mode 100644
index 000000000..fce2c3317
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/NormalizeFlags.scala
@@ -0,0 +1,30 @@
+package dotty.tools.dotc
+package transform
+
+import core._
+import DenotTransformers.SymTransformer
+import Phases.Phase
+import Contexts.Context
+import SymDenotations.SymDenotation
+import TreeTransforms.MiniPhaseTransform
+import Flags._, Symbols._
+
+/** 1. Widens all private[this] and protected[this] qualifiers to just private/protected
+ * 2. Sets PureInterface flag for traits that only have pure interface members and that
+ * do not have initialization code. A pure interface member is either an abstract
+ * or alias type definition or a deferred val or def.
+ */
+class NormalizeFlags extends MiniPhaseTransform with SymTransformer { thisTransformer =>
+ override def phaseName = "elimLocals"
+
+ def transformSym(ref: SymDenotation)(implicit ctx: Context) = {
+ var newFlags = ref.flags &~ Local
+ if (ref.is(NoInitsTrait) && ref.info.decls.forall(isPureInterfaceMember))
+ newFlags |= PureInterface
+ if (newFlags != ref.flags) ref.copySymDenotation(initFlags = newFlags)
+ else ref
+ }
+
+ private def isPureInterfaceMember(sym: Symbol)(implicit ctx: Context) =
+ if (sym.isTerm) sym.is(Deferred) else !sym.isClass
+}
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 04f648c00..708fb06c1 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -523,11 +523,7 @@ class Namer { typer: Typer =>
index(rest)(inClassContext(selfInfo))
denot.info = ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfInfo)
- if (impl.body forall isNoInitMember) {
- cls.setFlag(NoInits)
- if (cls.is(Trait) && impl.body.forall(isPureInterfaceMember))
- cls.setFlag(PureInterface)
- }
+ if (impl.body forall isNoInitMember) cls.setFlag(NoInits)
}
}