@@ -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.
@@ -532,8 +534,7 @@ class CheckCaptures extends Recheck, SymTransformer:
532
534
// the second closure `y => e` into the first one. This is an approximation
533
535
// of the CC rule which says that a closure contributes captures to its
534
536
// 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 , ())
537
538
case _ =>
538
539
case _ =>
539
540
super .recheckBlock(block, pt)
@@ -632,20 +633,19 @@ class CheckCaptures extends Recheck, SymTransformer:
632
633
* adding all references in the boxed capture set to the current environment.
633
634
*/
634
635
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 =
643
644
try super .recheck(tree, pt)
644
645
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
649
649
650
650
/** If `tree` is a reference or an application where the result type refers
651
651
* to an enclosing class or method parameter of the reference, check that the result type
0 commit comments