Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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.
  • Loading branch information...
commit fd6125428af90b02cb8969a53586f3551e275b0f 1 parent ee24807
@retronym retronym authored
View
9 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
View
2  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$.<init> by accounting for nesting in Namer#inConstructorFlag
+ locally(HasX.x)
// locally(Early.x) TODO sort out VerifyError in Early$.<init>
// DoubleOk TODO sort out VerifyError in DoubleOk$.<init>
}
View
8 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)
+}
View
16 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;
+ ()
+ };
+}
View
8 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
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.