@@ -154,8 +154,8 @@ object CheckCaptures:
154154 traverseChildren(t)
155155 check.traverse(tp)
156156
157- /** Attachment key for boxed curried closures */
158- val BoxedClosure = Property .Key [Type ]
157+ /** Attachment key for bodies of closures, provided they are values */
158+ val ClosureBodyValue = Property .Key [Unit ]
159159
160160class CheckCaptures extends Recheck , SymTransformer :
161161 thisPhase =>
@@ -243,18 +243,20 @@ class CheckCaptures extends Recheck, SymTransformer:
243243 if sym.ownersIterator.exists(_.isTerm) then CaptureSet .Var ()
244244 else CaptureSet .empty)
245245
246- /** For all nested environments up to `limit` or a closed environment perform `op` */
246+ /** For all nested environments up to `limit` or a closed environment perform `op`,
247+ * but skip environmenrts directly enclosing environments of kind ClosureResult.
248+ */
247249 def forallOuterEnvsUpTo (limit : Symbol )(op : Env => Unit )(using Context ): Unit =
248- def recur (env : Env ): Unit =
250+ def recur (env : Env , skip : Boolean ): Unit =
249251 if env.isOpen && env.owner != limit then
250- op(env)
252+ if ! skip then op(env)
251253 if ! env.isOutermost then
252254 var nextEnv = env.outer
253255 if env.owner.isConstructor then
254256 if nextEnv.owner != limit && ! nextEnv.isOutermost then
255257 nextEnv = nextEnv.outer
256- recur(nextEnv)
257- recur(curEnv)
258+ recur(nextEnv, skip = env.kind == EnvKind . ClosureResult )
259+ recur(curEnv, skip = false )
258260
259261 /** Include `sym` in the capture sets of all enclosing environments nested in the
260262 * the environment in which `sym` is defined.
@@ -495,8 +497,7 @@ class CheckCaptures extends Recheck, SymTransformer:
495497 // the second closure `y => e` into the first one. This is an approximation
496498 // of the CC rule which says that a closure contributes captures to its
497499 // environment only if a let-bound reference to the closure is used.
498- capt.println(i " boxing $rhs" )
499- rhs.putAttachment(BoxedClosure , ())
500+ mdef.rhs.putAttachment(ClosureBodyValue , ())
500501 case _ =>
501502 case _ =>
502503 super .recheckBlock(block, pt)
@@ -595,20 +596,19 @@ class CheckCaptures extends Recheck, SymTransformer:
595596 * adding all references in the boxed capture set to the current environment.
596597 */
597598 override def recheck (tree : Tree , pt : Type = WildcardType )(using Context ): Type =
598- if tree.isTerm && (pt.isBoxedCapturing || tree.hasAttachment( BoxedClosure )) then
599- val saved = curEnv
600-
601- tree match
602- case _ : RefTree | closureDef(_ ) =>
603- curEnv = Env (curEnv.owner, EnvKind .Boxed , CaptureSet .Var (), curEnv)
604- case _ =>
605-
599+ val saved = curEnv
600+ tree match
601+ case _ : RefTree | closureDef(_) if pt.isBoxedCapturing =>
602+ curEnv = Env (curEnv.owner, EnvKind . Boxed , CaptureSet . Var (), curEnv)
603+ case _ if tree.hasAttachment( ClosureBodyValue ) =>
604+ curEnv = Env (curEnv.owner, EnvKind .ClosureResult , CaptureSet .Var (), curEnv)
605+ case _ =>
606+ val res =
606607 try super .recheck(tree, pt)
607608 finally curEnv = saved
608- else
609- val res = super .recheck(tree, pt)
610- if tree.isTerm then markFree(res.boxedCaptureSet, tree.srcPos)
611- res
609+ if tree.isTerm && ! pt.isBoxedCapturing then
610+ markFree(res.boxedCaptureSet, tree.srcPos)
611+ res
612612
613613 /** If `tree` is a reference or an application where the result type refers
614614 * to an enclosing class or method parameter of the reference, check that the result type
0 commit comments