@@ -464,7 +464,7 @@ class CheckCaptures extends Recheck, SymTransformer:
464
464
* environments. At each stage, only include references from `cs` that are outside
465
465
* the environment's owner
466
466
*/
467
- def markFree (cs : CaptureSet , tree : Tree )(using Context ): Unit =
467
+ def markFree (cs : CaptureSet , tree : Tree , addUseInfo : Boolean = true )(using Context ): Unit =
468
468
// A captured reference with the symbol `sym` is visible from the environment
469
469
// if `sym` is not defined inside the owner of the environment.
470
470
inline def isVisibleFromEnv (sym : Symbol , env : Env ) =
@@ -546,7 +546,7 @@ class CheckCaptures extends Recheck, SymTransformer:
546
546
547
547
if ! cs.isAlwaysEmpty then
548
548
recur(cs, curEnv, null )
549
- useInfos += ((tree, cs, curEnv))
549
+ if addUseInfo then useInfos += ((tree, cs, curEnv))
550
550
end markFree
551
551
552
552
/** If capability `c` refers to a parameter that is not implicitly or explicitly
@@ -988,6 +988,8 @@ class CheckCaptures extends Recheck, SymTransformer:
988
988
* - Interpolate contravariant capture set variables in result type.
989
989
*/
990
990
override def recheckValDef (tree : ValDef , sym : Symbol )(using Context ): Type =
991
+ val savedEnv = curEnv
992
+ val runInConstructor = ! sym.isOneOf(Param | ParamAccessor | Lazy | NonMember )
991
993
try
992
994
if sym.is(Module ) then sym.info // Modules are checked by checking the module class
993
995
else
@@ -1006,6 +1008,8 @@ class CheckCaptures extends Recheck, SymTransformer:
1006
1008
" "
1007
1009
disallowBadRootsIn(
1008
1010
tree.tpt.nuType, NoSymbol , i " Mutable $sym" , " have type" , addendum, sym.srcPos)
1011
+ if runInConstructor then
1012
+ pushConstructorEnv()
1009
1013
checkInferredResult(super .recheckValDef(tree, sym), tree)
1010
1014
finally
1011
1015
if ! sym.is(Param ) then
@@ -1015,6 +1019,11 @@ class CheckCaptures extends Recheck, SymTransformer:
1015
1019
// function is compiled since we do not propagate expected types into blocks.
1016
1020
interpolateIfInferred(tree.tpt, sym)
1017
1021
1022
+ if runInConstructor && savedEnv.owner.isClass then
1023
+ curEnv = savedEnv
1024
+ markFree(tree.tpt.nuType.captureSet, tree, addUseInfo = false )
1025
+ end recheckValDef
1026
+
1018
1027
/** Recheck method definitions:
1019
1028
* - check body in a nested environment that tracks uses, in a nested level,
1020
1029
* and in a nested context that knows abaout Contains parameters so that we
@@ -1241,6 +1250,24 @@ class CheckCaptures extends Recheck, SymTransformer:
1241
1250
recheckFinish(result, arg, pt)
1242
1251
*/
1243
1252
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
+
1244
1271
/** The main recheck method does some box adapation for all nodes:
1245
1272
* - If expected type `pt` is boxed and the tree is a lambda or a reference,
1246
1273
* don't propagate free variables.
0 commit comments