@@ -724,41 +724,70 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
724
724
*/
725
725
var fnBody = tree.body
726
726
727
+ /** A map from parameter names to unique positions where the parameter
728
+ * appears in the argument list of an application.
729
+ */
730
+ var paramIndex = Map [Name , Int ]()
731
+
732
+ /** If parameter `param` appears exactly once as an argument in `args`,
733
+ * the singleton list consisting of its position in `args`, otherwise `Nil`.
734
+ */
735
+ def paramIndices (param : untpd.ValDef , args : List [untpd.Tree ], start : Int ): List [Int ] = args match {
736
+ case arg :: args1 =>
737
+ if (refersTo(arg, param))
738
+ if (paramIndices(param, args1, start + 1 ).isEmpty) start :: Nil
739
+ else Nil
740
+ else paramIndices(param, args1, start + 1 )
741
+ case _ => Nil
742
+ }
743
+
727
744
/** If function is of the form
728
- * (x1, ..., xN) => f(x1, ..., XN)
729
- * the type of `f`, otherwise NoType. (updates `fnBody` as a side effect).
745
+ * (x1, ..., xN) => f(... x1, ..., XN, ...)
746
+ * where each `xi` occurs exactly once in the argument list of `f` (in
747
+ * any order), the type of `f`, otherwise NoType.
748
+ * Updates `fnBody` and `paramIndex` as a side effect.
749
+ * @post: If result exists, `paramIndex` is defined for the name of
750
+ * every parameter in `params`.
730
751
*/
731
752
def calleeType : Type = fnBody match {
732
- case Apply (expr, args) if (args corresponds params)(refersTo) =>
733
- expr match {
734
- case untpd.TypedSplice (expr1) =>
735
- expr1.tpe
736
- case _ =>
737
- val protoArgs = args map (_ withType WildcardType )
738
- val callProto = FunProto (protoArgs, WildcardType , this )
739
- val expr1 = typedExpr(expr, callProto)
740
- fnBody = cpy.Apply (fnBody)(untpd.TypedSplice (expr1), args)
741
- expr1.tpe
742
- }
753
+ case Apply (expr, args) =>
754
+ paramIndex = {
755
+ for (param <- params; idx <- paramIndices(param, args, 0 ))
756
+ yield param.name -> idx
757
+ }.toMap
758
+ if (paramIndex.size == params.length)
759
+ expr match {
760
+ case untpd.TypedSplice (expr1) =>
761
+ expr1.tpe
762
+ case _ =>
763
+ val protoArgs = args map (_ withType WildcardType )
764
+ val callProto = FunProto (protoArgs, WildcardType , this )
765
+ val expr1 = typedExpr(expr, callProto)
766
+ fnBody = cpy.Apply (fnBody)(untpd.TypedSplice (expr1), args)
767
+ expr1.tpe
768
+ }
769
+ else NoType
743
770
case _ =>
744
771
NoType
745
772
}
746
773
747
774
/** Two attempts: First, if expected type is fully defined pick this one.
748
775
* Second, if function is of the form
749
- * (x1, ..., xN) => f(x1, ..., XN)
750
- * and f has a method type MT, pick the corresponding parameter type in MT,
751
- * if this one is fully defined.
776
+ * (x1, ..., xN) => f(... x1, ..., XN, ...)
777
+ * where each `xi` occurs exactly once in the argument list of `f` (in
778
+ * any order), and f has a method type MT, pick the corresponding parameter
779
+ * type in MT, if this one is fully defined.
752
780
* If both attempts fail, issue a "missing parameter type" error.
753
781
*/
754
782
def inferredParamType (param : untpd.ValDef , formal : Type ): Type = {
755
783
if (isFullyDefined(formal, ForceDegree .noBottom)) return formal
756
784
calleeType.widen match {
757
785
case mtpe : MethodType =>
758
- val pos = params indexWhere (_.name == param.name)
786
+ val pos = paramIndex( param.name)
759
787
if (pos < mtpe.paramInfos.length) {
760
788
val ptype = mtpe.paramInfos(pos)
761
- if (isFullyDefined(ptype, ForceDegree .noBottom)) return ptype
789
+ if (isFullyDefined(ptype, ForceDegree .noBottom) && ! ptype.isRepeatedParam)
790
+ return ptype
762
791
}
763
792
case _ =>
764
793
}
0 commit comments