@@ -154,8 +154,8 @@ object CheckCaptures:
154
154
traverseChildren(t)
155
155
check.traverse(tp)
156
156
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 ]
159
159
160
160
class CheckCaptures extends Recheck , SymTransformer :
161
161
thisPhase =>
@@ -243,18 +243,20 @@ class CheckCaptures extends Recheck, SymTransformer:
243
243
if sym.ownersIterator.exists(_.isTerm) then CaptureSet .Var ()
244
244
else CaptureSet .empty)
245
245
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
+ */
247
249
def forallOuterEnvsUpTo (limit : Symbol )(op : Env => Unit )(using Context ): Unit =
248
- def recur (env : Env ): Unit =
250
+ def recur (env : Env , skip : Boolean ): Unit =
249
251
if env.isOpen && env.owner != limit then
250
- op(env)
252
+ if ! skip then op(env)
251
253
if ! env.isOutermost then
252
254
var nextEnv = env.outer
253
255
if env.owner.isConstructor then
254
256
if nextEnv.owner != limit && ! nextEnv.isOutermost then
255
257
nextEnv = nextEnv.outer
256
- recur(nextEnv)
257
- recur(curEnv)
258
+ recur(nextEnv, skip = env.kind == EnvKind . ClosureResult )
259
+ recur(curEnv, skip = false )
258
260
259
261
/** Include `sym` in the capture sets of all enclosing environments nested in the
260
262
* the environment in which `sym` is defined.
@@ -495,8 +497,7 @@ class CheckCaptures extends Recheck, SymTransformer:
495
497
// the second closure `y => e` into the first one. This is an approximation
496
498
// of the CC rule which says that a closure contributes captures to its
497
499
// 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 , ())
500
501
case _ =>
501
502
case _ =>
502
503
super .recheckBlock(block, pt)
@@ -595,20 +596,19 @@ class CheckCaptures extends Recheck, SymTransformer:
595
596
* adding all references in the boxed capture set to the current environment.
596
597
*/
597
598
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 =
606
607
try super .recheck(tree, pt)
607
608
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
612
612
613
613
/** If `tree` is a reference or an application where the result type refers
614
614
* to an enclosing class or method parameter of the reference, check that the result type
0 commit comments