@@ -81,7 +81,7 @@ object CheckCaptures:
8181  end  Env 
8282
8383  def  definesEnv (sym : Symbol )(using  Context ):  Boolean  = 
84-     sym.is(Method ) ||  sym.isClass
84+     sym.is(Method ) ||  sym.isClass  ||  sym.is( Lazy ) 
8585
8686  /**  Similar normal substParams, but this is an approximating type map that 
8787   *  maps parameters in contravariant capture sets to the empty set. 
@@ -225,7 +225,7 @@ object CheckCaptures:
225225      def  needsSepCheck :  Boolean 
226226
227227      /**  If a tree is an argument for which needsSepCheck is true, 
228-        *  the type of the formal paremeter  corresponding to the argument. 
228+        *  the type of the formal parameter  corresponding to the argument. 
229229       */  
230230      def  formalType :  Type 
231231
@@ -441,7 +441,7 @@ class CheckCaptures extends Recheck, SymTransformer:
441441     */  
442442    def  capturedVars (sym : Symbol )(using  Context ):  CaptureSet  = 
443443      myCapturedVars.getOrElseUpdate(sym,
444-         if  sym.isTerm ||  ! sym.owner.isStaticOwner
444+         if  sym.isTerm ||  ! sym.owner.isStaticOwner  ||  sym.is( Lazy )  //  FIXME: are lazy vals in static owners a thing? 
445445        then  CaptureSet .Var (sym, nestedOK =  false )
446446        else  CaptureSet .empty)
447447
@@ -655,8 +655,10 @@ class CheckCaptures extends Recheck, SymTransformer:
655655     */  
656656    override  def  recheckIdent (tree : Ident , pt : Type )(using  Context ):  Type  = 
657657      val  sym  =  tree.symbol
658-       if  sym.is(Method ) then 
659-         //  If ident refers to a parameterless method, charge its cv to the environment
658+       if  sym.is(Method ) ||  sym.is(Lazy ) then 
659+         //  If ident refers to a parameterless method or lazy val, charge its cv to the environment.
660+         //  Lazy vals are like parameterless methods: accessing them may trigger initialization
661+         //  that uses captured references.
660662        includeCallCaptures(sym, sym.info, tree)
661663      else  if  sym.exists &&  ! sym.isStatic then 
662664        markPathFree(sym.termRef, pt, tree)
@@ -1083,6 +1085,7 @@ class CheckCaptures extends Recheck, SymTransformer:
10831085     *   - for externally visible definitions: check that their inferred type 
10841086     *     does not refine what was known before capture checking. 
10851087     *   - Interpolate contravariant capture set variables in result type. 
1088+      *   - for lazy vals: create a nested environment to track captures (similar to methods) 
10861089     */  
10871090    override  def  recheckValDef (tree : ValDef , sym : Symbol )(using  Context ):  Type  = 
10881091      val  savedEnv  =  curEnv
@@ -1105,8 +1108,16 @@ class CheckCaptures extends Recheck, SymTransformer:
11051108                " " 
11061109            disallowBadRootsIn(
11071110              tree.tpt.nuType, NoSymbol , i " Mutable  $sym" , " have type" 
1108-           if  runInConstructor then 
1111+ 
1112+           //  Lazy vals need their own environment to track captures from their RHS,
1113+           //  similar to how methods work
1114+           if  sym.is(Lazy ) then 
1115+             val  localSet  =  capturedVars(sym)
1116+             if  localSet ne CaptureSet .empty then 
1117+               curEnv =  Env (sym, EnvKind .Regular , localSet, curEnv, nestedClosure =  NoSymbol )
1118+           else  if  runInConstructor then 
11091119            pushConstructorEnv()
1120+ 
11101121          checkInferredResult(super .recheckValDef(tree, sym), tree)
11111122      finally 
11121123        if  ! sym.is(Param ) then 
@@ -1120,6 +1131,9 @@ class CheckCaptures extends Recheck, SymTransformer:
11201131        if  runInConstructor &&  savedEnv.owner.isClass then 
11211132          curEnv =  savedEnv
11221133          markFree(declaredCaptures, tree, addUseInfo =  false )
1134+         else  if  sym.is(Lazy ) then 
1135+           //  Restore environment after checking lazy val
1136+           curEnv =  savedEnv
11231137
11241138        if  sym.owner.isStaticOwner &&  ! declaredCaptures.elems.isEmpty &&  sym !=  defn.captureRoot then 
11251139          def  where  = 
0 commit comments