Skip to content

Commit cfdfb8b

Browse files
committed
removed RpcImplicitsProvider, unified & simplified implicit caching
1 parent 422f0a5 commit cfdfb8b

File tree

16 files changed

+116
-145
lines changed

16 files changed

+116
-145
lines changed

commons-core/src/main/scala/com/avsystem/commons/rpc/RPCFramework.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ trait RPCFramework {
1919
type RawRPC
2020
val RawRPC: BaseRawRpcCompanion
2121

22-
trait BaseRawRpcCompanion extends RawRpcCompanion[RawRPC] {
23-
override val implicits: RPCFramework.this.type = RPCFramework.this
24-
}
22+
trait BaseRawRpcCompanion extends RawRpcCompanion[RawRPC]
2523

2624
def read[T: Reader](raw: RawValue): T
2725
def write[T: Writer](value: T): RawValue

commons-core/src/main/scala/com/avsystem/commons/rpc/RawRpcCompanion.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import com.avsystem.commons.macros.rpc.RpcMacros
66
/**
77
* Base trait for companion objects of raw RPC traits.
88
*/
9-
trait RawRpcCompanion[Raw] extends RpcImplicitsProvider {
9+
trait RawRpcCompanion[Raw] {
1010
type AsRawRpc[Real] = AsRaw[Raw, Real]
1111
type AsRealRpc[Real] = AsReal[Raw, Real]
1212
type AsRawRealRpc[Real] = AsRawReal[Raw, Real]

commons-core/src/main/scala/com/avsystem/commons/rpc/RpcImplicitsProvider.scala

Lines changed: 0 additions & 11 deletions
This file was deleted.

commons-core/src/main/scala/com/avsystem/commons/rpc/RpcMetadataCompanion.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ package rpc
44
import com.avsystem.commons.macros.rpc.RpcMacros
55
import com.avsystem.commons.meta.MetadataCompanion
66

7-
trait RpcMetadataCompanion[M[_]] extends MetadataCompanion[M] with RpcImplicitsProvider {
7+
trait RpcMetadataCompanion[M[_]] extends MetadataCompanion[M] {
88
def materialize[Real]: M[Real] = macro RpcMacros.rpcMetadata[Real]
99
}

commons-core/src/test/scala/com/avsystem/commons/rpc/NewRawRpc.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,6 @@ trait NewRawRpc {
6565
@multi def prefix(@methodName name: String): NewRawRpc
6666
}
6767
object NewRawRpc extends RawRpcCompanion[NewRawRpc] {
68-
override val implicits: this.type = this
69-
7068
implicit def asRawRealFromGenCodec[T: GenCodec]: AsRawReal[String, T] = ???
7169
implicit def futureAsRawRealFromGenCodec[T: GenCodec]: AsRawReal[Future[String], Future[T]] = ???
7270
}

commons-core/src/test/scala/com/avsystem/commons/rpc/NewRpcMetadataTest.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ trait TestApi extends SomeBase {
2525
def postit(arg: String, bar: String, int: Int, @suchMeta(3, "c") foo: String): String
2626
}
2727
object TestApi {
28+
import NewRawRpc._
2829
implicit val asRawReal: NewRawRpc.AsRawRealRpc[TestApi] = NewRawRpc.materializeAsRawReal[TestApi]
2930
implicit val metadata: NewRpcMetadata[TestApi] = NewRpcMetadata.materialize[TestApi]
3031
}

commons-core/src/test/scala/com/avsystem/commons/serialization/GenCodecTest.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ class mongoId extends AnnotationAggregate {
3535

3636
@flatten sealed trait FlatSealedBase {
3737
@mongoId def id: String
38-
@generated
39-
@name("upper_id") def upperId: String = id.toUpperCase
38+
@generated @name("upper_id") def upperId: String = id.toUpperCase
4039
}
4140
object FlatSealedBase extends HasGenCodec[FlatSealedBase] {
4241
case class FirstCase(id: String, int: Int = 42) extends FlatSealedBase

commons-macros/src/main/scala/com/avsystem/commons/macros/MacroCommons.scala

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -367,37 +367,33 @@ trait MacroCommons { bundle =>
367367
private val implicitSearchCache = new mutable.HashMap[TypeKey, Option[TermName]]
368368
private val implicitsByTrace = new mutable.HashMap[ImplicitTrace, TermName]
369369
private val inferredImplicitTypes = new mutable.HashMap[TermName, Type]
370-
private val implicitImports = new ListBuffer[Tree]
371-
private val implicitsToDeclare = new ListBuffer[Tree]
370+
private val implicitsToDeclare = new ListBuffer[(TermName, Tree)]
372371

373372
def tryInferCachedImplicit(tpe: Type): Option[TermName] = {
374373
def compute: Option[TermName] =
375-
Option(c.typecheck(q"..$implicitImports; implicitly[$tpe]", silent = true))
376-
.filter(_ != EmptyTree)
377-
.map { case WrappedImplicitSearchResult(t) =>
378-
def newCachedImplicit(): TermName = {
379-
val name = c.freshName(TermName("cachedImplicit"))
380-
inferredImplicitTypes(name) = t.tpe
381-
implicitsToDeclare += q"private lazy val $name = ${replaceCompanion(t)}"
374+
Option(c.inferImplicitValue(tpe)).filter(_ != EmptyTree).map { found =>
375+
def newCachedImplicit(): TermName = {
376+
val name = c.freshName(TermName("cachedImplicit"))
377+
inferredImplicitTypes(name) = found.tpe
378+
implicitsToDeclare += (name -> replaceCompanion(found))
379+
name
380+
}
381+
ImplicitTrace(found).fold(newCachedImplicit()) { tr =>
382+
implicitsByTrace.get(tr).filter(n => inferredImplicitTypes(n) =:= found.tpe).getOrElse {
383+
val name = newCachedImplicit()
384+
implicitsByTrace(tr) = name
382385
name
383386
}
384-
ImplicitTrace(t).fold(newCachedImplicit()) { tr =>
385-
implicitsByTrace.get(tr).filter(n => inferredImplicitTypes(n) =:= t.tpe).getOrElse {
386-
val name = newCachedImplicit()
387-
implicitsByTrace(tr) = name
388-
name
389-
}
390-
}
391387
}
388+
}
392389
implicitSearchCache.getOrElseUpdate(TypeKey(tpe), compute)
393390
}
394391

395392
def inferCachedImplicit(tpe: Type, errorClue: String, errorPos: Position): TermName =
396393
tryInferCachedImplicit(tpe).getOrElse {
397394
val name = c.freshName(TermName(""))
398395
implicitSearchCache(TypeKey(tpe)) = Some(name)
399-
implicitsToDeclare +=
400-
q"private implicit val $name = $ImplicitsObj.infer[$tpe](${StringLiteral(errorClue, errorPos)})"
396+
implicitsToDeclare += (name -> q"$ImplicitsObj.infer[$tpe](${StringLiteral(errorClue, errorPos)})")
401397
inferredImplicitTypes(name) = tpe
402398
inferCachedImplicit(tpe, errorClue, errorPos)
403399
}
@@ -410,11 +406,14 @@ trait MacroCommons { bundle =>
410406
inferredImplicitTypes(name) = tpe
411407
}
412408

413-
def registerImplicitImport(importTree: Tree): Unit =
414-
implicitImports += importTree
415-
416409
def cachedImplicitDeclarations: List[Tree] =
417-
implicitsToDeclare.result()
410+
cachedImplicitDeclarations(mkPrivateLazyVal)
411+
412+
def cachedImplicitDeclarations(mkDecl: (TermName, Tree) => Tree): List[Tree] =
413+
implicitsToDeclare.result().map { case (n, b) => mkDecl(n, b) }
414+
415+
def mkPrivateLazyVal(name: TermName, body: Tree): Tree =
416+
q"private lazy val $name = $body"
418417

419418
private def standardImplicitNotFoundMsg(tpe: Type): String =
420419
symbolImplicitNotFoundMsg(tpe, tpe.typeSymbol, tpe.typeSymbol.typeSignature.typeParams, tpe.typeArgs)
@@ -921,8 +920,18 @@ trait MacroCommons { bundle =>
921920
* @param unapply companion object'a unapply method or `NoSymbol` for case class with more than 22 fields
922921
* @param params parameters with trees evaluating to default values (or `EmptyTree`s)
923922
*/
924-
case class ApplyUnapply(apply: Symbol, unapply: Symbol, params: List[(TermSymbol, Tree)]) {
923+
case class ApplyUnapply(ownerTpe: Type, typedCompanion: Tree, apply: Symbol, unapply: Symbol, params: List[TermSymbol]) {
925924
def standardCaseClass: Boolean = apply.isConstructor
925+
926+
def defaultValueFor(param: Symbol): Tree =
927+
defaultValueFor(param, params.indexOf(param))
928+
929+
def defaultValueFor(param: Symbol, idx: Int): Tree =
930+
if (param.asTerm.isParamWithDefault) {
931+
val methodEncodedName = param.owner.name.encodedName.toString
932+
q"${replaceCompanion(typedCompanion)}.${TermName(s"$methodEncodedName$$default$$${idx + 1}")}[..${ownerTpe.typeArgs}]"
933+
}
934+
else EmptyTree
926935
}
927936

928937
def applyUnapplyFor(tpe: Type): Option[ApplyUnapply] =
@@ -933,15 +942,8 @@ trait MacroCommons { bundle =>
933942
val ts = dtpe.typeSymbol.asType
934943
val caseClass = ts.isClass && ts.asClass.isCaseClass
935944

936-
def defaultValueFor(param: Symbol, idx: Int): Tree =
937-
if (param.asTerm.isParamWithDefault) {
938-
val methodEncodedName = param.owner.name.encodedName.toString
939-
q"${replaceCompanion(typedCompanion)}.${TermName(s"$methodEncodedName$$default$$${idx + 1}")}[..${tpe.typeArgs}]"
940-
}
941-
else EmptyTree
942-
943-
def paramsWithDefaults(methodSig: Type): List[(TermSymbol, Tree)] =
944-
methodSig.paramLists.head.zipWithIndex.map { case (p, i) => (p.asTerm, defaultValueFor(p, i)) }
945+
def params(methodSig: Type): List[TermSymbol] =
946+
methodSig.paramLists.head.map(_.asTerm)
945947

946948
// Seq is a weird corner case where technically an apply/unapplySeq pair exists but is recursive
947949
val applyUnapplyPairs =
@@ -964,19 +966,19 @@ trait MacroCommons { bundle =>
964966

965967
if (caseClass && applyUnapplyPairs.isEmpty) { // case classes with more than 22 fields
966968
val constructor = primaryConstructorOf(dtpe)
967-
Some(ApplyUnapply(constructor, NoSymbol, paramsWithDefaults(constructor.typeSignatureIn(dtpe))))
969+
Some(ApplyUnapply(dtpe, typedCompanion, constructor, NoSymbol, params(constructor.typeSignatureIn(dtpe))))
968970
} else {
969971
val applicableResults = applyUnapplyPairs.flatMap {
970972
case (apply, unapply) if caseClass && apply.isSynthetic && unapply.isSynthetic =>
971973
val constructor = primaryConstructorOf(dtpe)
972-
Some(ApplyUnapply(constructor, unapply, paramsWithDefaults(constructor.typeSignatureIn(dtpe))))
974+
Some(ApplyUnapply(dtpe, typedCompanion, constructor, unapply, params(constructor.typeSignatureIn(dtpe))))
973975
case (apply, unapply) if typeParamsMatch(apply, unapply) =>
974976
val applySig =
975977
setTypeArgs(apply.typeSignatureIn(typedCompanion.tpe))
976978
val unapplySig =
977979
setTypeArgs(unapply.typeSignatureIn(typedCompanion.tpe))
978980
if (matchingApplyUnapply(dtpe, applySig, unapplySig))
979-
Some(ApplyUnapply(apply, unapply, paramsWithDefaults(applySig)))
981+
Some(ApplyUnapply(dtpe, typedCompanion, apply, unapply, params(applySig)))
980982
else None
981983
case _ => None
982984
}

commons-macros/src/main/scala/com/avsystem/commons/macros/TestMacros.scala

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,17 @@ class TestMacros(val c: blackbox.Context) extends TypeClassDerivation {
2222
def forSingleton(tpe: Type, singleValueTree: Tree): Tree =
2323
q"$SingletonTCObj[$tpe](${tpe.toString}, $singleValueTree)"
2424

25-
def forApplyUnapply(tpe: Type, apply: Symbol, unapply: Symbol, params: List[ApplyParam]): Tree = {
25+
def forApplyUnapply(au: ApplyUnapply, params: List[ApplyParam]): Tree = {
2626
val deps = params.map { case ApplyParam(_, s, dv, t) =>
27-
val defaultValueOpt = if (dv == EmptyTree) q"None" else q"Some($DefValObj($dv))"
27+
val defaultValueOpt = if (dv == EmptyTree) q"$NoneObj" else q"$SomeObj($DefValObj($dv))"
2828
q"(${s.name.toString}, $t, $defaultValueOpt)"
2929
}
30-
q"$ApplyUnapplyTCObj[$tpe](${tpe.toString}, List(..$deps))"
30+
q"$ApplyUnapplyTCObj[${au.ownerTpe}](${au.ownerTpe.toString}, $ListObj(..$deps))"
3131
}
3232

3333
def forSealedHierarchy(tpe: Type, subtypes: List[KnownSubtype]): Tree = {
3434
val deps = subtypes.map({ case KnownSubtype(_, st, tree) => q"(${st.typeSymbol.name.toString}, $tree)" })
35-
q"$SealedHierarchyTCObj[$tpe](${tpe.toString}, List(..$deps))"
35+
q"$SealedHierarchyTCObj[$tpe](${tpe.toString}, $ListObj(..$deps))"
3636
}
3737

3838
def forUnknown(tpe: Type): Tree =
@@ -53,7 +53,7 @@ class TestMacros(val c: blackbox.Context) extends TypeClassDerivation {
5353
val newTpe = getType(newTree)
5454

5555
assertSameTypes(tpe, newTpe)
56-
q"???"
56+
q"$PredefObj.???"
5757
}
5858

5959
def testKnownSubtypes[T: WeakTypeTag, R: WeakTypeTag]: Tree = showOnDebug {
@@ -62,7 +62,7 @@ class TestMacros(val c: blackbox.Context) extends TypeClassDerivation {
6262
.getOrElse(typeOf[Nothing])
6363

6464
assertSameTypes(expectedResultTpe, weakTypeOf[R])
65-
q"???"
65+
q"$PredefObj.???"
6666
}
6767

6868
val ApplierUnapplierCls = tq"$CommonsPkg.macros.ApplierUnapplier"
@@ -71,25 +71,25 @@ class TestMacros(val c: blackbox.Context) extends TypeClassDerivation {
7171
val ttpe = weakTypeOf[T]
7272
val ftpe = weakTypeOf[F]
7373

74-
val ApplyUnapply(_, unapply, params) = applyUnapplyFor(ttpe)
74+
val au = applyUnapplyFor(ttpe)
7575
.getOrElse(c.abort(c.enclosingPosition,
7676
s"Could not find unambiguous, matching pair of apply/unapply methods for $ttpe"))
7777

78-
val companion = unapply.owner.asClass.module
78+
val companion = au.unapply.owner.asClass.module
7979

80-
val expectedTpe = params match {
80+
val expectedTpe = au.params match {
8181
case Nil => typeOf[Unit]
82-
case List((single, _)) => single.typeSignature
83-
case _ => getType(tq"(..${params.map(_._1.typeSignature)})")
82+
case List(single) => single.typeSignature
83+
case _ => getType(tq"(..${au.params.map(_.typeSignature)})")
8484
}
8585
assertSameTypes(expectedTpe, ftpe)
8686

87-
val applyParams = params match {
87+
val applyParams = au.params match {
8888
case List(_) => List(Ident(TermName("f")))
89-
case _ => params.indices.map(i => q"f.${TermName(s"_${i + 1}")}")
89+
case _ => au.params.indices.map(i => q"f.${TermName(s"_${i + 1}")}")
9090
}
9191

92-
val unapplyResult = params match {
92+
val unapplyResult = au.params match {
9393
case Nil => q"()"
9494
case _ => q"$companion.unapply(t).get"
9595
}

commons-macros/src/main/scala/com/avsystem/commons/macros/TypeClassDerivation.scala

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,10 @@ trait TypeClassDerivation extends MacroCommons {
104104
* Derives type class instance for record type. Record type is a class/trait whose companion object has
105105
* matching `apply` and `unapply` methods. In particular, every case class is a proper record type.
106106
*
107-
* @param tpe the record type
108-
* @param apply symbol of the `apply` method in companion object
109-
* @param unapply symbol of the `unapply` method in companion object
110-
* @param params metadata for parameters of `apply` method
107+
* @param applyUnapply info about case class or case class like type
108+
* @param params metadata for parameters of `apply` method
111109
*/
112-
def forApplyUnapply(tpe: Type, apply: Symbol, unapply: Symbol, params: List[ApplyParam]): Tree
110+
def forApplyUnapply(applyUnapply: ApplyUnapply, params: List[ApplyParam]): Tree
113111

114112
/**
115113
* Derives type class instance for union type (sealed hierarchy in which every non-abstract subtype has
@@ -142,12 +140,12 @@ trait TypeClassDerivation extends MacroCommons {
142140
def singleTypeTc: Option[Tree] =
143141
singleValueFor(dtpe).map(tree => forSingleton(dtpe, tree))
144142

145-
def applyUnapplyTc: Option[Tree] = applyUnapplyFor(dtpe).map {
146-
case ApplyUnapply(apply, unapply, params) =>
147-
val dependencies = params.zipWithIndex.map { case ((s, defaultValue), idx) =>
148-
ApplyParam(idx, s, defaultValue, dependency(actualParamType(s), tcTpe, s))
149-
}
150-
forApplyUnapply(dtpe, apply, unapply, dependencies)
143+
def applyUnapplyTc: Option[Tree] = applyUnapplyFor(dtpe).map { au =>
144+
val dependencies = au.params.zipWithIndex.map { case (s, idx) =>
145+
val defaultValue = au.defaultValueFor(s, idx)
146+
ApplyParam(idx, s, defaultValue, dependency(actualParamType(s), tcTpe, s))
147+
}
148+
forApplyUnapply(au, dependencies)
151149
}
152150

153151
def sealedHierarchyTc = knownSubtypes(dtpe).map { subtypes =>
@@ -175,11 +173,12 @@ trait TypeClassDerivation extends MacroCommons {
175173
val deferredName = c.freshName(TermName("deferred"))
176174
// introducing intermediate val to make sure exact type of materialized instance is not lost
177175
val underlyingName = c.freshName(TermName("underlying"))
176+
registerImplicit(tcTpe, deferredName)
178177

179178
val withDummyImplicit =
180179
q"""
181-
implicit def $deferredName: $DeferredInstanceCls[$tcTpe] with $tcTpe = $PredefObj.???
182-
$unguarded
180+
implicit def $deferredName: $DeferredInstanceCls[$tcTpe] with $tcTpe = $PredefObj.???
181+
$unguarded
183182
"""
184183

185184
def guarded: Tree =

0 commit comments

Comments
 (0)