@@ -317,20 +317,42 @@ class CheckCaptures extends Recheck, SymTransformer:
317317 /** Instantiate capture set variables appearing contra-variantly to their
318318 * upper approximation.
319319 */
320- private def interpolator (sym : Symbol , startingVariance : Int = 1 )(using Context ) = new TypeTraverser :
321- variance = startingVariance
322- override def traverse (t : Type ) = t match
323- case t @ CapturingType (parent, refs) =>
324- refs match
325- case refs : CaptureSet .Var if ! refs.isConst =>
326- if variance < 0 then refs.solve()
327- else refs.markSolved(provisional = ! sym.isMutableVar)
328- case _ =>
329- traverse(parent)
330- case t @ defn.RefinedFunctionOf (rinfo) =>
331- traverse(rinfo)
332- case _ =>
333- traverseChildren(t)
320+ private def interpolate (tp : Type , sym : Symbol , startingVariance : Int = 1 )(using Context ): Unit =
321+
322+ object variances extends TypeTraverser :
323+ variance = startingVariance
324+ val varianceOfVar = EqHashMap [CaptureSet .Var , Int ]()
325+ override def traverse (t : Type ) = t match
326+ case t @ CapturingType (parent, refs) =>
327+ refs match
328+ case refs : CaptureSet .Var if ! refs.isConst =>
329+ varianceOfVar(refs) = varianceOfVar.get(refs) match
330+ case Some (v0) => if v0 == 0 then 0 else (v0 + variance) / 2
331+ case None => variance
332+ case _ =>
333+ traverse(parent)
334+ case t @ defn.RefinedFunctionOf (rinfo) =>
335+ traverse(rinfo)
336+ case _ =>
337+ traverseChildren(t)
338+
339+ val interpolator = new TypeTraverser :
340+ override def traverse (t : Type ) = t match
341+ case t @ CapturingType (parent, refs) =>
342+ refs match
343+ case refs : CaptureSet .Var if ! refs.isConst =>
344+ if variances.varianceOfVar(refs) < 0 then refs.solve()
345+ else refs.markSolved(provisional = ! sym.isMutableVar)
346+ case _ =>
347+ traverse(parent)
348+ case t @ defn.RefinedFunctionOf (rinfo) =>
349+ traverse(rinfo)
350+ case _ =>
351+ traverseChildren(t)
352+
353+ variances.traverse(tp)
354+ interpolator.traverse(tp)
355+ end interpolate
334356
335357 /* Also set any previously unset owners of toplevel Fresh instances to improve
336358 * error diagnostics in separation checking.
@@ -354,14 +376,14 @@ class CheckCaptures extends Recheck, SymTransformer:
354376 /** If `tpt` is an inferred type, interpolate capture set variables appearing contra-
355377 * variantly in it. Also anchor Fresh instances with anchorCaps.
356378 */
357- private def interpolateVarsIn (tpt : Tree , sym : Symbol )(using Context ): Unit =
379+ private def interpolateIfInferred (tpt : Tree , sym : Symbol )(using Context ): Unit =
358380 if tpt.isInstanceOf [InferredTypeTree ] then
359- interpolator(sym).traverse( tpt.nuType)
381+ interpolate( tpt.nuType, sym )
360382 .showing(i " solved vars for $sym in ${tpt.nuType}" , capt)
361383 anchorCaps(sym).traverse(tpt.nuType)
362- for msg <- ccState.approxWarnings do
363- report.warning(msg, tpt.srcPos)
364- ccState.approxWarnings.clear()
384+ for msg <- ccState.approxWarnings do
385+ report.warning(msg, tpt.srcPos)
386+ ccState.approxWarnings.clear()
365387
366388 /** Assert subcapturing `cs1 <: cs2` (available for debugging, otherwise unused) */
367389 def assertSub (cs1 : CaptureSet , cs2 : CaptureSet )(using Context ) =
@@ -989,7 +1011,7 @@ class CheckCaptures extends Recheck, SymTransformer:
9891011 // for more info from the context, so we cannot interpolate. Note that we cannot
9901012 // expect to have all necessary info available at the point where the anonymous
9911013 // function is compiled since we do not propagate expected types into blocks.
992- interpolateVarsIn (tree.tpt, sym)
1014+ interpolateIfInferred (tree.tpt, sym)
9931015
9941016 /** Recheck method definitions:
9951017 * - check body in a nested environment that tracks uses, in a nested level,
@@ -1035,7 +1057,7 @@ class CheckCaptures extends Recheck, SymTransformer:
10351057 if ! sym.isAnonymousFunction then
10361058 // Anonymous functions propagate their type to the enclosing environment
10371059 // so it is not in general sound to interpolate their types.
1038- interpolateVarsIn (tree.tpt, sym)
1060+ interpolateIfInferred (tree.tpt, sym)
10391061 curEnv = saved
10401062 end recheckDefDef
10411063
@@ -1781,7 +1803,7 @@ class CheckCaptures extends Recheck, SymTransformer:
17811803 inContext(ctx.fresh.setOwner(root)):
17821804 checkSelfAgainstParents(root, root.baseClasses)
17831805 val selfType = root.asClass.classInfo.selfType
1784- interpolator( root, startingVariance = - 1 ).traverse(selfType )
1806+ interpolate(selfType, root, startingVariance = - 1 )
17851807 selfType match
17861808 case CapturingType (_, refs : CaptureSet .Var )
17871809 if ! root.isEffectivelySealed
0 commit comments