@@ -27,25 +27,18 @@ object CacheAliasImplicits {
27
27
* is cached. It applies to all alias implicits that have neither type parameters
28
28
* nor a given clause. Example: The alias
29
29
*
30
- * implicit a for TC = rhs
30
+ * given a as TC = rhs
31
31
*
32
- * is expanded before this phase
32
+ * is expanded before this phase to:
33
33
*
34
34
* implicit def a: TC = rhs
35
35
*
36
36
* It is then expanded further as follows:
37
37
*
38
- * 1. If `rhs` is a simple name `x` (possibly with a `this.` prefix), leave the definition as is.
39
- * 2. Otherwise, if `rhs` is a pure path, replace the definition with
38
+ * 1. If `rhs` is a simple name `x` (possibly with a `this.` prefix) that
39
+ * refers to a value, leave it as is.
40
40
*
41
- * implicit val a: TC = rhs
42
- *
43
- * 3. Otherwise, if `TC` is a reference type, replace the definition with
44
- *
45
- * private[this] var a$_cache: TC = null
46
- * implicit def a: TC = { if (a$_cache == null) a$_cache = rhs; a$_cache }
47
- *
48
- * 4. Otherwise `TC` is a value type. Replace the definition with
41
+ * 2. Otherwise, replace the definition with
49
42
*
50
43
* lazy implicit val a: TC = rhs
51
44
*/
@@ -56,47 +49,26 @@ class CacheAliasImplicits extends MiniPhase with IdentityDenotTransformer { this
56
49
57
50
override def transformDefDef (tree : DefDef )(implicit ctx : Context ): Tree = {
58
51
val sym = tree.symbol
59
- sym.info match {
60
- case ExprType (rhsType) if sym.is(Given , butNot = CacheAliasImplicits .NoCacheFlags ) =>
61
- // If rhs is a simple TermRef, leave a def.
62
- tree.rhs.tpe match {
63
- case TermRef (pre, _) =>
64
- pre match {
65
- case NoPrefix => return tree
66
- case pre : ThisType if pre.cls == ctx.owner.enclosingClass => return tree
67
- case _ =>
68
- }
69
- case _ =>
52
+ val rhsType = tree.rhs.tpe
53
+ val isCached = sym.info match {
54
+ case _ : ExprType if sym.is(Given , butNot = CacheAliasImplicits .NoCacheFlags ) =>
55
+ rhsType match {
56
+ case TermRef (NoPrefix , _)
57
+ if rhsType.isStable => false
58
+ case TermRef (pre : ThisType , _)
59
+ if rhsType.isStable && pre.cls == sym.owner.enclosingClass => false
60
+ case _ => true
70
61
}
71
- def makeVal (additionalFlags : FlagSet ) = {
72
- sym.copySymDenotation(
73
- initFlags = sym.flags &~ Method | additionalFlags,
74
- info = rhsType)
75
- .installAfter(thisPhase)
76
- cpy.ValDef (tree)(tree.name, tree.tpt, tree.rhs)
77
- }
78
- if (isPurePath(tree.rhs)) makeVal(EmptyFlags )
79
- else if (rhsType.classSymbol.isValueClass ||
80
- ! erasure(rhsType).typeSymbol.derivesFrom(defn.ObjectClass )) makeVal(Lazy )
81
- else {
82
- val cacheFlags = if (ctx.owner.isClass) Private | Local | Mutable else Mutable
83
- val cacheSym =
84
- ctx.newSymbol(ctx.owner, CacheName (tree.name), cacheFlags, rhsType, coord = sym.coord)
85
- .enteredAfter(thisPhase)
86
- val cacheDef = ValDef (cacheSym, tpd.defaultValue(rhsType))
87
- val cachingDef = cpy.DefDef (tree)(rhs =
88
- Block (
89
- If (
90
- ref(cacheSym).select(defn.Any_== ).appliedTo(nullLiteral),
91
- Assign (ref(cacheSym), tree.rhs),
92
- unitLiteral) :: Nil ,
93
- ref(cacheSym)
94
- )
95
- )
96
- Thicket (cacheDef, cachingDef)
97
- }
98
- case _ => tree
62
+ case _ => false
63
+ }
64
+ if (isCached) {
65
+ sym.copySymDenotation(
66
+ initFlags = sym.flags &~ Method | Lazy ,
67
+ info = rhsType)
68
+ .installAfter(thisPhase)
69
+ cpy.ValDef (tree)(tree.name, tree.tpt, tree.rhs)
99
70
}
71
+ else tree
100
72
}
101
73
}
102
74
0 commit comments