@@ -303,7 +303,6 @@ private final class ClassDefChecker(classDef: ClassDef,
303
303
val thisType = if (static) NoType else instanceThisType
304
304
val bodyEnv = Env .fromParams(params)
305
305
.withThisType(thisType)
306
- .withInConstructor(isConstructor)
307
306
308
307
if (isConstructor)
309
308
checkConstructorBody(body, bodyEnv)
@@ -328,12 +327,13 @@ private final class ClassDefChecker(classDef: ClassDef,
328
327
329
328
val startEnv = Env .fromParams(classDef.jsClassCaptures.getOrElse(Nil ) ++ params ++ restParam)
330
329
.withHasNewTarget(true )
331
- .withInConstructor(true )
332
330
333
331
val envJustBeforeSuper = checkBlockStats(body.beforeSuper, startEnv)
334
332
checkTreeOrSpreads(body.superCall.args, envJustBeforeSuper)
335
333
val envJustAfterSuper = envJustBeforeSuper.withThisType(instanceThisType)
336
- checkBlockStats(body.afterSuper, envJustAfterSuper)
334
+ val afterSuperStoreModulesHandled =
335
+ handleStoreModulesAfterSuperCtorCall(body.afterSuper)
336
+ checkBlockStats(afterSuperStoreModulesHandled, envJustAfterSuper)
337
337
}
338
338
339
339
private def checkJSMethodDef (methodDef : JSMethodDef ): Unit = withPerMethodState {
@@ -525,12 +525,10 @@ private final class ClassDefChecker(classDef: ClassDef,
525
525
* - There is no such `ApplyStatically` anywhere else in the body.
526
526
* - `cls` must be the enclosing class or its direct superclass.
527
527
* - In the statements before the delegate constructor call, and within
528
- * `args`:
529
- * - `This()` cannot be used except in `Assign(Select(This(), _), _)`,
530
- * i.e., to assign to a field (but not read from one).
531
- * - `StoreModule()` cannot be used.
528
+ * `args`, `This()` cannot be used except in `Assign(Select(This(), _), _)`,
529
+ * i.e., to assign to a field (but not read from one).
532
530
* - After the delegate constructor call, `This` can be used without
533
- * restriction.
531
+ * restriction. Moreover, we can have `StoreModule`s at the top-level.
534
532
*
535
533
* After the optimizer, there may be no delegate constructor call at all.
536
534
* This frequently happens as the optimizer inlines super constructor
@@ -561,7 +559,9 @@ private final class ClassDefChecker(classDef: ClassDef,
561
559
if (! postOptimizer)
562
560
reportError(i " Constructor must contain a delegate constructor call " )
563
561
564
- checkBlockStats(bodyStats, bodyEnv)
562
+ val bodyStatsStoreModulesHandled =
563
+ handleStoreModulesAfterSuperCtorCall(bodyStats)
564
+ checkBlockStats(bodyStatsStoreModulesHandled, bodyEnv)
565
565
} else {
566
566
val (delegateCtorCall : ApplyStatically ) :: afterDelegateCtor = rest
567
567
val ApplyStatically (_, receiver, cls, MethodIdent (ctor), args) = delegateCtorCall
@@ -585,11 +585,23 @@ private final class ClassDefChecker(classDef: ClassDef,
585
585
}
586
586
}
587
587
588
- checkBlockStats(afterDelegateCtor, unrestrictedEnv)
588
+ val afterDelegateCtorStoreModulesHandled =
589
+ handleStoreModulesAfterSuperCtorCall(afterDelegateCtor)
590
+ checkBlockStats(afterDelegateCtorStoreModulesHandled, unrestrictedEnv)
589
591
}
590
592
}
591
593
}
592
594
595
+ private def handleStoreModulesAfterSuperCtorCall (trees : List [Tree ]): List [Tree ] = {
596
+ /* If StoreModule's are allowed, there is nothing left to check about them,
597
+ * so we filter them out.
598
+ */
599
+ if (classDef.kind.hasModuleAccessor)
600
+ trees.filter(! _.isInstanceOf [StoreModule ])
601
+ else
602
+ trees
603
+ }
604
+
593
605
private def checkBlockStats (stats : List [Tree ], env : Env ): Env = {
594
606
stats.foldLeft(env) { (prevEnv, stat) =>
595
607
checkTree(stat, prevEnv)
@@ -717,14 +729,7 @@ private final class ClassDefChecker(classDef: ClassDef,
717
729
case _ : LoadModule =>
718
730
719
731
case StoreModule () =>
720
- if (! classDef.kind.hasModuleAccessor)
721
- reportError(i " Illegal StoreModule inside class of kind ${classDef.kind}" )
722
- if (! env.inConstructor)
723
- reportError(i " Illegal StoreModule outside of constructor " )
724
- if (env.thisType == NoType ) // can happen before JSSuperConstructorCall in JSModuleClass
725
- reportError(i " Cannot find `this` in scope for StoreModule() " )
726
- if (env.isThisRestricted)
727
- reportError(i " Restricted use of `this` for StoreModule() before super constructor call " )
732
+ reportError(i " Illegal StoreModule " )
728
733
729
734
case Select (qualifier, _) =>
730
735
checkTree(qualifier, env)
@@ -1063,8 +1068,6 @@ object ClassDefChecker {
1063
1068
val locals : Map [LocalName , LocalDef ],
1064
1069
/** Return types by label. */
1065
1070
val returnLabels : Set [LabelName ],
1066
- /** Whether we are in a constructor of the class. */
1067
- val inConstructor : Boolean ,
1068
1071
/** Whether usages of `this` are restricted in this scope. */
1069
1072
val isThisRestricted : Boolean
1070
1073
) {
@@ -1082,9 +1085,6 @@ object ClassDefChecker {
1082
1085
def withLabel (label : LabelName ): Env =
1083
1086
copy(returnLabels = returnLabels + label)
1084
1087
1085
- def withInConstructor (inConstructor : Boolean ): Env =
1086
- copy(inConstructor = inConstructor)
1087
-
1088
1088
def withIsThisRestricted (isThisRestricted : Boolean ): Env =
1089
1089
copy(isThisRestricted = isThisRestricted)
1090
1090
@@ -1093,11 +1093,9 @@ object ClassDefChecker {
1093
1093
thisType : Type = thisType,
1094
1094
locals : Map [LocalName , LocalDef ] = locals,
1095
1095
returnLabels : Set [LabelName ] = returnLabels,
1096
- inConstructor : Boolean = inConstructor,
1097
1096
isThisRestricted : Boolean = isThisRestricted
1098
1097
): Env = {
1099
- new Env (hasNewTarget, thisType, locals, returnLabels, inConstructor,
1100
- isThisRestricted)
1098
+ new Env (hasNewTarget, thisType, locals, returnLabels, isThisRestricted)
1101
1099
}
1102
1100
}
1103
1101
@@ -1108,7 +1106,6 @@ object ClassDefChecker {
1108
1106
thisType = NoType ,
1109
1107
locals = Map .empty,
1110
1108
returnLabels = Set .empty,
1111
- inConstructor = false ,
1112
1109
isThisRestricted = false
1113
1110
)
1114
1111
}
@@ -1123,7 +1120,6 @@ object ClassDefChecker {
1123
1120
thisType = NoType ,
1124
1121
paramLocalDefs.toMap,
1125
1122
Set .empty,
1126
- inConstructor = false ,
1127
1123
isThisRestricted = false
1128
1124
)
1129
1125
}
0 commit comments