@@ -697,160 +697,190 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
697
697
}
698
698
699
699
def typedFunction (tree : untpd.Function , pt : Type )(implicit ctx : Context ) = track(" typedFunction" ) {
700
+ if (ctx.mode is Mode .Type ) typedFunctionType(tree, pt)
701
+ else typedFunctionValue(tree, pt)
702
+ }
703
+
704
+ def typedFunctionType (tree : untpd.Function , pt : Type )(implicit ctx : Context ) = {
700
705
val untpd .Function (args, body) = tree
701
- if (ctx.mode is Mode .Type ) {
702
- val isImplicit = tree match {
703
- case _ : untpd.ImplicitFunction =>
704
- if (args.length == 0 ) {
705
- ctx.error(ImplicitFunctionTypeNeedsNonEmptyParameterList (), tree.pos)
706
- false
707
- }
708
- else true
709
- case _ => false
710
- }
711
- val funCls = defn.FunctionClass (args.length, isImplicit)
712
- typed(cpy.AppliedTypeTree (tree)(
713
- untpd.TypeTree (funCls.typeRef), args :+ body), pt)
706
+ val isImplicit = tree match {
707
+ case _ : untpd.ImplicitFunction =>
708
+ if (args.length == 0 ) {
709
+ ctx.error(ImplicitFunctionTypeNeedsNonEmptyParameterList (), tree.pos)
710
+ false
711
+ }
712
+ else true
713
+ case _ => false
714
714
}
715
- else {
716
- val params = args.asInstanceOf [List [untpd.ValDef ]]
717
-
718
- pt match {
719
- case pt : TypeVar if untpd.isFunctionWithUnknownParamType(tree) =>
720
- // try to instantiate `pt` if this is possible. If it does not
721
- // work the error will be reported later in `inferredParam`,
722
- // when we try to infer the parameter type.
723
- isFullyDefined(pt, ForceDegree .noBottom)
724
- case _ =>
725
- }
715
+ val funCls = defn.FunctionClass (args.length, isImplicit)
716
+
717
+ def typedDependent (params : List [ValDef ])(implicit ctx : Context ) = {
718
+ completeParams(params)
719
+ val params1 = params.map(typedExpr(_).asInstanceOf [ValDef ])
720
+ val resultTpt = typed(body)
721
+ val companion = if (isImplicit) ImplicitMethodType else MethodType
722
+ val mt = companion.fromSymbols(params1.map(_.symbol), resultTpt.tpe)
723
+ if (mt.isParamDependent)
724
+ ctx.error(i " $mt is an illegal function type because it has inter-parameter dependencies " )
725
+ val resTpt = TypeTree (mt.nonDependentResultApprox).withPos(body.pos)
726
+ val typeArgs = params1.map(_.tpt) :+ resTpt
727
+ val tycon = TypeTree (funCls.typeRef)
728
+ val core = assignType(cpy.AppliedTypeTree (tree)(tycon, typeArgs), tycon, typeArgs)
729
+ val appMeth = ctx.newSymbol(ctx.owner, nme.apply, Synthetic | Deferred , mt)
730
+ val appDef = assignType(
731
+ untpd.DefDef (appMeth.name, Nil , List (params1), resultTpt, EmptyTree ),
732
+ appMeth)
733
+ RefinedTypeTree (core, List (appDef), ctx.owner.asClass)
734
+ }
735
+
736
+ args match {
737
+ case ValDef (_, _, _) :: _ =>
738
+ typedDependent(args.asInstanceOf [List [ValDef ]])(
739
+ ctx.fresh.setOwner(ctx.newRefinedClassSymbol).setNewScope)
740
+ case _ =>
741
+ typed(cpy.AppliedTypeTree (tree)(untpd.TypeTree (funCls.typeRef), args :+ body), pt)
742
+ }
743
+ }
726
744
727
- val (protoFormals, protoResult) = decomposeProtoFunction(pt, params.length)
745
+ def typedFunctionValue (tree : untpd.Function , pt : Type )(implicit ctx : Context ) = {
746
+ val untpd .Function (args, body) = tree
747
+ val params = args.asInstanceOf [List [untpd.ValDef ]]
728
748
729
- def refersTo (arg : untpd.Tree , param : untpd.ValDef ): Boolean = arg match {
730
- case Ident (name) => name == param.name
731
- case _ => false
732
- }
749
+ pt match {
750
+ case pt : TypeVar if untpd.isFunctionWithUnknownParamType(tree) =>
751
+ // try to instantiate `pt` if this is possible. If it does not
752
+ // work the error will be reported later in `inferredParam`,
753
+ // when we try to infer the parameter type.
754
+ isFullyDefined(pt, ForceDegree .noBottom)
755
+ case _ =>
756
+ }
733
757
734
- /** The function body to be returned in the closure. Can become a TypedSplice
735
- * of a typed expression if this is necessary to infer a parameter type.
736
- */
737
- var fnBody = tree.body
758
+ val (protoFormals, protoResult) = decomposeProtoFunction(pt, params.length)
738
759
739
- /** A map from parameter names to unique positions where the parameter
740
- * appears in the argument list of an application.
741
- */
742
- var paramIndex = Map [ Name , Int ]()
760
+ def refersTo ( arg : untpd. Tree , param : untpd. ValDef ) : Boolean = arg match {
761
+ case Ident (name) => name == param.name
762
+ case _ => false
763
+ }
743
764
744
- /** If parameter `param` appears exactly once as an argument in `args`,
745
- * the singleton list consisting of its position in `args`, otherwise `Nil`.
746
- */
747
- def paramIndices (param : untpd.ValDef , args : List [untpd.Tree ]): List [Int ] = {
748
- def loop (args : List [untpd.Tree ], start : Int ): List [Int ] = args match {
749
- case arg :: args1 =>
750
- val others = loop(args1, start + 1 )
751
- if (refersTo(arg, param)) start :: others else others
752
- case _ => Nil
753
- }
754
- val allIndices = loop(args, 0 )
755
- if (allIndices.length == 1 ) allIndices else Nil
765
+ /** The function body to be returned in the closure. Can become a TypedSplice
766
+ * of a typed expression if this is necessary to infer a parameter type.
767
+ */
768
+ var fnBody = tree.body
769
+
770
+ /** A map from parameter names to unique positions where the parameter
771
+ * appears in the argument list of an application.
772
+ */
773
+ var paramIndex = Map [Name , Int ]()
774
+
775
+ /** If parameter `param` appears exactly once as an argument in `args`,
776
+ * the singleton list consisting of its position in `args`, otherwise `Nil`.
777
+ */
778
+ def paramIndices (param : untpd.ValDef , args : List [untpd.Tree ]): List [Int ] = {
779
+ def loop (args : List [untpd.Tree ], start : Int ): List [Int ] = args match {
780
+ case arg :: args1 =>
781
+ val others = loop(args1, start + 1 )
782
+ if (refersTo(arg, param)) start :: others else others
783
+ case _ => Nil
756
784
}
785
+ val allIndices = loop(args, 0 )
786
+ if (allIndices.length == 1 ) allIndices else Nil
787
+ }
757
788
758
- /** If function is of the form
759
- * (x1, ..., xN) => f(... x1, ..., XN, ...)
760
- * where each `xi` occurs exactly once in the argument list of `f` (in
761
- * any order), the type of `f`, otherwise NoType.
762
- * Updates `fnBody` and `paramIndex` as a side effect.
763
- * @post: If result exists, `paramIndex` is defined for the name of
764
- * every parameter in `params`.
765
- */
766
- def calleeType : Type = fnBody match {
767
- case Apply (expr, args) =>
768
- paramIndex = {
769
- for (param <- params; idx <- paramIndices(param, args))
770
- yield param.name -> idx
771
- }.toMap
772
- if (paramIndex.size == params.length)
773
- expr match {
774
- case untpd.TypedSplice (expr1) =>
775
- expr1.tpe
776
- case _ =>
777
- val protoArgs = args map (_ withType WildcardType )
778
- val callProto = FunProto (protoArgs, WildcardType , this )
779
- val expr1 = typedExpr(expr, callProto)
780
- fnBody = cpy.Apply (fnBody)(untpd.TypedSplice (expr1), args)
781
- expr1.tpe
782
- }
783
- else NoType
789
+ /** If function is of the form
790
+ * (x1, ..., xN) => f(... x1, ..., XN, ...)
791
+ * where each `xi` occurs exactly once in the argument list of `f` (in
792
+ * any order), the type of `f`, otherwise NoType.
793
+ * Updates `fnBody` and `paramIndex` as a side effect.
794
+ * @post: If result exists, `paramIndex` is defined for the name of
795
+ * every parameter in `params`.
796
+ */
797
+ def calleeType : Type = fnBody match {
798
+ case Apply (expr, args) =>
799
+ paramIndex = {
800
+ for (param <- params; idx <- paramIndices(param, args))
801
+ yield param.name -> idx
802
+ }.toMap
803
+ if (paramIndex.size == params.length)
804
+ expr match {
805
+ case untpd.TypedSplice (expr1) =>
806
+ expr1.tpe
807
+ case _ =>
808
+ val protoArgs = args map (_ withType WildcardType )
809
+ val callProto = FunProto (protoArgs, WildcardType , this )
810
+ val expr1 = typedExpr(expr, callProto)
811
+ fnBody = cpy.Apply (fnBody)(untpd.TypedSplice (expr1), args)
812
+ expr1.tpe
813
+ }
814
+ else NoType
815
+ case _ =>
816
+ NoType
817
+ }
818
+
819
+ /** Two attempts: First, if expected type is fully defined pick this one.
820
+ * Second, if function is of the form
821
+ * (x1, ..., xN) => f(... x1, ..., XN, ...)
822
+ * where each `xi` occurs exactly once in the argument list of `f` (in
823
+ * any order), and f has a method type MT, pick the corresponding parameter
824
+ * type in MT, if this one is fully defined.
825
+ * If both attempts fail, issue a "missing parameter type" error.
826
+ */
827
+ def inferredParamType (param : untpd.ValDef , formal : Type ): Type = {
828
+ if (isFullyDefined(formal, ForceDegree .noBottom)) return formal
829
+ calleeType.widen match {
830
+ case mtpe : MethodType =>
831
+ val pos = paramIndex(param.name)
832
+ if (pos < mtpe.paramInfos.length) {
833
+ val ptype = mtpe.paramInfos(pos)
834
+ if (isFullyDefined(ptype, ForceDegree .noBottom) && ! ptype.isRepeatedParam)
835
+ return ptype
836
+ }
784
837
case _ =>
785
- NoType
786
838
}
839
+ errorType(AnonymousFunctionMissingParamType (param, args, tree, pt), param.pos)
840
+ }
787
841
788
- /** Two attempts: First, if expected type is fully defined pick this one.
789
- * Second, if function is of the form
790
- * (x1, ..., xN) => f(... x1, ..., XN, ...)
791
- * where each `xi` occurs exactly once in the argument list of `f` (in
792
- * any order), and f has a method type MT, pick the corresponding parameter
793
- * type in MT, if this one is fully defined.
794
- * If both attempts fail, issue a "missing parameter type" error.
795
- */
796
- def inferredParamType (param : untpd.ValDef , formal : Type ): Type = {
797
- if (isFullyDefined(formal, ForceDegree .noBottom)) return formal
798
- calleeType.widen match {
799
- case mtpe : MethodType =>
800
- val pos = paramIndex(param.name)
801
- if (pos < mtpe.paramInfos.length) {
802
- val ptype = mtpe.paramInfos(pos)
803
- if (isFullyDefined(ptype, ForceDegree .noBottom) && ! ptype.isRepeatedParam)
804
- return ptype
805
- }
806
- case _ =>
807
- }
808
- errorType(AnonymousFunctionMissingParamType (param, args, tree, pt), param.pos)
809
- }
842
+ def protoFormal (i : Int ): Type =
843
+ if (protoFormals.length == params.length) protoFormals(i)
844
+ else errorType(WrongNumberOfParameters (protoFormals.length), tree.pos)
810
845
811
- def protoFormal (i : Int ): Type =
812
- if (protoFormals.length == params.length) protoFormals(i)
813
- else errorType(WrongNumberOfParameters (protoFormals.length), tree.pos)
814
-
815
- /** Is `formal` a product type which is elementwise compatible with `params`? */
816
- def ptIsCorrectProduct (formal : Type ) = {
817
- isFullyDefined(formal, ForceDegree .noBottom) &&
818
- defn.isProductSubType(formal) &&
819
- Applications .productSelectorTypes(formal).corresponds(params) {
820
- (argType, param) =>
821
- param.tpt.isEmpty || argType <:< typedAheadType(param.tpt).tpe
822
- }
846
+ /** Is `formal` a product type which is elementwise compatible with `params`? */
847
+ def ptIsCorrectProduct (formal : Type ) = {
848
+ isFullyDefined(formal, ForceDegree .noBottom) &&
849
+ defn.isProductSubType(formal) &&
850
+ Applications .productSelectorTypes(formal).corresponds(params) {
851
+ (argType, param) =>
852
+ param.tpt.isEmpty || argType <:< typedAheadType(param.tpt).tpe
823
853
}
854
+ }
824
855
825
- val desugared =
826
- if (protoFormals.length == 1 && params.length != 1 && ptIsCorrectProduct(protoFormals.head)) {
827
- desugar.makeTupledFunction(params, fnBody)
828
- }
829
- else {
830
- val inferredParams : List [untpd.ValDef ] =
831
- for ((param, i) <- params.zipWithIndex) yield
832
- if (! param.tpt.isEmpty) param
833
- else cpy.ValDef (param)(
834
- tpt = untpd.TypeTree (
835
- inferredParamType(param, protoFormal(i)).underlyingIfRepeated(isJava = false )))
836
-
837
- // Define result type of closure as the expected type, thereby pushing
838
- // down any implicit searches. We do this even if the expected type is not fully
839
- // defined, which is a bit of a hack. But it's needed to make the following work
840
- // (see typers.scala and printers/PlainPrinter.scala for examples).
841
- //
842
- // def double(x: Char): String = s"$x$x"
843
- // "abc" flatMap double
844
- //
845
- val resultTpt = protoResult match {
846
- case WildcardType (_) => untpd.TypeTree ()
847
- case _ => untpd.TypeTree (protoResult)
848
- }
849
- val inlineable = pt.hasAnnotation(defn.InlineParamAnnot )
850
- desugar.makeClosure(inferredParams, fnBody, resultTpt, inlineable)
856
+ val desugared =
857
+ if (protoFormals.length == 1 && params.length != 1 && ptIsCorrectProduct(protoFormals.head)) {
858
+ desugar.makeTupledFunction(params, fnBody)
859
+ }
860
+ else {
861
+ val inferredParams : List [untpd.ValDef ] =
862
+ for ((param, i) <- params.zipWithIndex) yield
863
+ if (! param.tpt.isEmpty) param
864
+ else cpy.ValDef (param)(
865
+ tpt = untpd.TypeTree (
866
+ inferredParamType(param, protoFormal(i)).underlyingIfRepeated(isJava = false )))
867
+
868
+ // Define result type of closure as the expected type, thereby pushing
869
+ // down any implicit searches. We do this even if the expected type is not fully
870
+ // defined, which is a bit of a hack. But it's needed to make the following work
871
+ // (see typers.scala and printers/PlainPrinter.scala for examples).
872
+ //
873
+ // def double(x: Char): String = s"$x$x"
874
+ // "abc" flatMap double
875
+ //
876
+ val resultTpt = protoResult match {
877
+ case WildcardType (_) => untpd.TypeTree ()
878
+ case _ => untpd.TypeTree (protoResult)
851
879
}
852
- typed(desugared, pt)
853
- }
880
+ val inlineable = pt.hasAnnotation(defn.InlineParamAnnot )
881
+ desugar.makeClosure(inferredParams, fnBody, resultTpt, inlineable)
882
+ }
883
+ typed(desugared, pt)
854
884
}
855
885
856
886
def typedClosure (tree : untpd.Closure , pt : Type )(implicit ctx : Context ): Tree = track(" typedClosure" ) {
0 commit comments