@@ -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.
@@ -532,8 +534,7 @@ class CheckCaptures extends Recheck, SymTransformer:
532534 // the second closure `y => e` into the first one. This is an approximation
533535 // of the CC rule which says that a closure contributes captures to its
534536 // environment only if a let-bound reference to the closure is used.
535- capt.println(i " boxing $rhs" )
536- rhs.putAttachment(BoxedClosure , ())
537+ mdef.rhs.putAttachment(ClosureBodyValue , ())
537538 case _ =>
538539 case _ =>
539540 super .recheckBlock(block, pt)
@@ -632,20 +633,19 @@ class CheckCaptures extends Recheck, SymTransformer:
632633 * adding all references in the boxed capture set to the current environment.
633634 */
634635 override def recheck (tree : Tree , pt : Type = WildcardType )(using Context ): Type =
635- if tree.isTerm && (pt.isBoxedCapturing || tree.hasAttachment( BoxedClosure )) then
636- val saved = curEnv
637-
638- tree match
639- case _ : RefTree | closureDef(_ ) =>
640- curEnv = Env (curEnv.owner, EnvKind .Boxed , CaptureSet .Var (), curEnv)
641- case _ =>
642-
636+ val saved = curEnv
637+ tree match
638+ case _ : RefTree | closureDef(_) if pt.isBoxedCapturing =>
639+ curEnv = Env (curEnv.owner, EnvKind . Boxed , CaptureSet . Var (), curEnv)
640+ case _ if tree.hasAttachment( ClosureBodyValue ) =>
641+ curEnv = Env (curEnv.owner, EnvKind .ClosureResult , CaptureSet .Var (), curEnv)
642+ case _ =>
643+ val res =
643644 try super .recheck(tree, pt)
644645 finally curEnv = saved
645- else
646- val res = super .recheck(tree, pt)
647- if tree.isTerm then markFree(res.boxedCaptureSet, tree.srcPos)
648- res
646+ if tree.isTerm && ! pt.isBoxedCapturing then
647+ markFree(res.boxedCaptureSet, tree.srcPos)
648+ res
649649
650650 /** If `tree` is a reference or an application where the result type refers
651651 * to an enclosing class or method parameter of the reference, check that the result type
0 commit comments