@@ -643,15 +643,12 @@ trait Implicits { self: Typer =>
643643 }
644644 }
645645
646- /** Find an implicit argument for parameter `formal`.
647- * Return a failure as a SearchFailureType in the type of the returned tree.
648- */
649- def inferImplicitArg (formal : Type , span : Span )(implicit ctx : Context ): Tree = {
646+ /** Handlers to synthesize implicits for special types */
647+ type SpecialHandler = (Type , Span ) => Context => Tree
648+ type SpecialHandlers = List [(ClassSymbol , SpecialHandler )]
650649
651- /** If `formal` is of the form ClassTag[T], where `T` is a class type,
652- * synthesize a class tag for `T`.
653- */
654- def synthesizedClassTag (formal : Type ): Tree = formal.argInfos match {
650+ lazy val synthesizedClassTag : SpecialHandler =
651+ (formal : Type , span : Span ) => implicit (ctx : Context ) => formal.argInfos match {
655652 case arg :: Nil =>
656653 fullyDefinedType(arg, " ClassTag argument" , span) match {
657654 case defn.ArrayOf (elemTp) =>
@@ -673,7 +670,8 @@ trait Implicits { self: Typer =>
673670 EmptyTree
674671 }
675672
676- def synthesizedTypeTag (formal : Type ): Tree = {
673+ lazy val synthesizedTypeTag : SpecialHandler =
674+ (formal : Type , span : Span ) => implicit (ctx : Context ) => {
677675 def quotedType (t : Type ) = {
678676 if (StagingContext .level == 0 )
679677 ctx.compilationUnit.needsStaging = true // We will need to run ReifyQuotes
@@ -705,59 +703,60 @@ trait Implicits { self: Typer =>
705703 }
706704 }
707705
708- def synthesizedTastyContext (formal : Type ): Tree =
706+ lazy val synthesizedTastyContext : SpecialHandler =
707+ (formal : Type , span : Span ) => implicit (ctx : Context ) =>
709708 if (ctx.inInlineMethod || enclosingInlineds.nonEmpty) ref(defn.TastyReflection_macroContext )
710709 else EmptyTree
711710
712- def synthesizedTupleFunction (formal : Type ): Tree = {
713- formal match {
714- case AppliedType (_, funArgs @ fun :: tupled :: Nil ) =>
715- def functionTypeEqual (baseFun : Type , actualArgs : List [Type ], actualRet : Type , expected : Type ) = {
716- expected =:= defn.FunctionOf (actualArgs, actualRet, defn.isImplicitFunctionType(baseFun), defn.isErasedFunctionType(baseFun))
717- }
718- val arity : Int = {
719- if (defn.isErasedFunctionType(fun) || defn.isErasedFunctionType(fun)) - 1 // TODO support?
720- else if (defn.isFunctionType(fun)) {
721- // TupledFunction[(...) => R, ?]
722- fun.dropDependentRefinement.dealias.argInfos match {
723- case funArgs :+ funRet if functionTypeEqual(fun, defn.tupleType(funArgs) :: Nil , funRet, tupled) =>
724- // TupledFunction[(...funArgs...) => funRet, ?]
725- funArgs.size
726- case _ => - 1
727- }
728- } else if (defn.isFunctionType(tupled)) {
729- // TupledFunction[?, (...) => R]
730- tupled.dropDependentRefinement.dealias.argInfos match {
731- case tupledArgs :: funRet :: Nil =>
732- defn.tupleTypes(tupledArgs) match {
733- case Some (funArgs) if functionTypeEqual(tupled, funArgs, funRet, fun) =>
734- // TupledFunction[?, ((...funArgs...)) => funRet]
735- funArgs.size
736- case _ => - 1
737- }
738- case _ => - 1
739- }
711+ lazy val synthesizedTupleFunction : SpecialHandler =
712+ (formal : Type , span : Span ) => implicit (ctx : Context ) => formal match {
713+ case AppliedType (_, funArgs @ fun :: tupled :: Nil ) =>
714+ def functionTypeEqual (baseFun : Type , actualArgs : List [Type ], actualRet : Type , expected : Type ) = {
715+ expected =:= defn.FunctionOf (actualArgs, actualRet, defn.isImplicitFunctionType(baseFun), defn.isErasedFunctionType(baseFun))
716+ }
717+ val arity : Int = {
718+ if (defn.isErasedFunctionType(fun) || defn.isErasedFunctionType(fun)) - 1 // TODO support?
719+ else if (defn.isFunctionType(fun)) {
720+ // TupledFunction[(...) => R, ?]
721+ fun.dropDependentRefinement.dealias.argInfos match {
722+ case funArgs :+ funRet if functionTypeEqual(fun, defn.tupleType(funArgs) :: Nil , funRet, tupled) =>
723+ // TupledFunction[(...funArgs...) => funRet, ?]
724+ funArgs.size
725+ case _ => - 1
740726 }
741- else {
742- // TupledFunction[?, ?]
743- - 1
727+ } else if (defn.isFunctionType(tupled)) {
728+ // TupledFunction[?, (...) => R]
729+ tupled.dropDependentRefinement.dealias.argInfos match {
730+ case tupledArgs :: funRet :: Nil =>
731+ defn.tupleTypes(tupledArgs) match {
732+ case Some (funArgs) if functionTypeEqual(tupled, funArgs, funRet, fun) =>
733+ // TupledFunction[?, ((...funArgs...)) => funRet]
734+ funArgs.size
735+ case _ => - 1
736+ }
737+ case _ => - 1
744738 }
745739 }
746- if (arity == - 1 )
747- EmptyTree
748- else if (arity <= Definitions .MaxImplementedFunctionArity )
749- ref(defn.InternalTupleFunctionModule ).select(s " tupledFunction $arity" .toTermName).appliedToTypes(funArgs)
750- else
751- ref(defn.InternalTupleFunctionModule ).select(" tupledFunctionXXL" .toTermName).appliedToTypes(funArgs)
752- case _ =>
740+ else {
741+ // TupledFunction[?, ?]
742+ - 1
743+ }
744+ }
745+ if (arity == - 1 )
753746 EmptyTree
754- }
747+ else if (arity <= Definitions .MaxImplementedFunctionArity )
748+ ref(defn.InternalTupleFunctionModule ).select(s " tupledFunction $arity" .toTermName).appliedToTypes(funArgs)
749+ else
750+ ref(defn.InternalTupleFunctionModule ).select(" tupledFunctionXXL" .toTermName).appliedToTypes(funArgs)
751+ case _ =>
752+ EmptyTree
755753 }
756754
757- /** If `formal` is of the form Eql[T, U], try to synthesize an
758- * `Eql.eqlAny[T, U]` as solution.
759- */
760- def synthesizedEq (formal : Type )(implicit ctx : Context ): Tree = {
755+ /** If `formal` is of the form Eql[T, U], try to synthesize an
756+ * `Eql.eqlAny[T, U]` as solution.
757+ */
758+ lazy val synthesizedEq : SpecialHandler =
759+ (formal : Type , span : Span ) => implicit (ctx : Context ) => {
761760
762761 /** Is there an `Eql[T, T]` instance, assuming -strictEquality? */
763762 def hasEq (tp : Type )(implicit ctx : Context ): Boolean = {
@@ -818,10 +817,11 @@ trait Implicits { self: Typer =>
818817 }
819818 }
820819
821- /** Creates a tree that will produce a ValueOf instance for the requested type.
822- * An EmptyTree is returned if materialization fails.
823- */
824- def synthesizedValueOf (formal : Type )(implicit ctx : Context ): Tree = {
820+ /** Creates a tree that will produce a ValueOf instance for the requested type.
821+ * An EmptyTree is returned if materialization fails.
822+ */
823+ lazy val synthesizedValueOf : SpecialHandler =
824+ (formal : Type , span : Span ) => implicit (ctx : Context ) => {
825825 def success (t : Tree ) = New (defn.ValueOfClass .typeRef.appliedTo(t.tpe), t :: Nil ).withSpan(span)
826826
827827 formal.argTypes match {
@@ -841,10 +841,11 @@ trait Implicits { self: Typer =>
841841 }
842842 }
843843
844- /** If `formal` is of the form `scala.reflect.Generic[T]` for some class type `T`,
845- * synthesize an instance for it.
846- */
847- def synthesizedGeneric (formal : Type ): Tree =
844+ /** If `formal` is of the form `scala.reflect.Generic[T]` for some class type `T`,
845+ * synthesize an instance for it.
846+ */
847+ lazy val synthesizedGeneric : SpecialHandler =
848+ (formal : Type , span : Span ) => implicit (ctx : Context ) =>
848849 formal.argTypes match {
849850 case arg :: Nil =>
850851 val pos = ctx.source.atSpan(span)
@@ -855,26 +856,44 @@ trait Implicits { self: Typer =>
855856 EmptyTree
856857 }
857858
859+ private var mySpecialHandlers : SpecialHandlers = null
860+
861+ private def specialHandlers (implicit ctx : Context ) = {
862+ if (mySpecialHandlers == null )
863+ mySpecialHandlers = List (
864+ defn.ClassTagClass -> synthesizedClassTag,
865+ defn.QuotedTypeClass -> synthesizedTypeTag,
866+ defn.GenericClass -> synthesizedGeneric,
867+ defn.TastyReflectionClass -> synthesizedTastyContext,
868+ defn.EqlClass -> synthesizedEq,
869+ defn.TupledFunctionClass -> synthesizedTupleFunction,
870+ defn.ValueOfClass -> synthesizedValueOf
871+ )
872+ mySpecialHandlers
873+ }
874+
875+ /** Find an implicit argument for parameter `formal`.
876+ * Return a failure as a SearchFailureType in the type of the returned tree.
877+ */
878+ def inferImplicitArg (formal : Type , span : Span )(implicit ctx : Context ): Tree = {
858879 inferImplicit(formal, EmptyTree , span)(ctx) match {
859880 case SearchSuccess (arg, _, _) => arg
860881 case fail @ SearchFailure (failed) =>
861- def trySpecialCase (cls : ClassSymbol , handler : Type => Tree , ifNot : => Tree ) = {
862- val base = formal.baseType(cls)
863- if (base <:< formal) {
864- // With the subtype test we enforce that the searched type `formal` is of the right form
865- handler(base).orElse(ifNot)
866- }
867- else ifNot
882+ def trySpecialCases (handlers : SpecialHandlers ): Tree = handlers match {
883+ case (cls, handler) :: rest =>
884+ val base = formal.baseType(cls)
885+ val result =
886+ if (base <:< formal) {
887+ // With the subtype test we enforce that the searched type `formal` is of the right form
888+ handler(base, span)(ctx)
889+ }
890+ else EmptyTree
891+ result.orElse(trySpecialCases(rest))
892+ case Nil =>
893+ failed
868894 }
869- if (fail.isAmbiguous) failed
870- else
871- trySpecialCase(defn.ClassTagClass , synthesizedClassTag,
872- trySpecialCase(defn.QuotedTypeClass , synthesizedTypeTag,
873- trySpecialCase(defn.GenericClass , synthesizedGeneric,
874- trySpecialCase(defn.TastyReflectionClass , synthesizedTastyContext,
875- trySpecialCase(defn.EqlClass , synthesizedEq,
876- trySpecialCase(defn.TupledFunctionClass , synthesizedTupleFunction,
877- trySpecialCase(defn.ValueOfClass , synthesizedValueOf, failed)))))))
895+ if (fail.isAmbiguous) failed
896+ else trySpecialCases(specialHandlers)
878897 }
879898 }
880899
0 commit comments