Skip to content

Commit 3396862

Browse files
committed
Refactor realizability to also cache result of isStableRealizable
1 parent ceaecda commit 3396862

File tree

1 file changed

+32
-13
lines changed

1 file changed

+32
-13
lines changed

compiler/src/dotty/tools/dotc/core/CheckRealizable.scala

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -68,22 +68,41 @@ class CheckRealizable(implicit ctx: Context) {
6868
*/
6969
private def isLateInitialized(sym: Symbol) = sym.is(Lazy, butNot = Module)
7070

71-
/** The realizability status of given type `tp`*/
71+
/** The realizability status of given type `tp` */
7272
def realizability(tp: Type): Realizability = tp.dealias match {
7373
case tp: TermRef =>
74+
// Suppose tp is a.b.c.type, where c is declared with type T, then sym is c, tp.info is T and
75+
// and tp.prefix is a.b.
7476
val sym = tp.symbol
75-
val r =
76-
if (sym.is(Stable)) realizability(tp.prefix)
77-
else {
78-
val r =
79-
if (!sym.isStable) NotStable
80-
else if (!isLateInitialized(sym)) realizability(tp.prefix)
81-
else if (!sym.isEffectivelyFinal) new NotFinal(sym)
82-
else realizability(tp.info).mapError(r => new ProblemInUnderlying(tp.info, r))
83-
if (r == Realizable) sym.setFlag(Stable)
84-
r
85-
}
86-
if (r == Realizable || tp.info.isStableRealizable) Realizable else r
77+
// We know tp is realizable if either:
78+
// 1. the symbol is stable and the prefix is realizable (so that, say, it contains no vars):
79+
if (sym.is(Stable)) realizability(tp.prefix)
80+
else {
81+
// 2. if tp.info is a realizable singleton type. We check this last
82+
// for performance, in all cases where some unrelated check might have failed.
83+
def patchRealizability(r: Realizability) =
84+
r.mapError(if (tp.info.isStableRealizable) Realizable else _)
85+
val r =
86+
if (!sym.isStable)
87+
patchRealizability(NotStable)
88+
// 3. If the symbol isn't "lazy" and its prefix is realizable
89+
else if (!isLateInitialized(sym))
90+
// XXX: This is a bit fishy: we only cache that the symbol is
91+
// stable if it appears under a realizable prefix.
92+
// XXX: Add object DependsOnPrefix extends Realizability(""), but filter it out here.
93+
patchRealizability(realizability(tp.prefix))
94+
// 4. If the symbol can't be overridden, and
95+
else if (!sym.isEffectivelyFinal)
96+
patchRealizability(new NotFinal(sym))
97+
else
98+
// Since patchRealizability checks realizability(tp.info) through
99+
// isStableRealizable, using patchRealizability wouldn't make
100+
// a difference, and calling it here again might introduce
101+
// a slowdown exponential in the prefix length.
102+
realizability(tp.info).mapError(r => new ProblemInUnderlying(tp.info, r))
103+
if (r == Realizable) sym.setFlag(Stable)
104+
r
105+
}
87106
case _: SingletonType | NoPrefix =>
88107
Realizable
89108
case tp =>

0 commit comments

Comments
 (0)