From 27f649a147d0e5f62f7a844ce00fcfcbb608f343 Mon Sep 17 00:00:00 2001 From: Pierre Ricadat Date: Thu, 19 Nov 2020 10:02:25 +0900 Subject: [PATCH 1/3] Update derivation-macro.md --- .../reference/contextual/derivation-macro.md | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/docs/docs/reference/contextual/derivation-macro.md b/docs/docs/reference/contextual/derivation-macro.md index bd81c7fa226f..6b4b493a696f 100644 --- a/docs/docs/reference/contextual/derivation-macro.md +++ b/docs/docs/reference/contextual/derivation-macro.md @@ -44,11 +44,11 @@ from the signature. The body of the `derived` method is shown below: given derived[T: Type](using qctx: QuoteContext) as Expr[Eq[T]] = { import qctx.reflect._ - val ev: Expr[Mirror.Of[T]] = Expr.summon(using '[Mirror.Of[T]]).get + val ev: Expr[Mirror.Of[T]] = Expr.summon(using Type.of[Mirror.Of[T]]).get ev match { - case '{ $m: Mirror.ProductOf[T] { type MirroredElemTypes = $elementTypes }} => - val elemInstances = summonAll(elementTypes) + case '{ $m: Mirror.ProductOf[T] { type MirroredElemTypes = elementTypes }} => + val elemInstances = summonAll[elementTypes] val eqProductBody: (Expr[T], Expr[T]) => Expr[Boolean] = (x, y) => { elemInstances.zipWithIndex.foldLeft(Expr(true: Boolean)) { case (acc, (elem, index)) => @@ -84,17 +84,17 @@ Instead we extract the tuple-type for element types using pattern matching over quotes and more specifically of the refined type: ```scala - case '{ $m: Mirror.ProductOf[T] { type MirroredElemTypes = $elementTypes } } => ... + case '{ $m: Mirror.ProductOf[T] { type MirroredElemTypes = elementTypes }} => ... ``` The implementation of `summonAll` as a macro can be show below assuming that we have the given instances for our primitive types: ```scala - def summonAll[T](t: Type[T])(using qctx: QuoteContext): List[Expr[Eq[_]]] = t match { - case '[String *: $tpes] => '{ summon[Eq[String]] } :: summonAll(tpes) - case '[Int *: $tpes] => '{ summon[Eq[Int]] } :: summonAll(tpes) - case '[$tpe *: $tpes] => derived(using tpe, qctx) :: summonAll(tpes) + def summonAll[T](using t: Type[T])(using qctx: QuoteContext): List[Expr[Eq[_]]] = t match { + case '[String *: tpes] => '{ summon[Eq[String]] } :: summonAll[tpes] + case '[Int *: tpes] => '{ summon[Eq[Int]] } :: summonAll[tpes] + case '[tpe *: tpes] => derived[tpe] :: summonAll[tpes] case '[EmptyTuple] => Nil } ``` @@ -120,8 +120,8 @@ Alternatively and what is shown below is that we can call the `eqv` method directly. The `eqGen` can trigger the derivation. ```scala -extension [T](x: =>T) - inline def === (y: =>T)(using eq: Eq[T]): Boolean = eq.eqv(x, y) +extension [T](inline x: T) + inline def === (inline y: T)(using eq: Eq[T]): Boolean = eq.eqv(x, y) implicit inline def eqGen[T]: Eq[T] = ${ Eq.derived[T] } ``` @@ -144,7 +144,7 @@ The full code is shown below: ```scala import scala.deriving._ import scala.quoted._ -import scala.quoted.matching._ + trait Eq[T] { def eqv(x: T, y: T): Boolean @@ -169,21 +169,21 @@ object Eq { def eqv(x: T, y: T): Boolean = body(x, y) } - def summonAll[T](t: Type[T])(using qctx: QuoteContext): List[Expr[Eq[_]]] = t match { - case '[String *: $tpes] => '{ summon[Eq[String]] } :: summonAll(tpes) - case '[Int *: $tpes] => '{ summon[Eq[Int]] } :: summonAll(tpes) - case '[$tpe *: $tpes] => derived(using tpe, qctx) :: summonAll(tpes) + def summonAll[T](using t: Type[T])(using qctx: QuoteContext): List[Expr[Eq[_]]] = t match { + case '[String *: tpes] => '{ summon[Eq[String]] } :: summonAll[tpes] + case '[Int *: tpes] => '{ summon[Eq[Int]] } :: summonAll[tpes] + case '[tpe *: tpes] => derived[tpe] :: summonAll[tpes] case '[EmptyTuple] => Nil } given derived[T: Type](using qctx: QuoteContext) as Expr[Eq[T]] = { import qctx.reflect._ - val ev: Expr[Mirror.Of[T]] = Expr.summon(using '[Mirror.Of[T]]).get + val ev: Expr[Mirror.Of[T]] = Expr.summon(using Type.of[Mirror.Of[T]]).get ev match { - case '{ $m: Mirror.ProductOf[T] { type MirroredElemTypes = $elementTypes }} => - val elemInstances = summonAll(elementTypes) + case '{ $m: Mirror.ProductOf[T] { type MirroredElemTypes = elementTypes }} => + val elemInstances = summonAll[elementTypes] val eqProductBody: (Expr[T], Expr[T]) => Expr[Boolean] = (x, y) => { elemInstances.zipWithIndex.foldLeft(Expr(true: Boolean)) { case (acc, (elem, index)) => @@ -197,8 +197,8 @@ object Eq { eqProduct((x: T, y: T) => ${eqProductBody('x, 'y)}) } - case '{ $m: Mirror.SumOf[T] { type MirroredElemTypes = $elementTypes }} => - val elemInstances = summonAll(elementTypes) + case '{ $m: Mirror.SumOf[T] { type MirroredElemTypes = elementTypes }} => + val elemInstances = summonAll[elementTypes] val eqSumBody: (Expr[T], Expr[T]) => Expr[Boolean] = (x, y) => { val ordx = '{ $m.ordinal($x) } val ordy = '{ $m.ordinal($y) } @@ -217,8 +217,7 @@ object Eq { } object Macro3 { - extension [T](x: =>T) - inline def === (y: =>T)(using eq: Eq[T]): Boolean = eq.eqv(x, y) + extension [T](inline x: T) inline def === (inline y: T)(using eq: Eq[T]): Boolean = eq.eqv(x, y) implicit inline def eqGen[T]: Eq[T] = ${ Eq.derived[T] } } From 88de8a333b4160de89ec3e6fb51e0fe5a41cdecb Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 19 Nov 2020 10:49:28 +0100 Subject: [PATCH 2/3] Apply suggestions from code review --- docs/docs/reference/contextual/derivation-macro.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/docs/reference/contextual/derivation-macro.md b/docs/docs/reference/contextual/derivation-macro.md index 6b4b493a696f..ca1d2c9f8275 100644 --- a/docs/docs/reference/contextual/derivation-macro.md +++ b/docs/docs/reference/contextual/derivation-macro.md @@ -91,7 +91,7 @@ The implementation of `summonAll` as a macro can be show below assuming that we have the given instances for our primitive types: ```scala - def summonAll[T](using t: Type[T])(using qctx: QuoteContext): List[Expr[Eq[_]]] = t match { + def summonAll[T: Type](using qctx: QuoteContext): List[Expr[Eq[_]]] = t match { case '[String *: tpes] => '{ summon[Eq[String]] } :: summonAll[tpes] case '[Int *: tpes] => '{ summon[Eq[Int]] } :: summonAll[tpes] case '[tpe *: tpes] => derived[tpe] :: summonAll[tpes] @@ -169,7 +169,7 @@ object Eq { def eqv(x: T, y: T): Boolean = body(x, y) } - def summonAll[T](using t: Type[T])(using qctx: QuoteContext): List[Expr[Eq[_]]] = t match { + def summonAll[T: Type](using qctx: QuoteContext): List[Expr[Eq[_]]] = t match { case '[String *: tpes] => '{ summon[Eq[String]] } :: summonAll[tpes] case '[Int *: tpes] => '{ summon[Eq[Int]] } :: summonAll[tpes] case '[tpe *: tpes] => derived[tpe] :: summonAll[tpes] @@ -217,7 +217,8 @@ object Eq { } object Macro3 { - extension [T](inline x: T) inline def === (inline y: T)(using eq: Eq[T]): Boolean = eq.eqv(x, y) + extension [T](inline x: T) + inline def === (inline y: T)(using eq: Eq[T]): Boolean = eq.eqv(x, y) implicit inline def eqGen[T]: Eq[T] = ${ Eq.derived[T] } } From 4bda7be5bb9755214334a5ba9313038869eae549 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 19 Nov 2020 10:53:22 +0100 Subject: [PATCH 3/3] Apply suggestions from code review --- docs/docs/reference/contextual/derivation-macro.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/reference/contextual/derivation-macro.md b/docs/docs/reference/contextual/derivation-macro.md index ca1d2c9f8275..e204fd5a52d6 100644 --- a/docs/docs/reference/contextual/derivation-macro.md +++ b/docs/docs/reference/contextual/derivation-macro.md @@ -44,7 +44,7 @@ from the signature. The body of the `derived` method is shown below: given derived[T: Type](using qctx: QuoteContext) as Expr[Eq[T]] = { import qctx.reflect._ - val ev: Expr[Mirror.Of[T]] = Expr.summon(using Type.of[Mirror.Of[T]]).get + val ev: Expr[Mirror.Of[T]] = Expr.summon[Mirror.Of[T]].get ev match { case '{ $m: Mirror.ProductOf[T] { type MirroredElemTypes = elementTypes }} => @@ -179,7 +179,7 @@ object Eq { given derived[T: Type](using qctx: QuoteContext) as Expr[Eq[T]] = { import qctx.reflect._ - val ev: Expr[Mirror.Of[T]] = Expr.summon(using Type.of[Mirror.Of[T]]).get + val ev: Expr[Mirror.Of[T]] = Expr.summon[Mirror.Of[T]].get ev match { case '{ $m: Mirror.ProductOf[T] { type MirroredElemTypes = elementTypes }} =>