Skip to content

Commit 540479a

Browse files
oderskyDarkDimius
authored andcommitted
Clean up code relating to interfaces.
Previous implementation was confused about the meaning of interface (with default methods or without?). Now instead of Interface/JavaInterface we have PureInterface - all members are abstract methods NoInits - all members are methods
1 parent 18cd0dd commit 540479a

File tree

10 files changed

+43
-26
lines changed

10 files changed

+43
-26
lines changed

src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,18 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
2626

2727
/** Is tree legal as a member definition of an interface?
2828
*/
29-
def isInterfaceMember(tree: Tree): Boolean = unsplice(tree) match {
30-
case EmptyTree => true
31-
case Import(_, _) => true
32-
case TypeDef(_, _, _) => true
33-
case DefDef(mods, _, _, _, _, __) => mods.flags is Deferred
34-
case ValDef(mods, _, _, _) => mods is Deferred
29+
def isPureInterfaceMember(tree: Tree): Boolean = unsplice(tree) match {
30+
case EmptyTree | Import(_, _) | TypeDef(_, _, _) => true
31+
case DefDef(_, _, _, _, _, rhs) => rhs.isEmpty
32+
case ValDef(mods, _, _, rhs) => rhs.isEmpty
3533
case _ => false
3634
}
3735

36+
/** Is tree legal as a member definition of a no-init trait?
37+
*/
38+
def isNoInitMember(tree: Tree): Boolean =
39+
isPureInterfaceMember(tree) || unsplice(tree).isInstanceOf[DefDef]
40+
3841
def isOpAssign(tree: Tree) = unsplice(tree) match {
3942
case Apply(fn, _ :: Nil) =>
4043
unsplice(fn) match {

src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ class Definitions {
191191
lazy val ScalaStaticsClass = ScalaStaticsModule.moduleClass.asClass
192192

193193
def staticsMethod(name: PreName) = ctx.requiredMethod(ScalaStaticsClass, name)
194-
194+
195195
lazy val DottyPredefModule = ctx.requiredModule("dotty.DottyPredef")
196196
lazy val NilModule = ctx.requiredModule("scala.collection.immutable.Nil")
197197
lazy val PredefConformsClass = ctx.requiredClass("scala.Predef." + tpnme.Conforms)
@@ -201,7 +201,7 @@ class Definitions {
201201
// needed as a synthetic class because Scala 2.x refers to it in classfiles
202202
// but does not define it as an explicit class.
203203
newCompleteClassSymbol(
204-
ScalaPackageClass, tpnme.Singleton, Trait | Interface | Final,
204+
ScalaPackageClass, tpnme.Singleton, PureInterfaceCreationFlags | Final,
205205
List(AnyClass.typeRef), EmptyScope)
206206
lazy val SeqClass: ClassSymbol = ctx.requiredClass("scala.collection.Seq")
207207
lazy val Seq_apply = ctx.requiredMethod(SeqClass, nme.apply)
@@ -506,7 +506,7 @@ class Definitions {
506506
val cls = newClassSymbol(
507507
ScalaPackageClass,
508508
traitName,
509-
Trait | Interface | Synthetic,
509+
PureInterfaceCreationFlags | Synthetic,
510510
completer)
511511
myLambdaTraits += cls
512512
cls

src/dotty/tools/dotc/core/Flags.scala

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ object Flags {
287287
/** A trait that has only abstract methods as members
288288
* (and therefore can be represented by a Java interface
289289
*/
290-
final val Interface = typeFlag(22, "interface")
290+
final val PureInterface = typeFlag(22, "interface")
291291

292292
/** Labeled with of abstract & override */
293293
final val AbsOverride = termFlag(22, "abstract override")
@@ -335,6 +335,9 @@ object Flags {
335335
final val JavaStaticTerm = JavaStatic.toTermFlags
336336
final val JavaStaticType = JavaStatic.toTypeFlags
337337

338+
/** Trait is not an interface, but does not have fields or intialization code */
339+
final val NoInits = typeFlag(32, "<noInits>")
340+
338341
/** Variable is accessed from nested function. */
339342
final val Captured = termFlag(32, "<captured>")
340343

@@ -353,9 +356,6 @@ object Flags {
353356
/** Symbol is a Java-style varargs method */
354357
final val JavaVarargs = termFlag(37, "<varargs>")
355358

356-
/** Symbol is a Java default method */
357-
final val DefaultMethod = termFlag(38, "<defaultmethod>")
358-
359359
// Flags following this one are not pickled
360360

361361
/** Symbol always defines a fresh named type */
@@ -464,6 +464,9 @@ object Flags {
464464
/** Accessors always have these flags set */
465465
final val AccessorCreationFlags = Method | Accessor
466466

467+
/** Pure interfaces always have these flags */
468+
final val PureInterfaceCreationFlags = Trait | NoInits | PureInterface
469+
467470
/** The flags of the self symbol */
468471
final val SelfSymFlags = Private | Local | Deferred
469472

@@ -539,8 +542,11 @@ object Flags {
539542
/** Is a default parameter in Scala 2*/
540543
final val DefaultParameter = allOf(Param, DefaultParameterized)
541544

542-
/** A Java interface */
543-
final val JavaInterface = allOf(JavaDefined, Trait)
545+
/** A trait that does not need to be initialized */
546+
final val NoInitsTrait = allOf(Trait, NoInits)
547+
548+
/** A Java interface, potentially with default methods */
549+
final val JavaTrait = allOf(JavaDefined, Trait, NoInits)
544550

545551
/** A Java companion object */
546552
final val JavaModule = allOf(JavaDefined, Module)

src/dotty/tools/dotc/core/pickling/ClassfileConstants.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ object ClassfileConstants {
345345
case JAVA_ACC_SYNTHETIC => Synthetic
346346
case JAVA_ACC_STATIC => JavaStatic
347347
case JAVA_ACC_ABSTRACT => if (isAnnotation) EmptyFlags else if (isClass) Abstract else Deferred
348-
case JAVA_ACC_INTERFACE => if (isAnnotation) EmptyFlags else JavaInterface
348+
case JAVA_ACC_INTERFACE => if (isAnnotation) EmptyFlags else PureInterfaceCreationFlags | JavaDefined
349349
case _ => EmptyFlags
350350
}
351351

src/dotty/tools/dotc/core/pickling/ClassfileParser.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -503,8 +503,9 @@ class ClassfileParser(
503503
parseExceptions(attrLen)
504504

505505
case tpnme.CodeATTR =>
506-
if (sym.owner is Flags.Interface) {
507-
sym.setFlag(Flags.DefaultMethod)
506+
if (sym.owner is Flags.JavaTrait) {
507+
sym.resetFlag(Flags.Deferred)
508+
sym.owner.resetFlag(Flags.PureInterface)
508509
ctx.log(s"$sym in ${sym.owner} is a java8+ default method.")
509510
}
510511
in.skip(attrLen)

src/dotty/tools/dotc/core/pickling/PickleBuffer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ object PickleBuffer {
220220
DEFERRED_PKL -> Deferred,
221221
FINAL_PKL -> Final,
222222
METHOD_PKL -> Method,
223-
INTERFACE_PKL -> Interface,
223+
INTERFACE_PKL -> PureInterface,
224224
MODULE_PKL -> Module,
225225
IMPLICIT_PKL -> Implicit,
226226
SEALED_PKL -> Sealed,

src/dotty/tools/dotc/printing/PlainPrinter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
296296
/** String representation of symbol's definition key word */
297297
protected def keyString(sym: Symbol): String = {
298298
val flags = sym.flagsUNSAFE
299-
if (flags is JavaInterface) "interface"
299+
if (flags is JavaTrait) "interface"
300300
else if ((flags is Trait) && !(flags is ImplClass)) "trait"
301301
else if (sym.isClass) "class"
302302
else if (sym.isType) "type"

src/dotty/tools/dotc/transform/ExplicitOuter.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,11 @@ object ExplicitOuter {
144144
nme.OUTER.expandedName(cls)
145145

146146
/** Class needs an outer pointer, provided there is a reference to an outer this in it. */
147-
def needsOuterIfReferenced(cls: ClassSymbol)(implicit ctx: Context): Boolean = !(
148-
cls.isStatic ||
149-
cls.owner.enclosingClass.isStaticOwner ||
150-
cls.is(Interface)
151-
)
147+
def needsOuterIfReferenced(cls: ClassSymbol)(implicit ctx: Context): Boolean =
148+
!(cls.isStatic ||
149+
cls.owner.enclosingClass.isStaticOwner ||
150+
cls.is(PureInterface)
151+
)
152152

153153
/** Class unconditionally needs an outer pointer. This is the case if
154154
* the class needs an outer pointer if referenced and one of the following holds:

src/dotty/tools/dotc/transform/Mixin.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
134134
case Some(call) =>
135135
if (defn.PhantomClasses.contains(baseCls)) Nil else call :: Nil
136136
case None =>
137-
if (baseCls.is(Interface) || defn.PhantomClasses.contains(baseCls)) Nil
137+
if (baseCls.is(NoInitsTrait) || defn.PhantomClasses.contains(baseCls)) Nil
138138
else {
139139
//println(i"synth super call ${baseCls.primaryConstructor}: ${baseCls.primaryConstructor.info}")
140140
superRef(baseCls.primaryConstructor).appliedToNone :: Nil

src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,13 @@ class Namer { typer: Typer =>
492492

493493
index(rest)(inClassContext(selfInfo))
494494
denot.info = ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfInfo)
495+
if (cls is Trait) {
496+
if (body forall isNoInitMember) {
497+
cls.setFlag(NoInits)
498+
if (body forall isPureInterfaceMember)
499+
cls.setFlag(PureInterface)
500+
}
501+
}
495502
}
496503
}
497504

0 commit comments

Comments
 (0)