@@ -643,15 +643,12 @@ trait Implicits { self: Typer =>
643
643
}
644
644
}
645
645
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 )]
650
649
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 {
655
652
case arg :: Nil =>
656
653
fullyDefinedType(arg, " ClassTag argument" , span) match {
657
654
case defn.ArrayOf (elemTp) =>
@@ -673,7 +670,8 @@ trait Implicits { self: Typer =>
673
670
EmptyTree
674
671
}
675
672
676
- def synthesizedTypeTag (formal : Type ): Tree = {
673
+ lazy val synthesizedTypeTag : SpecialHandler =
674
+ (formal : Type , span : Span ) => implicit (ctx : Context ) => {
677
675
def quotedType (t : Type ) = {
678
676
if (StagingContext .level == 0 )
679
677
ctx.compilationUnit.needsStaging = true // We will need to run ReifyQuotes
@@ -705,59 +703,60 @@ trait Implicits { self: Typer =>
705
703
}
706
704
}
707
705
708
- def synthesizedTastyContext (formal : Type ): Tree =
706
+ lazy val synthesizedTastyContext : SpecialHandler =
707
+ (formal : Type , span : Span ) => implicit (ctx : Context ) =>
709
708
if (ctx.inInlineMethod || enclosingInlineds.nonEmpty) ref(defn.TastyReflection_macroContext )
710
709
else EmptyTree
711
710
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
740
726
}
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
744
738
}
745
739
}
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 )
753
746
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
755
753
}
756
754
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 ) => {
761
760
762
761
/** Is there an `Eql[T, T]` instance, assuming -strictEquality? */
763
762
def hasEq (tp : Type )(implicit ctx : Context ): Boolean = {
@@ -818,10 +817,11 @@ trait Implicits { self: Typer =>
818
817
}
819
818
}
820
819
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 ) => {
825
825
def success (t : Tree ) = New (defn.ValueOfClass .typeRef.appliedTo(t.tpe), t :: Nil ).withSpan(span)
826
826
827
827
formal.argTypes match {
@@ -841,10 +841,11 @@ trait Implicits { self: Typer =>
841
841
}
842
842
}
843
843
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 ) =>
848
849
formal.argTypes match {
849
850
case arg :: Nil =>
850
851
val pos = ctx.source.atSpan(span)
@@ -855,26 +856,44 @@ trait Implicits { self: Typer =>
855
856
EmptyTree
856
857
}
857
858
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 = {
858
879
inferImplicit(formal, EmptyTree , span)(ctx) match {
859
880
case SearchSuccess (arg, _, _) => arg
860
881
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
868
894
}
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)
878
897
}
879
898
}
880
899
0 commit comments