summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-05-09 21:16:42 +0200
committerJason Zaugg <jzaugg@gmail.com>2014-05-09 21:16:42 +0200
commitd079e769b9372daae8d7770c4156f85ea1af6621 (patch)
tree07f672cc54501b0eee17b5ab812738679c1009eb
parent7289a263475a3c789df35e999931902acf08c0d5 (diff)
parentf0846e74dbce99ae1d8e2f1d7e5faeadc2a5c375 (diff)
downloadscala-d079e769b9372daae8d7770c4156f85ea1af6621.tar.gz
scala-d079e769b9372daae8d7770c4156f85ea1af6621.tar.bz2
scala-d079e769b9372daae8d7770c4156f85ea1af6621.zip
Merge pull request #3730 from lrytz/checkinit
Fix checkinit build
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala86
-rw-r--r--test/files/run/t3569.scala3
-rw-r--r--test/files/run/t5256h.scala3
-rw-r--r--test/files/run/t7974.flags1
-rw-r--r--test/files/run/t7974/Test.scala2
-rw-r--r--test/files/run/t8570.flags1
-rw-r--r--test/files/run/t8570.scala10
-rw-r--r--test/files/run/t8570a.check1
-rw-r--r--test/files/run/t8570a.flags1
-rw-r--r--test/files/run/t8570a.scala14
10 files changed, 87 insertions, 35 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 673bc04bd9..33e8e47c76 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -1004,24 +1004,56 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
buildBitmapOffsets()
var stats1 = addCheckedGetters(clazz, stats)
- def accessedReference(sym: Symbol) = sym.tpe match {
- case MethodType(Nil, ConstantType(c)) => Literal(c)
- case _ =>
- // if it is a mixed-in lazy value, complete the accessor
- if (sym.isLazy && sym.isGetter) {
- val isUnit = sym.tpe.resultType.typeSymbol == UnitClass
- val initCall = Apply(staticRef(initializer(sym)), gen.mkAttributedThis(clazz) :: Nil)
- val selection = Select(This(clazz), sym.accessed)
- val init = if (isUnit) initCall else atPos(sym.pos)(Assign(selection, initCall))
- val returns = if (isUnit) UNIT else selection
-
- mkLazyDef(clazz, sym, List(init), returns, fieldOffset(sym))
- }
- else sym.getter(sym.owner).tpe.resultType.typeSymbol match {
- case UnitClass => UNIT
- case _ => Select(This(clazz), sym.accessed)
- }
+ def getterBody(getter: Symbol) = {
+ assert(getter.isGetter)
+ val readValue = getter.tpe match {
+ // A field "final val f = const" in a trait generates a getter with a ConstantType.
+ case MethodType(Nil, ConstantType(c)) =>
+ Literal(c)
+ case _ =>
+ // if it is a mixed-in lazy value, complete the accessor
+ if (getter.isLazy) {
+ val isUnit = isUnitGetter(getter)
+ val initCall = Apply(staticRef(initializer(getter)), gen.mkAttributedThis(clazz) :: Nil)
+ val selection = fieldAccess(getter)
+ val init = if (isUnit) initCall else atPos(getter.pos)(Assign(selection, initCall))
+ val returns = if (isUnit) UNIT else selection
+ mkLazyDef(clazz, getter, List(init), returns, fieldOffset(getter))
+ }
+ // For a field of type Unit in a trait, no actual field is generated when being mixed in.
+ else if (isUnitGetter(getter)) UNIT
+ else fieldAccess(getter)
+ }
+ if (!needsInitFlag(getter)) readValue
+ else mkCheckedAccessor(clazz, readValue, fieldOffset(getter), getter.pos, getter)
+ }
+
+ def setterBody(setter: Symbol) = {
+ val getter = setter.getterIn(clazz)
+
+ // A trait with a field of type Unit creates a trait setter (invoked by the
+ // implementation class constructor), like for any other trait field.
+ // However, no actual field is created in the class that mixes in the trait.
+ // Therefore the setter does nothing (except setting the -Xcheckinit flag).
+
+ val setInitFlag =
+ if (!needsInitFlag(getter)) Nil
+ else List(mkSetFlag(clazz, fieldOffset(getter), getter, bitmapKind(getter)))
+
+ val fieldInitializer =
+ if (isUnitGetter(getter)) Nil
+ else List(Assign(fieldAccess(setter), Ident(setter.firstParam)))
+
+ (fieldInitializer ::: setInitFlag) match {
+ case Nil => UNIT
+ // If there's only one statement, the Block factory does not actually create a Block.
+ case stats => Block(stats: _*)
+ }
}
+
+ def isUnitGetter(getter: Symbol) = getter.tpe.resultType.typeSymbol == UnitClass
+ def fieldAccess(accessor: Symbol) = Select(This(clazz), accessor.accessed)
+
def isOverriddenSetter(sym: Symbol) =
nme.isTraitSetterName(sym.name) && {
val other = sym.nextOverriddenSymbol
@@ -1036,27 +1068,17 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
}
// if class is not a trait add accessor definitions
else if (!clazz.isTrait) {
- // This needs to be a def to avoid sharing trees
- def accessedRef = accessedReference(sym)
if (isConcreteAccessor(sym)) {
// add accessor definitions
addDefDef(sym, {
if (sym.isSetter) {
+ // If this is a setter of a mixed-in field which is overridden by another mixin,
+ // the trait setter of the overridden one does not need to do anything - the
+ // trait setter of the overriding field will initialize the field.
if (isOverriddenSetter(sym)) UNIT
- else accessedRef match {
- case ref @ Literal(_) => ref
- case ref =>
- val init = Assign(ref, Ident(sym.firstParam))
- val getter = sym.getter(clazz)
-
- if (!needsInitFlag(getter)) init
- else Block(init, mkSetFlag(clazz, fieldOffset(getter), getter, bitmapKind(getter)), UNIT)
- }
+ else setterBody(sym)
}
- else if (needsInitFlag(sym))
- mkCheckedAccessor(clazz, accessedRef, fieldOffset(sym), sym.pos, sym)
- else
- accessedRef
+ else getterBody(sym)
})
}
else if (sym.isModule && !(sym hasFlag LIFTED | BRIDGE)) {
diff --git a/test/files/run/t3569.scala b/test/files/run/t3569.scala
index 91d437e0e3..eb3b424439 100644
--- a/test/files/run/t3569.scala
+++ b/test/files/run/t3569.scala
@@ -26,7 +26,8 @@ object Test {
s.x += 1
println(s.x)
- (classOf[X].getDeclaredFields map ("" + _)).sorted foreach println
+ // under -Xcheckinit there's an additional $init$ field
+ (classOf[X].getDeclaredFields map ("" + _)).sorted.filter(_ != "private volatile byte Test$X.bitmap$init$0") foreach println
(classOf[Y].getDeclaredFields map ("" + _)).sorted foreach println
}
}
diff --git a/test/files/run/t5256h.scala b/test/files/run/t5256h.scala
index f58aa6dbe7..435124a469 100644
--- a/test/files/run/t5256h.scala
+++ b/test/files/run/t5256h.scala
@@ -6,5 +6,6 @@ object Test extends App {
val c = cm.classSymbol(mutant.getClass)
println(c)
println(c.fullName)
- println(c.info)
+ // under -Xcheckinit there's an additional $init$ field
+ c.info.toString.lines.filter(_ != " private var bitmap$init$0: Boolean") foreach println
}
diff --git a/test/files/run/t7974.flags b/test/files/run/t7974.flags
new file mode 100644
index 0000000000..5fc2a03894
--- /dev/null
+++ b/test/files/run/t7974.flags
@@ -0,0 +1 @@
+-Xcheckinit:false
diff --git a/test/files/run/t7974/Test.scala b/test/files/run/t7974/Test.scala
index 9403ea332b..433d9061a7 100644
--- a/test/files/run/t7974/Test.scala
+++ b/test/files/run/t7974/Test.scala
@@ -9,7 +9,7 @@ object Test extends BytecodeTest {
val classNode = loadClassNode("Symbols", skipDebugInfo = false)
val textifier = new Textifier
classNode.accept(new TraceClassVisitor(null, textifier, null))
-
+
val classString = stringFromWriter(w => textifier.print(w))
val result =
classString.split('\n')
diff --git a/test/files/run/t8570.flags b/test/files/run/t8570.flags
new file mode 100644
index 0000000000..3d1ee4760a
--- /dev/null
+++ b/test/files/run/t8570.flags
@@ -0,0 +1 @@
+-Xcheckinit
diff --git a/test/files/run/t8570.scala b/test/files/run/t8570.scala
new file mode 100644
index 0000000000..bbe83e9080
--- /dev/null
+++ b/test/files/run/t8570.scala
@@ -0,0 +1,10 @@
+trait Trait40_1 {
+ val value37_2 = ()
+ def run = { value37_2 }
+}
+
+object Test {
+ def main(args: Array[String]) {
+ (new Trait40_1 {}).run
+ }
+}
diff --git a/test/files/run/t8570a.check b/test/files/run/t8570a.check
new file mode 100644
index 0000000000..6a452c185a
--- /dev/null
+++ b/test/files/run/t8570a.check
@@ -0,0 +1 @@
+()
diff --git a/test/files/run/t8570a.flags b/test/files/run/t8570a.flags
new file mode 100644
index 0000000000..3d1ee4760a
--- /dev/null
+++ b/test/files/run/t8570a.flags
@@ -0,0 +1 @@
+-Xcheckinit
diff --git a/test/files/run/t8570a.scala b/test/files/run/t8570a.scala
new file mode 100644
index 0000000000..ef116e2a8a
--- /dev/null
+++ b/test/files/run/t8570a.scala
@@ -0,0 +1,14 @@
+trait Trait40_1 {
+ val value37_2 = ()
+ def run = { value37_2 }
+}
+
+trait T1 extends Trait40_1 {
+ override val value37_2 = ()
+}
+
+object Test {
+ def main(args: Array[String]) {
+ println((new T1 {}).run)
+ }
+}