From 05cb6297074c658d2b3a8577a7a70d9ecbd65d67 Mon Sep 17 00:00:00 2001
From: "Paolo G. Giarrusso" <p.giarrusso@gmail.com>
Date: Sun, 2 Dec 2018 15:06:33 +0100
Subject: [PATCH 1/4] Show that Any#L is still rejected when written by the
 user

This tests that b3dd07cc068d4ad6f74ba4321b325170653d3cb6 is not *too* liberal.
---
 tests/neg/i4031-anysel.scala | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 tests/neg/i4031-anysel.scala

diff --git a/tests/neg/i4031-anysel.scala b/tests/neg/i4031-anysel.scala
new file mode 100644
index 000000000000..c97209733375
--- /dev/null
+++ b/tests/neg/i4031-anysel.scala
@@ -0,0 +1,3 @@
+object Test {
+  val v: Any = 1: Any#L // error
+}

From 632f79269f6a0fcb53d6941fe2214154b72707e2 Mon Sep 17 00:00:00 2001
From: "Paolo G. Giarrusso" <p.giarrusso@gmail.com>
Date: Wed, 16 Jan 2019 16:24:34 +0100
Subject: [PATCH 2/4] Singletons of mutable vars with singleton types are
 realizable

Such a "variable" can only have one value, so this is okay.

This goes back to 9125f580d44462fbb0f81ce8cdd7344e5cee51d1.
---
 .../src/dotty/tools/dotc/core/CheckRealizable.scala |  5 ++++-
 tests/pos/realizable-mut.scala                      | 13 +++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)
 create mode 100644 tests/pos/realizable-mut.scala

diff --git a/compiler/src/dotty/tools/dotc/core/CheckRealizable.scala b/compiler/src/dotty/tools/dotc/core/CheckRealizable.scala
index 57dc1bcb5af9..6c6716bb1af3 100644
--- a/compiler/src/dotty/tools/dotc/core/CheckRealizable.scala
+++ b/compiler/src/dotty/tools/dotc/core/CheckRealizable.scala
@@ -68,6 +68,7 @@ class CheckRealizable(implicit ctx: Context) {
   def realizability(tp: Type): Realizability = tp.dealias match {
     case tp: TermRef =>
       val sym = tp.symbol
+      lazy val tpInfoRealizable = realizability(tp.info)
       if (sym.is(Stable)) realizability(tp.prefix)
       else {
         val r =
@@ -80,10 +81,12 @@ class CheckRealizable(implicit ctx: Context) {
           else
             // otherwise we need to look at the info to determine realizability
             // roughly: it's realizable if the info does not have bad bounds
-            realizability(tp.info).mapError(r => new ProblemInUnderlying(tp, r))
+            tpInfoRealizable.mapError(r => new ProblemInUnderlying(tp, r))
         r andAlso {
           if (sym.isStable) sym.setFlag(Stable) // it's known to be stable and realizable
           realizability(tp.prefix)
+        } mapError { r =>
+          if (tp.info.isStable && tpInfoRealizable == Realizable) Realizable else r
         }
       }
     case _: SingletonType | NoPrefix =>
diff --git a/tests/pos/realizable-mut.scala b/tests/pos/realizable-mut.scala
new file mode 100644
index 000000000000..599fbd90cd47
--- /dev/null
+++ b/tests/pos/realizable-mut.scala
@@ -0,0 +1,13 @@
+object Foo {
+  val x = new Object
+
+  class A(var y: x.type)
+
+  val a = new A(x)
+
+  val y: a.y.type = x
+// 1 |val y: a.y.type = x
+//   |         ^
+//   |         Object(x)(a.y) is not a legal path
+//   |         since it refers to nonfinal variable y
+}

From d3ac612bc245b614953b69732a06da1e03e56758 Mon Sep 17 00:00:00 2001
From: "Paolo G. Giarrusso" <p.giarrusso@gmail.com>
Date: Tue, 10 Apr 2018 20:54:03 +0200
Subject: [PATCH 3/4] Add stress-test for realizability checking

I wrote this because I feared (incorrectly) exponential slowdowns in
realizability checking for this code. But debugging suggests that the
complexity of realizability checking is constant in the size of these
expressions (even after I disable caching of `Stable`).

Beware 1: these expressions almost smash the stack by sheer size.

Beware 2: this fails with `-Yno-deep-subtypes`, but simply because the checking
heuristics assumes people don't try to do this.

Beware 3: this also depends on unstable members with singletons types being
stable.
---
 tests/pos-deep-subtype/i4036.scala | 64 ++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 tests/pos-deep-subtype/i4036.scala

diff --git a/tests/pos-deep-subtype/i4036.scala b/tests/pos-deep-subtype/i4036.scala
new file mode 100644
index 000000000000..df06ad9b3b3c
--- /dev/null
+++ b/tests/pos-deep-subtype/i4036.scala
@@ -0,0 +1,64 @@
+trait A { def x: this.type = this; type T }
+trait B { def y: this.type = this; def x: y.type = y; type T }
+object A {
+  val v = new A { type T = Int }
+  v: v.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.type
+
+  1: v.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.T
+
+  val u = new B { type T = Int }
+  u: u.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
+    x.type
+
+  val z = new B { type T = this.type }
+  z: z.T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
+    T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T
+}

From 0ee31f4e6f3c654b1aa2bf230aa31b91784fe2b5 Mon Sep 17 00:00:00 2001
From: "Paolo G. Giarrusso" <p.giarrusso@gmail.com>
Date: Thu, 17 Jan 2019 01:10:40 +0100
Subject: [PATCH 4/4] Stop stack overflows in testing

Stack consumption grew apparently.
---
 tests/pos-deep-subtype/i4036.scala | 2 --
 1 file changed, 2 deletions(-)

diff --git a/tests/pos-deep-subtype/i4036.scala b/tests/pos-deep-subtype/i4036.scala
index df06ad9b3b3c..1784a9189fab 100644
--- a/tests/pos-deep-subtype/i4036.scala
+++ b/tests/pos-deep-subtype/i4036.scala
@@ -14,7 +14,6 @@ object A {
     x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
     x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
     x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
-    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
     x.type
 
   1: v.
@@ -29,7 +28,6 @@ object A {
     x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
     x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
     x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
-    x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
     x.T
 
   val u = new B { type T = Int }