Skip to content

Commit c619dd7

Browse files
committed
Don't cache given instances that are macros.
An inline given instance with a splice as right hand side should not be cached.
1 parent b73e372 commit c619dd7

File tree

3 files changed

+26
-14
lines changed

3 files changed

+26
-14
lines changed

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package dotc
33
package ast
44

55
import core._
6-
import Flags._, Trees._, Types._, Contexts._
6+
import Flags._, Trees._, Types._, Contexts._, Constants.Constant
77
import Names._, StdNames._, NameOps._, Symbols._
88
import typer.ConstFold
99
import reporting.trace
@@ -856,6 +856,16 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
856856
case _ => None
857857
}
858858
}
859+
860+
object SplicedRHS {
861+
/** Extracts splices, possibly wrapped in blocks or type ascriptions */
862+
def unapply(tree: tpd.Tree)(implicit ctx: Context): Option[tpd.Tree] = tree match {
863+
case Block(stat :: Nil, Literal(Constant(()))) => unapply(stat)
864+
case Block(Nil, expr) => unapply(expr)
865+
case Typed(expr, _) => unapply(expr)
866+
case _ => Spliced.unapply(tree)
867+
}
868+
}
859869
}
860870

861871
object TreeInfo {

compiler/src/dotty/tools/dotc/typer/MemoizeGivenAliases.scala

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,29 +31,31 @@ trait MemoizeGivenAliases { this: Typer =>
3131
*
3232
* It is then expanded as follows:
3333
*
34-
* 1. If `rhs` is a simple name `x` (possibly with a `this.` prefix), leave the definition as is.
34+
* 1. If `rhs` is a simple name `x` (possibly with a `this.` prefix),
35+
* or `rhs` is a splice, leave the definition as is.
3536
* 2. Otherwise, wrap `rhs` in a call to `scala.compiletime.memo`.
3637
*/
3738
def memoizeGivenAlias(rhs: Tree, meth: Symbol) given Context : Tree = meth.info match {
3839
case ExprType(rhsType) if meth.is(Given, butNot = MemoizeGivenAliases.NoCacheFlags) =>
3940
// If rhs is a simple stable TermRef, leave as is.
40-
val needsMemo = rhs.tpe match {
41-
case rhsTpe @ TermRef(pre, _) if rhsTpe.isStable =>
42-
pre match {
43-
case NoPrefix => false
44-
case pre: ThisType => pre.cls != meth.owner.enclosingClass
45-
case _ => true
46-
}
47-
case _ => true
41+
val needsMemo = rhs match {
42+
case SplicedRHS(_) => false
43+
case _ => rhs.tpe match {
44+
case rhsTpe @ TermRef(pre, _) if rhsTpe.isStable =>
45+
pre match {
46+
case NoPrefix => false
47+
case pre: ThisType => pre.cls != meth.owner.enclosingClass
48+
case _ => true
49+
}
50+
case _ => true
51+
}
4852
}
4953
if (needsMemo) {
5054
val memoized = ref(defn.Compiletime_memo).appliedToType(rhsType).appliedTo(rhs)
51-
adapt(memoized, rhsType)
55+
adapt(memoized, rhsType) // this will do the inlining of `memo`
5256
}
5357
else rhs
5458
case _ => rhs
5559
}
5660
}
5761

58-
59-

docs/docs/reference/contextual/relationship-implicits.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Given instances can be mapped to combinations of implicit objects, classes and i
2828
class ListOrd[T](implicit ord: Ord[T]) extends Ord[List[T]] { ... }
2929
final implicit def ListOrd[T](implicit ord: Ord[T]): ListOrd[T] = new ListOrd[T]
3030
```
31-
3. Alias givens map to implicit methods. If an alias has neither type parameters nor a given clause, its right-hand side is cached in a variable, unless the right hand side is a simple reference in which case we can use a forwarder to that reference without caching it.
31+
3. Alias givens map to implicit methods. If an alias is not a macro, and has neither type parameters nor a given clause, its right-hand side is cached in a variable, unless the right hand side is a simple reference in which case we can use a forwarder to that reference without caching it.
3232

3333
Examples:
3434

0 commit comments

Comments
 (0)