From 7375f8e013ced92c6280c551af1c707122cc53f7 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Thu, 8 May 2014 11:05:33 +0200 Subject: Fix run/t3569.scala under checkinit --- test/files/run/t3569.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 } } -- cgit v1.2.3 From 908ccd9feea072b4ed249db5f2741f745b42ca75 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Thu, 8 May 2014 11:11:09 +0200 Subject: Fix run/t5256h.scala under checkinit --- test/files/run/t5256h.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 } -- cgit v1.2.3 From f0c33206bc125cf4326a340e2cd7c7ec2f360726 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 9 May 2014 16:47:56 +0200 Subject: SI-8570 set the checkinit bit for unit-typed fields of traits Fix only, refactoring in subsequent commit. --- src/compiler/scala/tools/nsc/transform/Mixin.scala | 9 ++++++--- test/files/run/t8570.flags | 1 + test/files/run/t8570.scala | 10 ++++++++++ test/files/run/t8570a.check | 1 + test/files/run/t8570a.flags | 1 + test/files/run/t8570a.scala | 14 ++++++++++++++ 6 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 test/files/run/t8570.flags create mode 100644 test/files/run/t8570.scala create mode 100644 test/files/run/t8570a.check create mode 100644 test/files/run/t8570a.flags create mode 100644 test/files/run/t8570a.scala diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 673bc04bd9..9c9008bfcc 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -1042,15 +1042,18 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { // add accessor definitions addDefDef(sym, { if (sym.isSetter) { + val getter = sym.getter(clazz) + def setInitFlag = mkSetFlag(clazz, fieldOffset(getter), getter, bitmapKind(getter)) if (isOverriddenSetter(sym)) UNIT else accessedRef match { - case ref @ Literal(_) => ref + case ref @ Literal(_) => + if (!needsInitFlag(getter)) ref + else Block(setInitFlag, 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 Block(init, setInitFlag, UNIT) } } else if (needsInitFlag(sym)) 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) + } +} -- cgit v1.2.3 From 63321ac39651fd8493a821e3da5cea36d7ce2b3c Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 9 May 2014 11:31:21 +0200 Subject: Clarify and clean up trait getter / setter generation --- src/compiler/scala/tools/nsc/transform/Mixin.scala | 89 +++++++++++++--------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 9c9008bfcc..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,30 +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) { - val getter = sym.getter(clazz) - def setInitFlag = mkSetFlag(clazz, fieldOffset(getter), getter, bitmapKind(getter)) + // 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(_) => - if (!needsInitFlag(getter)) ref - else Block(setInitFlag, ref) - case ref => - val init = Assign(ref, Ident(sym.firstParam)) - - if (!needsInitFlag(getter)) init - else Block(init, setInitFlag, 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)) { -- cgit v1.2.3 From f0846e74dbce99ae1d8e2f1d7e5faeadc2a5c375 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 9 May 2014 11:40:04 +0200 Subject: Disable run/t7974 under checkinit --- test/files/run/t7974.flags | 1 + test/files/run/t7974/Test.scala | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 test/files/run/t7974.flags 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') -- cgit v1.2.3