From bb940560529ba460af4caa967caaa7f34f944b04 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 16 Jun 2015 13:20:19 +0200 Subject: [PATCH 1/5] Avoid spurious StaleSymbol error in members Refinement classes and their members could give spurious stale symbol errors if the symbol is loaded in a different run than the classfile containing it. The problem is that refinement classes do not form part of the scope of their owners. The fix assumes that refinement classes are always "stillValid". --- src/dotty/tools/dotc/core/SymDenotations.scala | 3 ++- src/dotty/tools/dotc/core/Symbols.scala | 2 +- tests/{pending => }/run/Course-2002-10.check | 0 tests/{pending => }/run/Course-2002-10.scala | 0 4 files changed, 3 insertions(+), 2 deletions(-) rename tests/{pending => }/run/Course-2002-10.check (100%) rename tests/{pending => }/run/Course-2002-10.scala (100%) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index d2b0d5030869..fb26b2540689 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -40,7 +40,7 @@ trait SymDenotations { this: Context => } def stillValid(denot: SymDenotation): Boolean = - if (denot is ValidForever) true + if (denot.is(ValidForever) || denot.isRefinementClass) true else { val initial = denot.initial if (initial ne denot) @@ -49,6 +49,7 @@ trait SymDenotations { this: Context => val owner = denot.owner.denot stillValid(owner) && ( !owner.isClass + || owner.isRefinementClass || (owner.unforcedDecls.lookupAll(denot.name) contains denot.symbol) || denot.isSelfSym) } catch { diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 0478b1b7be50..602bdba80d0a 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -408,7 +408,7 @@ object Symbols { /** Subclass tests and casts */ final def isTerm(implicit ctx: Context): Boolean = (if(isDefinedInCurrentRun) lastDenot else denot).isTerm - + final def isType(implicit ctx: Context): Boolean = (if(isDefinedInCurrentRun) lastDenot else denot).isType diff --git a/tests/pending/run/Course-2002-10.check b/tests/run/Course-2002-10.check similarity index 100% rename from tests/pending/run/Course-2002-10.check rename to tests/run/Course-2002-10.check diff --git a/tests/pending/run/Course-2002-10.scala b/tests/run/Course-2002-10.scala similarity index 100% rename from tests/pending/run/Course-2002-10.scala rename to tests/run/Course-2002-10.scala From d25497a92f425c8966dce47cd17fba456ef2660f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 16 Jun 2015 15:02:22 +0200 Subject: [PATCH 2/5] Avoid double negation in isJvmSam. Found while trying to chase down the problem with stale symbols in last commit. Double negation is confusing. The new formulation avoids it. --- src/dotty/tools/dotc/transform/ExpandSAMs.scala | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/src/dotty/tools/dotc/transform/ExpandSAMs.scala index 2416e46246fb..1650a244d337 100644 --- a/src/dotty/tools/dotc/transform/ExpandSAMs.scala +++ b/src/dotty/tools/dotc/transform/ExpandSAMs.scala @@ -25,20 +25,19 @@ class ExpandSAMs extends MiniPhaseTransform { thisTransformer => import ast.tpd._ - def noJvmSam(cls: ClassSymbol)(implicit ctx: Context): Boolean = - !cls.is(Trait) || - cls.superClass != defn.ObjectClass || - !cls.is(NoInits) || - !cls.directlyInheritedTraits.forall(_.is(NoInits)) || - ExplicitOuter.needsOuterIfReferenced(cls) || - cls.typeRef.fields.nonEmpty // Superaccessors already show up as abstract methods here, so no test necessary - + /** Is SAMType `cls` also a SAM under the rules of the JVM? */ + def isJvmSam(cls: ClassSymbol)(implicit ctx: Context): Boolean = + cls.is(NoInitsTrait) && + cls.superClass == defn.ObjectClass && + cls.directlyInheritedTraits.forall(_.is(NoInits)) && + !ExplicitOuter.needsOuterIfReferenced(cls) && + cls.typeRef.fields.isEmpty // Superaccessors already show up as abstract methods here, so no test necessary override def transformBlock(tree: Block)(implicit ctx: Context, info: TransformerInfo): Tree = tree match { case Block(stats @ (fn: DefDef) :: Nil, Closure(_, fnRef, tpt)) if fnRef.symbol == fn.symbol => tpt.tpe match { case NoType => tree // it's a plain function - case tpe @ SAMType(_) if !noJvmSam(tpe.classSymbol.asClass) => + case tpe @ SAMType(_) if isJvmSam(tpe.classSymbol.asClass) => if (tpe isRef defn.PartialFunctionClass) toPartialFunction(tree) else tree case tpe => From 4eb107258458801b72e5c34ab4ccf3729b9e12d6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 16 Jun 2015 16:12:45 +0200 Subject: [PATCH 3/5] Produce PureInterface flag together with NoInits flag The previous stale symbol was discovered because NormalizeFlags looks at all declarations of a MoInits trait in the SymTransformer. I.e it does this for all no-init traits, whether loaded from a classfile or currently compiled. This is wasteful because it forces too many definitions. The new scheme drops the scan in favor of producing PureInterface together with NoInits. PureInterface is already read as a flag from Java snd Scala2 classfiles. For source and Tasty it is now generated as members are indexed. --- src/dotty/tools/dotc/ast/TreeInfo.scala | 32 ++++++++++++++----- .../tools/dotc/core/SymDenotations.scala | 6 ++++ .../tools/dotc/core/tasty/TreeUnpickler.scala | 23 +++++++------ .../tools/dotc/transform/NormalizeFlags.scala | 5 --- src/dotty/tools/dotc/typer/Namer.scala | 3 +- 5 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala index 6401c01c1273..b20b7c9f249c 100644 --- a/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -8,6 +8,7 @@ import Names._, StdNames._, NameOps._, Decorators._, Symbols._ import util.HashSet trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] => + import TreeInfo._ // Note: the <: Type constraint looks necessary (and is needed to make the file compile in dotc). // But Scalac accepts the program happily without it. Need to find out why. @@ -26,10 +27,12 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] => /** Does tree contain an initialization part when seen as a member of a class or trait? */ - def isNoInitMember(tree: Tree): Boolean = unsplice(tree) match { - case EmptyTree | Import(_, _) | TypeDef(_, _) | DefDef(_, _, _, _, _) => true - case tree: ValDef => tree.unforcedRhs == EmptyTree - case _ => false + def defKind(tree: Tree): DefKind = unsplice(tree) match { + case EmptyTree | _: Import => InterfaceDef + case tree: TypeDef => if (tree.isClassDef) NoInitDef else InterfaceDef + case tree: DefDef => if (tree.unforcedRhs == EmptyTree) InterfaceDef else NoInitDef + case tree: ValDef => if (tree.unforcedRhs == EmptyTree) InterfaceDef else GeneralDef + case _ => GeneralDef } def isOpAssign(tree: Tree) = unsplice(tree) match { @@ -272,6 +275,7 @@ trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped] } trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => + import TreeInfo._ /** The purity level of this statement. * @return pure if statement has no side effects @@ -510,15 +514,27 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => case nil => Nil } +} + +object TreeInfo { - private class PurityLevel(val x: Int) { + class PurityLevel(val x: Int) extends AnyVal { def >= (that: PurityLevel) = x >= that.x def min(that: PurityLevel) = new PurityLevel(x min that.x) } - private val Pure = new PurityLevel(2) - private val Idempotent = new PurityLevel(1) - private val Impure = new PurityLevel(0) + val Pure = new PurityLevel(2) + val Idempotent = new PurityLevel(1) + val Impure = new PurityLevel(0) + + case class DefKind(val x: Int) extends AnyVal { + def >= (that: DefKind) = x >= that.x + def min(that: DefKind) = new DefKind(x min that.x) + } + + val InterfaceDef = new DefKind(2) + val NoInitDef = new DefKind(1) + val GeneralDef = new DefKind(0) } /** a Match(Typed(_, tpt), _) must be translated into a switch if isSwitchAnnotation(tpt.tpe) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index fb26b2540689..f4fde3e81dd6 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -115,6 +115,12 @@ object SymDenotations { /** Unset given flags(s) of this denotation */ final def resetFlag(flags: FlagSet): Unit = { myFlags &~= flags } + final def setFlagsFromDefKind(kind: TreeInfo.DefKind): Unit = + if (kind >= TreeInfo.NoInitDef) { + setFlag(NoInits) + if (kind == TreeInfo.InterfaceDef && myFlags.is(Trait)) setFlag(PureInterface) + } + /** Has this denotation one of the flags in `fs` set? */ final def is(fs: FlagSet)(implicit ctx: Context) = { (if (fs <= FromStartFlags) myFlags else flags) is fs diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index e753bdcab739..0dfef0c5100b 100644 --- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -6,7 +6,8 @@ package tasty import Contexts._, Symbols._, Types._, Scopes._, SymDenotations._, Names._, NameOps._ import StdNames._, Denotations._, Flags._, Constants._, Annotations._ import util.Positions._ -import dotty.tools.dotc.ast.{tpd, Trees, untpd} +import ast.{tpd, Trees, untpd} +import ast.TreeInfo._ import Trees._ import Decorators._ import TastyUnpickler._, TastyBuffer._, PositionPickler._ @@ -352,7 +353,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { /** Create symbol of definition node and enter in symAtAddr map * @return true iff the definition does not contain initialization code */ - def createSymbol()(implicit ctx: Context): Boolean = { + def createSymbol()(implicit ctx: Context): DefKind = { val start = currentAddr val tag = readByte() val end = readEnd() @@ -408,7 +409,10 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { sym.completer.withDecls(newScope) forkAt(templateStart).indexTemplateParams()(localContext(sym)) } - tag != VALDEF || rhsIsEmpty + if (isClass) NoInitDef + else if (sym.isType || sym.isConstructor || flags.is(Deferred)) InterfaceDef + else if (tag == VALDEF) GeneralDef + else NoInitDef } /** Read modifier list into triplet of flags, annotations and a privateWithin @@ -474,23 +478,23 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { * current address and `end`. * @return true iff none of the statements contains initialization code */ - def indexStats(end: Addr)(implicit ctx: Context): Boolean = { - val noInitss = + def indexStats(end: Addr)(implicit ctx: Context): DefKind = { + val defKinds = until(end) { nextByte match { case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM => createSymbol() case IMPORT => skipTree() - true + InterfaceDef case PACKAGE => processPackage { (pid, end) => implicit ctx => indexStats(end) } case _ => skipTree() - false + GeneralDef } } - noInitss.forall(_ == true) + (InterfaceDef /: defKinds)(_ min _) } /** Process package with given operation `op`. The operation takes as arguments @@ -631,8 +635,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { } else EmptyValDef setClsInfo(parentRefs, if (self.isEmpty) NoType else self.tpt.tpe) - val noInits = fork.indexStats(end) - if (noInits) cls.setFlag(NoInits) + cls.setFlagsFromDefKind(fork.indexStats(end)) 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/NormalizeFlags.scala b/src/dotty/tools/dotc/transform/NormalizeFlags.scala index 2f5907b75b67..75584690409c 100644 --- a/src/dotty/tools/dotc/transform/NormalizeFlags.scala +++ b/src/dotty/tools/dotc/transform/NormalizeFlags.scala @@ -19,12 +19,7 @@ class NormalizeFlags extends MiniPhaseTransform with SymTransformer { thisTransf 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 10667f884928..e8a0294f8479 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -563,7 +563,8 @@ 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) + cls.setFlagsFromDefKind( + (TreeInfo.InterfaceDef /: impl.body)((kind, stat) => kind min defKind(stat))) } } From 112f39aa1c3a9e36848b30d7d2709fb1b2ef7949 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 16 Jun 2015 16:27:10 +0200 Subject: [PATCH 4/5] Use FlagSet directly instead of defKind Instead of classifying class members with a TreeInfo.DefKind, we use directly the flags into which kinds were previously translated. --- src/dotty/tools/dotc/ast/TreeInfo.scala | 26 ++++++----------- src/dotty/tools/dotc/core/Flags.scala | 2 ++ .../tools/dotc/core/SymDenotations.scala | 10 +++---- .../tools/dotc/core/tasty/TreeUnpickler.scala | 29 ++++++++++--------- src/dotty/tools/dotc/typer/Namer.scala | 4 +-- 5 files changed, 33 insertions(+), 38 deletions(-) diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala index b20b7c9f249c..c9a22f09e8e7 100644 --- a/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -25,14 +25,16 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] => case _ => false } - /** Does tree contain an initialization part when seen as a member of a class or trait? + /** The largest subset of {NoInits, PureInterface} that a + * trait enclosing this statement can have as flags. + * Does tree contain an initialization part when seen as a member of a class or trait? */ - def defKind(tree: Tree): DefKind = unsplice(tree) match { - case EmptyTree | _: Import => InterfaceDef - case tree: TypeDef => if (tree.isClassDef) NoInitDef else InterfaceDef - case tree: DefDef => if (tree.unforcedRhs == EmptyTree) InterfaceDef else NoInitDef - case tree: ValDef => if (tree.unforcedRhs == EmptyTree) InterfaceDef else GeneralDef - case _ => GeneralDef + def defKind(tree: Tree): FlagSet = unsplice(tree) match { + case EmptyTree | _: Import => NoInitsInterface + case tree: TypeDef => if (tree.isClassDef) NoInits else NoInitsInterface + case tree: DefDef => if (tree.unforcedRhs == EmptyTree) NoInitsInterface else NoInits + case tree: ValDef => if (tree.unforcedRhs == EmptyTree) NoInitsInterface else EmptyFlags + case _ => EmptyFlags } def isOpAssign(tree: Tree) = unsplice(tree) match { @@ -517,7 +519,6 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => } object TreeInfo { - class PurityLevel(val x: Int) extends AnyVal { def >= (that: PurityLevel) = x >= that.x def min(that: PurityLevel) = new PurityLevel(x min that.x) @@ -526,15 +527,6 @@ object TreeInfo { val Pure = new PurityLevel(2) val Idempotent = new PurityLevel(1) val Impure = new PurityLevel(0) - - case class DefKind(val x: Int) extends AnyVal { - def >= (that: DefKind) = x >= that.x - def min(that: DefKind) = new DefKind(x min that.x) - } - - val InterfaceDef = new DefKind(2) - val NoInitDef = new DefKind(1) - val GeneralDef = new DefKind(0) } /** a Match(Typed(_, tpt), _) must be translated into a switch if isSwitchAnnotation(tpt.tpe) diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index 3efadcb00406..759dff0d44d8 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -467,6 +467,8 @@ object Flags { /** Pure interfaces always have these flags */ final val PureInterfaceCreationFlags = Trait | NoInits | PureInterface + final val NoInitsInterface = NoInits | PureInterface + /** The flags of the self symbol */ final val SelfSymFlags = Private | Local | Deferred diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index f4fde3e81dd6..6d8d6a8f065a 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -115,11 +115,11 @@ object SymDenotations { /** Unset given flags(s) of this denotation */ final def resetFlag(flags: FlagSet): Unit = { myFlags &~= flags } - final def setFlagsFromDefKind(kind: TreeInfo.DefKind): Unit = - if (kind >= TreeInfo.NoInitDef) { - setFlag(NoInits) - if (kind == TreeInfo.InterfaceDef && myFlags.is(Trait)) setFlag(PureInterface) - } + /** Set applicable flags from `flags` which is a subset of {NoInits, PureInterface} */ + final def setApplicableFlags(flags: FlagSet): Unit = { + val mask = if (myFlags.is(Trait)) NoInitsInterface else NoInits + setFlag(flags & mask) + } /** Has this denotation one of the flags in `fs` set? */ final def is(fs: FlagSet)(implicit ctx: Context) = { diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 0dfef0c5100b..44abef435274 100644 --- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -7,7 +7,6 @@ import Contexts._, Symbols._, Types._, Scopes._, SymDenotations._, Names._, Name import StdNames._, Denotations._, Flags._, Constants._, Annotations._ import util.Positions._ import ast.{tpd, Trees, untpd} -import ast.TreeInfo._ import Trees._ import Decorators._ import TastyUnpickler._, TastyBuffer._, PositionPickler._ @@ -351,9 +350,10 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { } /** Create symbol of definition node and enter in symAtAddr map - * @return true iff the definition does not contain initialization code + * @return the largest subset of {NoInits, PureInterface} that a + * trait owning this symbol can have as flags. */ - def createSymbol()(implicit ctx: Context): DefKind = { + def createSymbol()(implicit ctx: Context): FlagSet = { val start = currentAddr val tag = readByte() val end = readEnd() @@ -409,10 +409,10 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { sym.completer.withDecls(newScope) forkAt(templateStart).indexTemplateParams()(localContext(sym)) } - if (isClass) NoInitDef - else if (sym.isType || sym.isConstructor || flags.is(Deferred)) InterfaceDef - else if (tag == VALDEF) GeneralDef - else NoInitDef + if (isClass) NoInits + else if (sym.isType || sym.isConstructor || flags.is(Deferred)) NoInitsInterface + else if (tag == VALDEF) EmptyFlags + else NoInits } /** Read modifier list into triplet of flags, annotations and a privateWithin @@ -476,25 +476,26 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { /** Create symbols for a definitions in statement sequence between * current address and `end`. - * @return true iff none of the statements contains initialization code + * @return the largest subset of {NoInits, PureInterface} that a + * trait owning the indexed statements can have as flags. */ - def indexStats(end: Addr)(implicit ctx: Context): DefKind = { - val defKinds = + def indexStats(end: Addr)(implicit ctx: Context): FlagSet = { + val flagss = until(end) { nextByte match { case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM => createSymbol() case IMPORT => skipTree() - InterfaceDef + NoInitsInterface case PACKAGE => processPackage { (pid, end) => implicit ctx => indexStats(end) } case _ => skipTree() - GeneralDef + EmptyFlags } } - (InterfaceDef /: defKinds)(_ min _) + (NoInitsInterface /: flagss)(_ & _) } /** Process package with given operation `op`. The operation takes as arguments @@ -635,7 +636,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { } else EmptyValDef setClsInfo(parentRefs, if (self.isEmpty) NoType else self.tpt.tpe) - cls.setFlagsFromDefKind(fork.indexStats(end)) + cls.setApplicableFlags(fork.indexStats(end)) val constr = readIndexedDef().asInstanceOf[DefDef] def mergeTypeParamsAndAliases(tparams: List[TypeDef], stats: List[Tree]): (List[Tree], List[Tree]) = diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index e8a0294f8479..879c0d0a8cc2 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -563,8 +563,8 @@ class Namer { typer: Typer => index(rest)(inClassContext(selfInfo)) denot.info = ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfInfo) - cls.setFlagsFromDefKind( - (TreeInfo.InterfaceDef /: impl.body)((kind, stat) => kind min defKind(stat))) + cls.setApplicableFlags( + (NoInitsInterface /: impl.body)((fs, stat) => fs & defKind(stat))) } } From 0e6b857ae9501ce3708f273618caafee6b614f82 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 16 Jun 2015 16:41:22 +0200 Subject: [PATCH 5/5] Add NoInits when reading a Scala2 pure interface NoInits is implied for pure interfaces, so has to be set. The Java classfile parser already does the right thing here. --- src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala b/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala index aa1fd9a903ce..b080a97b6e94 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala @@ -220,7 +220,7 @@ object PickleBuffer { DEFERRED_PKL -> Deferred, FINAL_PKL -> Final, METHOD_PKL -> Method, - INTERFACE_PKL -> PureInterface, + INTERFACE_PKL -> NoInitsInterface, MODULE_PKL -> Module, IMPLICIT_PKL -> Implicit, SEALED_PKL -> Sealed,