Skip to content

Commit 93f1197

Browse files
committed
minimal working init calls
test/files/trait-defaults/fields compiles and runs: x y z abstract public protected abstract protected private private[this] abstract public protected abstract protected private private[this] abstract public protected abstract protected private private[this]
1 parent 5333015 commit 93f1197

File tree

3 files changed

+58
-9
lines changed

3 files changed

+58
-9
lines changed

src/compiler/scala/tools/nsc/transform/Mixin.scala

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,32 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
397397

398398
// TODO in namers: if(sym.owner.isTrait && sym.isSetter && !sym.isDeferred) sym.addAnnotation(TraitSetterAnnotationClass)
399399

400+
/** Add calls to supermixin constructors
401+
* `super[mix].$init$()`
402+
* to tree, which is assumed to be the body of a constructor of class clazz.
403+
*/
404+
private def addMixinConstructorCalls(clazz: Symbol)(tree: Tree): Tree = {
405+
def mixinConstructorCall(`trait`: Symbol): Tree = typedPos(tree.pos) {
406+
Apply(Select(This(clazz), `trait`.primaryConstructor), List())
407+
}
408+
val mixinConstructorCalls = clazz.mixinClasses.filter(_.isTrait).map(mixinConstructorCall).reverse
409+
tree match {
410+
// TODO???
411+
// case Block(Nil, expr) =>
412+
// // AnyVal constructor - have to provide a real body so the
413+
// // jvm doesn't throw a VerifyError. But we can't add the
414+
// // body until now, because the typer knows that Any has no
415+
// // constructor and won't accept a call to super.init.
416+
// assert((clazz isSubClass AnyValClass) || clazz.info.parents.isEmpty, clazz)
417+
// Block(List(Apply(gen.mkSuperInitCall, Nil)), expr)
418+
419+
case Block(stats, expr) =>
420+
// needs `hasSymbolField` check because `supercall` could be a block (named / default args)
421+
val (presuper, supercall :: rest) = stats span (t => t.hasSymbolWhich(_ hasFlag PRESUPER))
422+
treeCopy.Block(tree, presuper ::: (supercall :: mixinConstructorCalls ::: rest), expr)
423+
}
424+
}
425+
400426
/** The first transform; called in a pre-order traversal at phase mixin
401427
* (that is, every node is processed before its children).
402428
*
@@ -405,13 +431,18 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
405431
private def preTransform(tree: Tree): Tree = {
406432
val sym = tree.symbol
407433
tree match {
434+
case DefDef(_,_,_,_,_,_) if sym.isClassConstructor && sym.isPrimaryConstructor && sym.owner != ArrayClass =>
435+
deriveDefDef(tree)(addMixinConstructorCalls(sym.owner))
436+
408437
case Template(parents, self, body) if doImplementTraitMembers(currentOwner) =>
409438
localTyper = erasure.newTyper(rootContext.make(tree, currentOwner))
410439
exitingMixin(currentOwner.owner.info)//todo: needed?
411440

412441
implementTraitMembers(currentOwner, unit)
413442

414443
tree
444+
445+
415446
case _ =>
416447
tree
417448
}
@@ -964,12 +995,13 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
964995
// add superaccessors
965996
addDefDef(sym)
966997
}
967-
else {
968-
// add forwarders
969-
assert(sym.alias != NoSymbol, sym)
970-
// debuglog("New forwarder: " + sym.defString + " => " + sym.alias.defString)
971-
if (!sym.isMacro) addDefDef(sym, Apply(staticRef(sym.alias), gen.mkAttributedThis(clazz) :: sym.paramss.head.map(Ident)))
972-
}
998+
// TODO: override methods to encode linearization order
999+
// else {
1000+
// // add forwarders
1001+
// assert(sym.alias != NoSymbol, sym)
1002+
// // debuglog("New forwarder: " + sym.defString + " => " + sym.alias.defString)
1003+
// if (!sym.isMacro) addDefDef(sym, Apply(staticRef(sym.alias), gen.mkAttributedThis(clazz) :: sym.paramss.head.map(Ident)))
1004+
// }
9731005
}
9741006
}
9751007
stats1 = add(stats1, newDefs.toList)

src/reflect/scala/reflect/internal/Symbols.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3265,7 +3265,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
32653265

32663266
override def existentialBound = GenPolyType(this.typeParams, TypeBounds.upper(this.classBound))
32673267

3268-
def primaryConstructorName = if (this hasFlag TRAIT | IMPLCLASS) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR
3268+
def primaryConstructorName = if (this hasFlag TRAIT) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR
32693269

32703270
override def primaryConstructor = {
32713271
val c = info decl primaryConstructorName

test/files/trait-defaults/fields.scala

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1+
trait Empty {
2+
println("a")
3+
}
4+
5+
class CE extends Empty
6+
17
trait T {
28
val abs: String
39
protected val protabs: String
410
val pub = "public"
511
protected val prot = "protected"
612
private val privvy = "private"
713
private[this] val privateThis = "private[this]"
14+
// TODO:
15+
// final val const = "const"
816

917
trait Nested { println(abs + privateThis) }
1018

@@ -36,9 +44,18 @@ trait T {
3644
}
3745
}
3846

39-
class C extends T {
47+
class C extends AnyRef with T {
48+
println("x")
4049
val abs = "abstract"
50+
println("y")
4151
val protabs = "abstract protected"
52+
final val const = "const"
53+
println("z")
4254
}
4355

44-
object Test extends C with App
56+
object Test extends C {
57+
def main(args: Array[String]): Unit = {
58+
NO
59+
new NT{}
60+
new NC
61+
}}

0 commit comments

Comments
 (0)