@@ -464,7 +464,7 @@ class CheckCaptures extends Recheck, SymTransformer:
464464 * environments. At each stage, only include references from `cs` that are outside
465465 * the environment's owner
466466 */
467- def markFree (cs : CaptureSet , tree : Tree )(using Context ): Unit =
467+ def markFree (cs : CaptureSet , tree : Tree , addUseInfo : Boolean = true )(using Context ): Unit =
468468 // A captured reference with the symbol `sym` is visible from the environment
469469 // if `sym` is not defined inside the owner of the environment.
470470 inline def isVisibleFromEnv (sym : Symbol , env : Env ) =
@@ -546,7 +546,7 @@ class CheckCaptures extends Recheck, SymTransformer:
546546
547547 if ! cs.isAlwaysEmpty then
548548 recur(cs, curEnv, null )
549- useInfos += ((tree, cs, curEnv))
549+ if addUseInfo then useInfos += ((tree, cs, curEnv))
550550 end markFree
551551
552552 /** If capability `c` refers to a parameter that is not implicitly or explicitly
@@ -988,6 +988,8 @@ class CheckCaptures extends Recheck, SymTransformer:
988988 * - Interpolate contravariant capture set variables in result type.
989989 */
990990 override def recheckValDef (tree : ValDef , sym : Symbol )(using Context ): Type =
991+ val savedEnv = curEnv
992+ val runInConstructor = ! sym.isOneOf(Param | ParamAccessor | Lazy | NonMember )
991993 try
992994 if sym.is(Module ) then sym.info // Modules are checked by checking the module class
993995 else
@@ -1006,6 +1008,8 @@ class CheckCaptures extends Recheck, SymTransformer:
10061008 " "
10071009 disallowBadRootsIn(
10081010 tree.tpt.nuType, NoSymbol , i " Mutable $sym" , " have type" , addendum, sym.srcPos)
1011+ if runInConstructor then
1012+ pushConstructorEnv()
10091013 checkInferredResult(super .recheckValDef(tree, sym), tree)
10101014 finally
10111015 if ! sym.is(Param ) then
@@ -1015,6 +1019,11 @@ class CheckCaptures extends Recheck, SymTransformer:
10151019 // function is compiled since we do not propagate expected types into blocks.
10161020 interpolateIfInferred(tree.tpt, sym)
10171021
1022+ if runInConstructor && savedEnv.owner.isClass then
1023+ curEnv = savedEnv
1024+ markFree(tree.tpt.nuType.captureSet, tree, addUseInfo = false )
1025+ end recheckValDef
1026+
10181027 /** Recheck method definitions:
10191028 * - check body in a nested environment that tracks uses, in a nested level,
10201029 * and in a nested context that knows abaout Contains parameters so that we
@@ -1241,6 +1250,24 @@ class CheckCaptures extends Recheck, SymTransformer:
12411250 recheckFinish(result, arg, pt)
12421251 */
12431252
1253+ /** If environment is owned by a class, run in a new environment owned by
1254+ * its primary constructor instead.
1255+ */
1256+ def pushConstructorEnv ()(using Context ): Unit =
1257+ if curEnv.owner.isClass then
1258+ val constr = curEnv.owner.primaryConstructor
1259+ if constr.exists then
1260+ val constrSet = capturedVars(constr)
1261+ if capturedVars(constr) ne CaptureSet .empty then
1262+ curEnv = Env (constr, EnvKind .Regular , constrSet, curEnv)
1263+
1264+ override def recheckStat (stat : Tree )(using Context ): Unit =
1265+ val saved = curEnv
1266+ if ! stat.isInstanceOf [MemberDef ] then
1267+ pushConstructorEnv()
1268+ try recheck(stat)
1269+ finally curEnv = saved
1270+
12441271 /** The main recheck method does some box adapation for all nodes:
12451272 * - If expected type `pt` is boxed and the tree is a lambda or a reference,
12461273 * don't propagate free variables.
0 commit comments