aboutsummaryrefslogtreecommitdiff
path: root/tests/pending/run/outertest.scala
blob: edeac9f62645e32c96af8bf07f927564f029f486 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// A test for the case where the outer field of class B#J should be eliminated.

import reflect.ClassTag

abstract class A {
  abstract class I

  val foo = this
}

class B extends A {
  class J extends I {
    val bar = foo
  }

  type II = I
  class K extends II {
    val bar = foo
  }

  class L extends (I @annotation.tailrec) {
    val bar = foo
  }
}


class C extends A {
  val c: C = this

  class M extends c.I {
    val bar = foo
  }
}


object Test extends dotty.runtime.LegacyApp {
  val b = new B
  val c0 = new C
  val c = new C {
// TODO NEEDS MANUAL CHANGE (early initializers)
// BEGIN copied early initializers
override val c = c0
// END copied early initializers
}

  assert((new b.J).bar eq b)
  assert((new b.K).bar eq b)
  assert((new b.L).bar eq b)
  assert((new c.M).bar eq c)

  def checkOuterFields[C: ClassTag](expected: Int): Unit = {
    val cls = implicitly[ClassTag[C]].runtimeClass
    val outerFields = cls.getDeclaredFields().filter(_.getName.contains("$outer"))
    assert(outerFields.size == expected, outerFields.map(_.getName))
  }

  checkOuterFields[A#I](1) // the base class must have the $outer pointer
  checkOuterFields[B#J](0) // reuse parent class' $outer pointer
  checkOuterFields[B#K](0) // ... through an alias
  checkOuterFields[B#L](0) // ... through the annotated type
  checkOuterFields[C#M](1) // different prefix, can't share.
}