diff options
-rw-r--r-- | src/dotty/tools/dotc/ast/TreeInfo.scala | 15 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Definitions.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Flags.scala | 18 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/ClassfileConstants.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/ClassfileParser.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/PickleBuffer.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/PlainPrinter.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/AttachOuter.scala | 65 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/ExplicitOuter.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/Mixin.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 7 |
11 files changed, 43 insertions, 91 deletions
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala index 51e1ff16f..8163c8bcc 100644 --- a/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -26,15 +26,18 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] => /** Is tree legal as a member definition of an interface? */ - def isInterfaceMember(tree: Tree): Boolean = unsplice(tree) match { - case EmptyTree => true - case Import(_, _) => true - case TypeDef(_, _, _) => true - case DefDef(mods, _, _, _, _, __) => mods.flags is Deferred - case ValDef(mods, _, _, _) => mods is Deferred + def isPureInterfaceMember(tree: Tree): Boolean = unsplice(tree) match { + case EmptyTree | Import(_, _) | TypeDef(_, _, _) => true + case DefDef(_, _, _, _, _, rhs) => rhs.isEmpty + case ValDef(mods, _, _, rhs) => rhs.isEmpty 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/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index b1c2baff6..d78e09418 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -191,7 +191,7 @@ class Definitions { lazy val ScalaStaticsClass = ScalaStaticsModule.moduleClass.asClass def staticsMethod(name: PreName) = ctx.requiredMethod(ScalaStaticsClass, name) - + lazy val DottyPredefModule = ctx.requiredModule("dotty.DottyPredef") lazy val NilModule = ctx.requiredModule("scala.collection.immutable.Nil") lazy val PredefConformsClass = ctx.requiredClass("scala.Predef." + tpnme.Conforms) @@ -201,7 +201,7 @@ class Definitions { // needed as a synthetic class because Scala 2.x refers to it in classfiles // but does not define it as an explicit class. newCompleteClassSymbol( - ScalaPackageClass, tpnme.Singleton, Trait | Interface | Final, + ScalaPackageClass, tpnme.Singleton, PureInterfaceCreationFlags | Final, List(AnyClass.typeRef), EmptyScope) lazy val SeqClass: ClassSymbol = ctx.requiredClass("scala.collection.Seq") lazy val Seq_apply = ctx.requiredMethod(SeqClass, nme.apply) @@ -506,7 +506,7 @@ class Definitions { val cls = newClassSymbol( ScalaPackageClass, traitName, - Trait | Interface | Synthetic, + PureInterfaceCreationFlags | Synthetic, completer) myLambdaTraits += cls cls diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index 804f6af1a..db969767b 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -287,7 +287,7 @@ object Flags { /** A trait that has only abstract methods as members * (and therefore can be represented by a Java interface */ - final val Interface = typeFlag(22, "interface") + final val PureInterface = typeFlag(22, "interface") /** Labeled with of abstract & override */ final val AbsOverride = termFlag(22, "abstract override") @@ -335,6 +335,9 @@ object Flags { final val JavaStaticTerm = JavaStatic.toTermFlags final val JavaStaticType = JavaStatic.toTypeFlags + /** Trait is not an interface, but does not have fields or intialization code */ + final val NoInits = typeFlag(32, "<noInits>") + /** Variable is accessed from nested function. */ final val Captured = termFlag(32, "<captured>") @@ -353,9 +356,6 @@ object Flags { /** Symbol is a Java-style varargs method */ final val JavaVarargs = termFlag(37, "<varargs>") - /** Symbol is a Java default method */ - final val DefaultMethod = termFlag(38, "<defaultmethod>") - // Flags following this one are not pickled /** Symbol always defines a fresh named type */ @@ -464,6 +464,9 @@ object Flags { /** Accessors always have these flags set */ final val AccessorCreationFlags = Method | Accessor + /** Pure interfaces always have these flags */ + final val PureInterfaceCreationFlags = Trait | NoInits | PureInterface + /** The flags of the self symbol */ final val SelfSymFlags = Private | Local | Deferred @@ -539,8 +542,11 @@ object Flags { /** Is a default parameter in Scala 2*/ final val DefaultParameter = allOf(Param, DefaultParameterized) - /** A Java interface */ - final val JavaInterface = allOf(JavaDefined, Trait) + /** A trait that does not need to be initialized */ + final val NoInitsTrait = allOf(Trait, NoInits) + + /** A Java interface, potentially with default methods */ + final val JavaTrait = allOf(JavaDefined, Trait, NoInits) /** A Java companion object */ final val JavaModule = allOf(JavaDefined, Module) diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileConstants.scala b/src/dotty/tools/dotc/core/pickling/ClassfileConstants.scala index c35b9ca47..158f6b409 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileConstants.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileConstants.scala @@ -345,7 +345,7 @@ object ClassfileConstants { case JAVA_ACC_SYNTHETIC => Synthetic case JAVA_ACC_STATIC => JavaStatic case JAVA_ACC_ABSTRACT => if (isAnnotation) EmptyFlags else if (isClass) Abstract else Deferred - case JAVA_ACC_INTERFACE => if (isAnnotation) EmptyFlags else JavaInterface + case JAVA_ACC_INTERFACE => if (isAnnotation) EmptyFlags else PureInterfaceCreationFlags | JavaDefined case _ => EmptyFlags } diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala index 67f825502..f2a5e4171 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala @@ -503,8 +503,9 @@ class ClassfileParser( parseExceptions(attrLen) case tpnme.CodeATTR => - if (sym.owner is Flags.Interface) { - sym.setFlag(Flags.DefaultMethod) + if (sym.owner is Flags.JavaTrait) { + sym.resetFlag(Flags.Deferred) + sym.owner.resetFlag(Flags.PureInterface) ctx.log(s"$sym in ${sym.owner} is a java8+ default method.") } in.skip(attrLen) diff --git a/src/dotty/tools/dotc/core/pickling/PickleBuffer.scala b/src/dotty/tools/dotc/core/pickling/PickleBuffer.scala index d2a05bf3a..9f8d4fc2d 100644 --- a/src/dotty/tools/dotc/core/pickling/PickleBuffer.scala +++ b/src/dotty/tools/dotc/core/pickling/PickleBuffer.scala @@ -220,7 +220,7 @@ object PickleBuffer { DEFERRED_PKL -> Deferred, FINAL_PKL -> Final, METHOD_PKL -> Method, - INTERFACE_PKL -> Interface, + INTERFACE_PKL -> PureInterface, MODULE_PKL -> Module, IMPLICIT_PKL -> Implicit, SEALED_PKL -> Sealed, diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala index 78ee32b98..ffbae59bb 100644 --- a/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -296,7 +296,7 @@ class PlainPrinter(_ctx: Context) extends Printer { /** String representation of symbol's definition key word */ protected def keyString(sym: Symbol): String = { val flags = sym.flagsUNSAFE - if (flags is JavaInterface) "interface" + if (flags is JavaTrait) "interface" else if ((flags is Trait) && !(flags is ImplClass)) "trait" else if (sym.isClass) "class" else if (sym.isType) "type" diff --git a/src/dotty/tools/dotc/transform/AttachOuter.scala b/src/dotty/tools/dotc/transform/AttachOuter.scala deleted file mode 100644 index 9d2b0574d..000000000 --- a/src/dotty/tools/dotc/transform/AttachOuter.scala +++ /dev/null @@ -1,65 +0,0 @@ -package dotty.tools.dotc -package transform - -import TreeTransforms._ -import core.DenotTransformers._ -import core.Symbols._ -import core.Contexts._ -import core.Types._ -import core.Flags._ -import core.Decorators._ -import core.StdNames.nme -import ast.Trees._ -import util.Attachment - -/** This phase decorates News and parent constructors of non-static inner classes - * with an attachment indicating the outer reference as a tree. This is necessary because - * outer prefixes are erased, and explicit outer runs only after erasure. - */ -class AttachOuter extends MiniPhaseTransform { - import ast.tpd._ - - val Outer = new Attachment.Key[Tree] - - override def phaseName: String = "attachOuter" - - private def outerPrefix(tpe: Type)(implicit ctx: Context): Type = tpe match { - case tpe: TypeRef => - tpe.symbol match { - case cls: ClassSymbol => - if (cls.owner.isStaticOwner || cls.is(Interface)) NoPrefix - else if (tpe.prefix eq NoPrefix) cls.owner.enclosingClass.thisType - else tpe.prefix - case _ => - outerPrefix(tpe.underlying) - } - case tpe: TypeProxy => - outerPrefix(tpe.underlying) - } - - override def transformNew(tree: New)(implicit ctx: Context, info: TransformerInfo): Tree = { - val pre = outerPrefix(tree.tpt.tpe) - pre match { - case pre: SingletonType => - tree.putAttachment(Outer, singleton(pre)) match { - case Some(outer) => assert(outer.tpe =:= pre) - case none => - } - case NoPrefix => - } - tree - } - - override def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo): Tree = { - def transformParent(tree: Tree): Tree = tree match { - case tree: TypeTree if outerPrefix(tree.tpe) != NoPrefix => - val constr = New(tree.tpe, Nil).withPos(tree.pos) - val Select(nu: New, _) = methPart(constr) - transformNew(nu) - constr - case _ => - tree - } - cpy.Template(tree)(parents = tree.parents mapconserve transformParent) - } -}
\ No newline at end of file diff --git a/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/src/dotty/tools/dotc/transform/ExplicitOuter.scala index 28d742b5e..436d9bcf7 100644 --- a/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -144,11 +144,11 @@ object ExplicitOuter { nme.OUTER.expandedName(cls) /** Class needs an outer pointer, provided there is a reference to an outer this in it. */ - def needsOuterIfReferenced(cls: ClassSymbol)(implicit ctx: Context): Boolean = !( - cls.isStatic || - cls.owner.enclosingClass.isStaticOwner || - cls.is(Interface) - ) + def needsOuterIfReferenced(cls: ClassSymbol)(implicit ctx: Context): Boolean = + !(cls.isStatic || + cls.owner.enclosingClass.isStaticOwner || + cls.is(PureInterface) + ) /** Class unconditionally needs an outer pointer. This is the case if * the class needs an outer pointer if referenced and one of the following holds: diff --git a/src/dotty/tools/dotc/transform/Mixin.scala b/src/dotty/tools/dotc/transform/Mixin.scala index 1d342404a..3d68a2687 100644 --- a/src/dotty/tools/dotc/transform/Mixin.scala +++ b/src/dotty/tools/dotc/transform/Mixin.scala @@ -134,7 +134,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform => case Some(call) => if (defn.PhantomClasses.contains(baseCls)) Nil else call :: Nil case None => - if (baseCls.is(Interface) || defn.PhantomClasses.contains(baseCls)) Nil + if (baseCls.is(NoInitsTrait) || defn.PhantomClasses.contains(baseCls)) Nil else { //println(i"synth super call ${baseCls.primaryConstructor}: ${baseCls.primaryConstructor.info}") superRef(baseCls.primaryConstructor).appliedToNone :: Nil diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 3a1f0a98b..e8bb1b9e7 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -492,6 +492,13 @@ class Namer { typer: Typer => index(rest)(inClassContext(selfInfo)) denot.info = ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfInfo) + if (cls is Trait) { + if (body forall isNoInitMember) { + cls.setFlag(NoInits) + if (body forall isPureInterfaceMember) + cls.setFlag(PureInterface) + } + } } } |