@@ -318,7 +318,7 @@ class CheckCaptures extends Recheck, SymTransformer:
318318 * upper approximation.
319319 */
320320 private def interpolate (tp : Type , sym : Symbol , startingVariance : Int = 1 )(using Context ): Unit =
321-
321+
322322 object variances extends TypeTraverser :
323323 variance = startingVariance
324324 val varianceOfVar = EqHashMap [CaptureSet .Var , Int ]()
@@ -335,7 +335,7 @@ class CheckCaptures extends Recheck, SymTransformer:
335335 traverse(rinfo)
336336 case _ =>
337337 traverseChildren(t)
338-
338+
339339 val interpolator = new TypeTraverser :
340340 override def traverse (t : Type ) = t match
341341 case t @ CapturingType (parent, refs) =>
@@ -349,7 +349,7 @@ class CheckCaptures extends Recheck, SymTransformer:
349349 traverse(rinfo)
350350 case _ =>
351351 traverseChildren(t)
352-
352+
353353 variances.traverse(tp)
354354 interpolator.traverse(tp)
355355 end interpolate
@@ -947,28 +947,51 @@ class CheckCaptures extends Recheck, SymTransformer:
947947 * { def $anonfun(...) = ...; closure($anonfun, ...)}
948948 */
949949 override def recheckClosureBlock (mdef : DefDef , expr : Closure , pt : Type )(using Context ): Type =
950+
951+ def matchParams (paramss : List [ParamClause ], pt : Type ): Unit =
952+ // println(i"match $mdef against $pt")
953+ paramss match
954+ case params :: paramss1 => pt match
955+ case defn.PolyFunctionOf (poly : PolyType ) =>
956+ assert(params.hasSameLengthAs(poly.paramInfos))
957+ matchParams(paramss1, poly.instantiate(params.map(_.symbol.typeRef)))
958+ case FunctionOrMethod (argTypes, resType) =>
959+ assert(params.hasSameLengthAs(argTypes), i " $mdef vs $pt, ${params}" )
960+ for (argType, param) <- argTypes.lazyZip(params) do
961+ // println(i"compare $argType against $param")
962+ checkConformsExpr(argType, root.freshToCap(param.asInstanceOf [ValDef ].tpt.nuType), param)
963+ if ccConfig.preTypeClosureResults && ! (isEtaExpansion(mdef) && ccConfig.handleEtaExpansionsSpecially) then
964+ // Check whether the closure's result conforms to the expected type
965+ // This constrains parameter types of the closure which can give better
966+ // error messages.
967+ // But if the closure is an eta expanded method reference it's better to not constrain
968+ // its internals early since that would give error messages in generated code
969+ // which are less intelligible. An example is the line `a = x` in
970+ // neg-custom-args/captures/vars.scala. That's why this code is conditioned.
971+ // to apply only to closures that are not eta expansions.
972+ assert(paramss1.isEmpty)
973+ val respt = root.resultToFresh:
974+ pt match
975+ case defn.RefinedFunctionOf (rinfo) =>
976+ val paramTypes = params.map(_.asInstanceOf [ValDef ].tpt.nuType)
977+ rinfo.instantiate(paramTypes)
978+ case _ =>
979+ resType
980+ val res = root.resultToFresh(mdef.tpt.nuType)
981+ // We need to open existentials here in order not to get vars mixed up in them
982+ // We do the proper check with existentials when we are finished with the closure block.
983+ capt.println(i " pre-check closure $expr of type $res against $respt" )
984+ checkConformsExpr(res, respt, expr)
985+ case _ =>
986+ case Nil =>
987+
950988 openClosures = (mdef.symbol, pt) :: openClosures
989+ // openClosures is needed for errors but currently makes no difference
990+ // TODO follow up on this
951991 try
952- // Constrain closure's parameters and result from the expected type before
953- // rechecking the body.
954- val res = recheckClosure(expr, pt, forceDependent = true )
955- if ! (isEtaExpansion(mdef) && ccConfig.handleEtaExpansionsSpecially) then
956- // Check whether the closure's results conforms to the expected type
957- // This constrains parameter types of the closure which can give better
958- // error messages.
959- // But if the closure is an eta expanded method reference it's better to not constrain
960- // its internals early since that would give error messages in generated code
961- // which are less intelligible. An example is the line `a = x` in
962- // neg-custom-args/captures/vars.scala. That's why this code is conditioned.
963- // to apply only to closures that are not eta expansions.
964- val res1 = root.resultToFresh(res) // TODO: why deep = true?
965- val pt1 = root.resultToFresh(pt)
966- // We need to open existentials here in order not to get vars mixed up in them
967- // We do the proper check with existentials when we are finished with the closure block.
968- capt.println(i " pre-check closure $expr of type $res1 against $pt1" )
969- checkConformsExpr(res1, pt1, expr)
992+ matchParams(mdef.paramss, pt)
970993 recheckDef(mdef, mdef.symbol)
971- res
994+ recheckClosure(expr, pt, forceDependent = true )
972995 finally
973996 openClosures = openClosures.tail
974997 end recheckClosureBlock
0 commit comments