From fd6125428af90b02cb8969a53586f3551e275b0f Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 28 Jan 2013 09:10:37 +0100 Subject: SI-6666 Account for nesting in setting INCONSTRUCTOR This flag is calcualed in Namers, and assigned to class and module class symbols that are defined in self/super-calls, and in early definitions. For example, class D is INCONSTRUCTOR in each case below: class C extends Super({class D; ()}) class C(a: Any) { def this(a: Any) = this({class D; ()}) } new { val x = { class D; () } with Super(()) But, the calculation of this flag failed to account for nesting, so it was not set in cases like: class C(a: Any) { def this(a: Any) = this({val x = {class D; ()}; x}) } This patch searches the enclosing context chain, rather than just the immediate context. The search is terminated at the first non term-owned context. In the following example, this avoids marking `E` as INCONSTRUCTOR; only `D` should be. class C extends Super({class D { class E }; ()}) This closes SI-6259 and SI-6506, and fixes one problem in the recently reopened SI-6957. --- src/compiler/scala/tools/nsc/typechecker/Namers.scala | 9 ++++++--- test/files/run/t6259.scala | 2 +- test/files/run/t6506.scala | 8 ++++++++ test/files/run/t6666a.scala | 16 ++++++++++++++++ test/files/run/t6957.scala | 8 ++++++++ 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 test/files/run/t6506.scala create mode 100644 test/files/run/t6666a.scala create mode 100644 test/files/run/t6957.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 98b6264051..967a3214f2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -123,9 +123,12 @@ trait Namers extends MethodSynthesis { def setPrivateWithin(tree: MemberDef, sym: Symbol): Symbol = setPrivateWithin(tree, sym, tree.mods) - def inConstructorFlag: Long = - if (owner.isConstructor && !context.inConstructorSuffix || owner.isEarlyInitialized) INCONSTRUCTOR - else 0l + def inConstructorFlag: Long = { + val termOwnedContexts: List[Context] = context.enclosingContextChain.takeWhile(_.owner.isTerm) + val constructorNonSuffix = termOwnedContexts exists (c => c.owner.isConstructor && !c.inConstructorSuffix) + val earlyInit = termOwnedContexts exists (_.owner.isEarlyInitialized) + if (constructorNonSuffix || earlyInit) INCONSTRUCTOR else 0L + } def moduleClassFlags(moduleFlags: Long) = (moduleFlags & ModuleToClassFlags) | inConstructorFlag diff --git a/test/files/run/t6259.scala b/test/files/run/t6259.scala index a5a7bf9043..294c95e96b 100644 --- a/test/files/run/t6259.scala +++ b/test/files/run/t6259.scala @@ -48,7 +48,7 @@ object Test extends App { val e = new E {}; e.F val g = new G; g.H - //locally(HasX.x) TODO sort out VerifyError in HasX$InVal$2$. by accounting for nesting in Namer#inConstructorFlag + locally(HasX.x) // locally(Early.x) TODO sort out VerifyError in Early$. // DoubleOk TODO sort out VerifyError in DoubleOk$. } diff --git a/test/files/run/t6506.scala b/test/files/run/t6506.scala new file mode 100644 index 0000000000..04d77c3c16 --- /dev/null +++ b/test/files/run/t6506.scala @@ -0,0 +1,8 @@ +object Test { + def main(args: Array[String]) { + new WL(new {} #:: S) with T + } + object S { def #::(a: Any): Any = () } + trait T + class WL(a: Any) +} diff --git a/test/files/run/t6666a.scala b/test/files/run/t6666a.scala new file mode 100644 index 0000000000..1d208a32e7 --- /dev/null +++ b/test/files/run/t6666a.scala @@ -0,0 +1,16 @@ +class A(a: Any) + +object Test { + def main(args: Array[String]): Unit = { + } + + val x: Unit = { + object InVal extends A({ + new {} // okay + val o = {new {}} // nesting triggers a VerifyError. + null + }); + InVal; + () + }; +} diff --git a/test/files/run/t6957.scala b/test/files/run/t6957.scala new file mode 100644 index 0000000000..d0bf8e7b5e --- /dev/null +++ b/test/files/run/t6957.scala @@ -0,0 +1,8 @@ +object Test { + def main(args: Array[String]) { + class Foo + class Parent(f:Foo) + class Child extends Parent({val x=new Foo{}; x}) + new Child + } +} -- cgit v1.2.3