@@ -68,22 +68,41 @@ class CheckRealizable(implicit ctx: Context) {
68
68
*/
69
69
private def isLateInitialized (sym : Symbol ) = sym.is(Lazy , butNot = Module )
70
70
71
- /** The realizability status of given type `tp`*/
71
+ /** The realizability status of given type `tp` */
72
72
def realizability (tp : Type ): Realizability = tp.dealias match {
73
73
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.
74
76
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
+ }
87
106
case _ : SingletonType | NoPrefix =>
88
107
Realizable
89
108
case tp =>
0 commit comments