@@ -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 }
0 commit comments