@@ -27,25 +27,18 @@ object CacheAliasImplicits {
2727 * is cached. It applies to all alias implicits that have neither type parameters
2828 * nor a given clause. Example: The alias
2929 *
30- * implicit a for TC = rhs
30+ * given a as TC = rhs
3131 *
32- * is expanded before this phase
32+ * is expanded before this phase to:
3333 *
3434 * implicit def a: TC = rhs
3535 *
3636 * It is then expanded further as follows:
3737 *
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.
4040 *
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
4942 *
5043 * lazy implicit val a: TC = rhs
5144 */
@@ -56,47 +49,26 @@ class CacheAliasImplicits extends MiniPhase with IdentityDenotTransformer { this
5649
5750 override def transformDefDef (tree : DefDef )(implicit ctx : Context ): Tree = {
5851 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
7061 }
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)
9970 }
71+ else tree
10072 }
10173}
10274
0 commit comments