Skip to content

Commit c819cb1

Browse files
committed
Make Symbol accesses null-safe
1 parent 64f7249 commit c819cb1

14 files changed

+67
-64
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -521,20 +521,20 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
521521
/*
522522
* must-single-thread
523523
*/
524-
def fieldLoad( field: Symbol, hostClass: Symbol = null): Unit = fieldOp(field, isLoad = true, hostClass)
524+
def fieldLoad( field: Symbol, hostClass: Symbol | Null = null): Unit = fieldOp(field, isLoad = true, hostClass)
525525

526526
/*
527527
* must-single-thread
528528
*/
529-
def fieldStore(field: Symbol, hostClass: Symbol = null): Unit = fieldOp(field, isLoad = false, hostClass)
529+
def fieldStore(field: Symbol, hostClass: Symbol | Null = null): Unit = fieldOp(field, isLoad = false, hostClass)
530530

531531
/*
532532
* must-single-thread
533533
*/
534-
private def fieldOp(field: Symbol, isLoad: Boolean, specificReceiver: Symbol): Unit = {
534+
private def fieldOp(field: Symbol, isLoad: Boolean, specificReceiver: Symbol | Null): Unit = {
535535
val useSpecificReceiver = specificReceiver != null && !field.isScalaStatic
536536

537-
val owner = internalName(if (useSpecificReceiver) specificReceiver else field.owner)
537+
val owner = internalName(if (useSpecificReceiver) specificReceiver.nn else field.owner)
538538
val fieldJName = field.javaSimpleName
539539
val fieldDescr = symInfoTK(field).descriptor
540540
val isStatic = field.isStaticMember
@@ -629,7 +629,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
629629
if (earlyReturnVar == null) {
630630
earlyReturnVar = locals.makeLocal(returnType, "earlyReturnVar", expr.tpe, expr.span)
631631
}
632-
locals.store(earlyReturnVar)
632+
locals.store(earlyReturnVar.nn)
633633
}
634634
bc goTo nextCleanup
635635
shouldEmitCleanup = true
@@ -853,7 +853,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
853853
bc.invokevirtual(target, sym.javaSimpleName, methodBType.descriptor)
854854
generatedType = methodBType.returnType
855855
} else {
856-
val receiverClass = if (!invokeStyle.isVirtual) null else {
856+
val receiverClass: Symbol | Null = if (!invokeStyle.isVirtual) null else {
857857
// receiverClass is used in the bytecode to as the method receiver. using sym.owner
858858
// may lead to IllegalAccessErrors, see 9954eaf / aladdin bug 455.
859859
val qualSym = qual.tpe.typeSymbol
@@ -1389,16 +1389,16 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
13891389
* invocation instruction, otherwise `method.owner`. A specific receiver class is needed to
13901390
* prevent an IllegalAccessError, (aladdin bug 455).
13911391
*/
1392-
def genCallMethod(method: Symbol, style: InvokeStyle, pos: Span = NoSpan, specificReceiver: Symbol = null): BType = {
1392+
def genCallMethod(method: Symbol, style: InvokeStyle, pos: Span = NoSpan, specificReceiver: Symbol | Null = null): BType = {
13931393
val methodOwner = method.owner
13941394

13951395
// the class used in the invocation's method descriptor in the classfile
1396-
val receiverClass = {
1396+
val receiverClass: Symbol = {
13971397
if (specificReceiver != null)
13981398
assert(style.isVirtual || specificReceiver == methodOwner, s"specificReceiver can only be specified for virtual calls. $method - $specificReceiver")
13991399

1400-
val useSpecificReceiver = specificReceiver != null && !defn.isBottomClass(specificReceiver) && !method.isScalaStatic
1401-
val receiver = if (useSpecificReceiver) specificReceiver else methodOwner
1400+
val useSpecificReceiver = specificReceiver != null && !defn.isBottomClass(specificReceiver.nn) && !method.isScalaStatic
1401+
val receiver = if (useSpecificReceiver) specificReceiver.nn else methodOwner
14021402

14031403
// workaround for a JVM bug: https://bugs.openjdk.java.net/browse/JDK-8154587
14041404
// when an interface method overrides a member of Object (note that all interfaces implicitly
@@ -1432,7 +1432,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
14321432
val bmType = asmMethodType(method)
14331433
val mdescr = bmType.descriptor
14341434

1435-
val isInterface = isEmittedInterface(receiverClass)
1435+
val isInterface = isEmittedInterface(receiverClass.nn)
14361436
import InvokeStyle._
14371437
if (style == Super) {
14381438
if (isInterface && !method.is(JavaDefined)) {

compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
8787
var cnode: ClassNode1 = null
8888
var thisName: String = null // the internal name of the class being emitted
8989

90-
var claszSymbol: Symbol = null
90+
var claszSymbol: Symbol = _
9191
var isCZParcelable = false
9292
var isCZStaticModule = false
9393

@@ -364,9 +364,9 @@ trait BCodeSkelBuilder extends BCodeHelpers {
364364
var jMethodName: String = null
365365
var isMethSymStaticCtor = false
366366
var returnType: BType = null
367-
var methSymbol: Symbol = null
367+
var methSymbol: Symbol = _
368368
// used by genLoadTry() and genSynchronized()
369-
var earlyReturnVar: Symbol = null
369+
var earlyReturnVar: Symbol | Null = null
370370
var shouldEmitCleanup = false
371371
// stack tracking
372372
var stackHeight = 0

compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder {
3636
// if the synchronized block returns a result, store it in a local variable.
3737
// Just leaving it on the stack is not valid in MSIL (stack is cleaned when leaving try-blocks).
3838
val hasResult = (expectedType != UNIT)
39-
val monitorResult: Symbol = if (hasResult) locals.makeLocal(tpeTK(args.head), "monitorResult", defn.ObjectType, tree.span) else null
39+
val monitorResult: Symbol | Null = if (hasResult) locals.makeLocal(tpeTK(args.head), "monitorResult", defn.ObjectType, tree.span) else null
4040

4141
/* ------ (1) pushing and entering the monitor, also keeping a reference to it in a local var. ------ */
4242
genLoadQualifier(fun)
@@ -55,7 +55,7 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder {
5555
registerCleanup(monCleanup)
5656
genLoad(args.head, expectedType /* toTypeKind(tree.tpe.resultType) */)
5757
unregisterCleanup(monCleanup)
58-
if (hasResult) { locals.store(monitorResult) }
58+
if (hasResult) { locals.store(monitorResult.nn) }
5959
nopIfNeeded(startProtected)
6060
val endProtected = currProgramPoint()
6161

@@ -66,7 +66,7 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder {
6666
*/
6767
locals.load(monitor)
6868
emit(asm.Opcodes.MONITOREXIT)
69-
if (hasResult) { locals.load(monitorResult) }
69+
if (hasResult) { locals.load(monitorResult.uncheckedNN) }
7070
val postHandler = new asm.Label
7171
bc goTo postHandler
7272

@@ -214,7 +214,7 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder {
214214
* please notice `tmp` has type tree.tpe, while `earlyReturnVar` has the method return type.
215215
* Because those two types can be different, dedicated vars are needed.
216216
*/
217-
val tmp = if (guardResult) locals.makeLocal(tpeTK(tree), "tmp", tree.tpe, tree.span) else null
217+
val tmp: Symbol | Null = if (guardResult) locals.makeLocal(tpeTK(tree), "tmp", tree.tpe, tree.span) else null
218218

219219
/*
220220
* upon early return from the try-body or one of its EHs (but not the EH-version of the finally-clause)
@@ -375,8 +375,8 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder {
375375
cleanups match {
376376
case Nil =>
377377
if (earlyReturnVar != null) {
378-
locals.load(earlyReturnVar)
379-
bc.emitRETURN(locals(earlyReturnVar).tk)
378+
locals.load(earlyReturnVar.uncheckedNN)
379+
bc.emitRETURN(locals(earlyReturnVar.uncheckedNN).tk)
380380
} else {
381381
bc emitRETURN UNIT
382382
}
@@ -396,15 +396,15 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder {
396396
}
397397

398398
/* `tmp` (if non-null) is the symbol of the local-var used to preserve the result of the try-body, see `guardResult` */
399-
def emitFinalizer(finalizer: Tree, tmp: Symbol, isDuplicate: Boolean): Unit = {
399+
def emitFinalizer(finalizer: Tree, tmp: Symbol | Null, isDuplicate: Boolean): Unit = {
400400
var saved: immutable.Map[ /* Labeled */ Symbol, (BType, LoadDestination) ] = null
401401
if (isDuplicate) {
402402
saved = jumpDest
403403
}
404404
// when duplicating, the above guarantees new asm.Labels are used for LabelDefs contained in the finalizer (their vars are reused, that's ok)
405-
if (tmp != null) { locals.store(tmp) }
405+
if (tmp != null) { locals.store(tmp.uncheckedNN) }
406406
genLoad(finalizer, UNIT)
407-
if (tmp != null) { locals.load(tmp) }
407+
if (tmp != null) { locals.load(tmp.uncheckedNN) }
408408
if (isDuplicate) {
409409
jumpDest = saved
410410
}

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ class JSCodeGen()(using genCtx: Context) {
7272
private val generatedClasses = mutable.ListBuffer.empty[js.ClassDef]
7373
private val generatedStaticForwarderClasses = mutable.ListBuffer.empty[(Symbol, js.ClassDef)]
7474

75-
val currentClassSym = new ScopedVar[Symbol]
76-
private val currentMethodSym = new ScopedVar[Symbol]
75+
val currentClassSym = new ScopedVar[Symbol | Null]
76+
private val currentMethodSym = new ScopedVar[Symbol | Null]
7777
private val localNames = new ScopedVar[LocalNameGenerator]
7878
private val thisLocalVarIdent = new ScopedVar[Option[js.LocalIdent]]
7979
private val isModuleInitialized = new ScopedVar[ScopedVar.VarBox[Boolean]]
@@ -126,7 +126,7 @@ class JSCodeGen()(using genCtx: Context) {
126126
implicit def implicitLocalNames: LocalNameGenerator = localNames.get
127127

128128
def currentThisType: jstpe.Type = {
129-
encodeClassType(currentClassSym) match {
129+
encodeClassType(currentClassSym.get.nn) match {
130130
case tpe @ jstpe.ClassType(cls) =>
131131
jstpe.BoxedClassToPrimType.getOrElse(cls, tpe)
132132
case tpe =>
@@ -856,7 +856,7 @@ class JSCodeGen()(using genCtx: Context) {
856856
/** Gen definitions for the fields of a class. */
857857
private def genClassFields(td: TypeDef): List[js.MemberDef] = {
858858
val classSym = td.symbol.asClass
859-
assert(currentClassSym.get == classSym,
859+
assert(currentClassSym.get eq classSym,
860860
"genClassFields called with a ClassDef other than the current one")
861861

862862
val isJSClass = classSym.isNonNativeJSClass
@@ -1493,7 +1493,7 @@ class JSCodeGen()(using genCtx: Context) {
14931493

14941494
if (primitives.isPrimitive(sym)) {
14951495
None
1496-
} else if (sym.is(Deferred) && currentClassSym.isNonNativeJSClass) {
1496+
} else if (sym.is(Deferred) && currentClassSym.get.nn.isNonNativeJSClass) {
14971497
// scala-js/#4409: Do not emit abstract methods in non-native JS classes
14981498
None
14991499
} else if (sym.is(Deferred)) {
@@ -1503,7 +1503,7 @@ class JSCodeGen()(using genCtx: Context) {
15031503
} else if (isIgnorableDefaultParam) {
15041504
// #11592
15051505
None
1506-
} else if (sym.is(Bridge) && sym.name.is(DefaultGetterName) && currentClassSym.isNonNativeJSClass) {
1506+
} else if (sym.is(Bridge) && sym.name.is(DefaultGetterName) && currentClassSym.get.nn.isNonNativeJSClass) {
15071507
/* #12572 Bridges for default accessors in non-native JS classes must not be emitted,
15081508
* because they call another default accessor, making their entire body an
15091509
* <undefined-param> that cannot be eliminated.
@@ -1582,7 +1582,7 @@ class JSCodeGen()(using genCtx: Context) {
15821582
else genExpr(tree)
15831583
}
15841584

1585-
if (namespace.isStatic || !currentClassSym.isNonNativeJSClass) {
1585+
if (namespace.isStatic || !currentClassSym.get.nn.isNonNativeJSClass) {
15861586
val flags = js.MemberFlags.empty.withNamespace(namespace)
15871587
js.MethodDef(flags, methodName, originalName, jsParams, resultIRType, Some(genBody()))(
15881588
optimizerHints, None)
@@ -1688,7 +1688,7 @@ class JSCodeGen()(using genCtx: Context) {
16881688
tree match {
16891689
case _: This =>
16901690
val sym = tree.symbol
1691-
if (sym != currentClassSym.get && sym.is(Module))
1691+
if ((sym ne currentClassSym.get) && sym.is(Module))
16921692
genLoadModuleOrGlobalScope(sym)
16931693
else
16941694
MaybeGlobalScope.NotGlobalScope(genExpr(tree))
@@ -1784,7 +1784,7 @@ class JSCodeGen()(using genCtx: Context) {
17841784
genApplyDynamic(app)*/
17851785

17861786
case tree: This =>
1787-
val currentClass = currentClassSym.get
1787+
val currentClass = currentClassSym.get.nn
17881788
val symIsModuleClass = tree.symbol.is(ModuleClass)
17891789
assert(tree.symbol == currentClass || symIsModuleClass,
17901790
s"Trying to access the this of another class: tree.symbol = ${tree.symbol}, class symbol = $currentClass")
@@ -1886,8 +1886,8 @@ class JSCodeGen()(using genCtx: Context) {
18861886
val qualifier = lhs.qualifier
18871887

18881888
def ctorAssignment = (
1889-
currentMethodSym.get.name == nme.CONSTRUCTOR &&
1890-
currentMethodSym.get.owner == qualifier.symbol &&
1889+
currentMethodSym.get.nn.name == nme.CONSTRUCTOR &&
1890+
currentMethodSym.get.nn.owner == qualifier.symbol &&
18911891
qualifier.isInstanceOf[This]
18921892
)
18931893
// TODO This fails for OFFSET$x fields. Re-enable when we can.
@@ -2178,7 +2178,7 @@ class JSCodeGen()(using genCtx: Context) {
21782178
if (sym == defn.Any_getClass) {
21792179
// The only primitive that is also callable as super call
21802180
js.GetClass(genThis())
2181-
} else if (currentClassSym.isNonNativeJSClass) {
2181+
} else if (currentClassSym.get.nn.isNonNativeJSClass) {
21822182
genJSSuperCall(tree, isStat)
21832183
} else {
21842184
/* #3013 `qual` can be `this.$outer()` in some cases since Scala 2.12,
@@ -2188,10 +2188,10 @@ class JSCodeGen()(using genCtx: Context) {
21882188
genExpr(qual), sym, genActualArgs(sym, args))
21892189

21902190
// Initialize the module instance just after the super constructor call.
2191-
if (isStaticModule(currentClassSym) && !isModuleInitialized.get.value &&
2192-
currentMethodSym.get.isClassConstructor) {
2191+
if (isStaticModule(currentClassSym.get.nn) && !isModuleInitialized.get.value &&
2192+
currentMethodSym.get.nn.isClassConstructor) {
21932193
isModuleInitialized.get.value = true
2194-
val className = encodeClassName(currentClassSym)
2194+
val className = encodeClassName(currentClassSym.get.nn)
21952195
val thisType = jstpe.ClassType(className)
21962196
val initModule = js.StoreModule(className, js.This()(thisType))
21972197
js.Block(superCall, initModule)
@@ -3245,7 +3245,7 @@ class JSCodeGen()(using genCtx: Context) {
32453245
genApplyJSClassMethod(genReceiver, sym, genScalaArgs)
32463246
} else {
32473247
val jsSuperClassValue = explicitJSSuperClassValue.orElse {
3248-
Some(genLoadJSConstructor(currentClassSym.get.asClass.superClass))
3248+
Some(genLoadJSConstructor(currentClassSym.get.nn.asClass.superClass))
32493249
}
32503250
genApplyJSMethodGeneric(sym, MaybeGlobalScope.NotGlobalScope(genReceiver),
32513251
genJSArgs, isStat, jsSuperClassValue)(tree.sourcePos)
@@ -3873,7 +3873,7 @@ class JSCodeGen()(using genCtx: Context) {
38733873

38743874
case JS_NEW_TARGET =>
38753875
// js.new.target
3876-
val valid = currentMethodSym.get.isClassConstructor && currentClassSym.isNonNativeJSClass
3876+
val valid = currentMethodSym.get.nn.isClassConstructor && currentClassSym.get.nn.isNonNativeJSClass
38773877
if (!valid) {
38783878
report.error(
38793879
"Illegal use of js.`new`.target.\n" +

compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
585585
}
586586

587587
private def reportCannotDisambiguateError(jsName: JSName, alts: List[Symbol]): Unit = {
588-
val currentClass = currentClassSym.get
588+
val currentClass = currentClassSym.get.nn
589589

590590
/* Find a position that is in the current class for decent error reporting.
591591
* If there are more than one, always use the "highest" one (i.e., the
@@ -623,7 +623,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
623623
*/
624624
private def genApplyForSingleExported(formalArgsRegistry: FormalArgsRegistry,
625625
exported: Exported, static: Boolean): js.Tree = {
626-
if (currentClassSym.isJSType && exported.sym.owner != currentClassSym.get) {
626+
if (currentClassSym.get.nn.isJSType && exported.sym.owner != currentClassSym.get) {
627627
assert(!static, s"nonsensical JS super call in static export of ${exported.sym}")
628628
genApplyForSingleExportedJSSuperCall(formalArgsRegistry, exported)
629629
} else {
@@ -642,7 +642,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
642642
val allArgs = formalArgsRegistry.genAllArgsRefsForForwarder()
643643

644644
val superClass = {
645-
val superClassSym = currentClassSym.asClass.superClass
645+
val superClassSym = currentClassSym.get.nn.asClass.superClass
646646
if (superClassSym.isNestedJSClass)
647647
js.VarRef(js.LocalIdent(JSSuperClassParamName))(jstpe.AnyType)
648648
else
@@ -806,7 +806,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
806806
implicit pos: SourcePosition): js.Tree = {
807807

808808
val sym = exported.sym
809-
val currentClass = currentClassSym.get
809+
val currentClass = currentClassSym.get.nn
810810

811811
def receiver =
812812
if (static) genLoadModule(sym.owner)

compiler/src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ object Contexts {
226226
*/
227227
def effectiveScope(using Context): Scope =
228228
val myOwner: Symbol | Null = owner
229-
if myOwner != null && myOwner.isClass then myOwner.asClass.unforcedDecls
229+
if myOwner != null && myOwner.uncheckedNN.isClass
230+
then myOwner.uncheckedNN.asClass.unforcedDecls
230231
else scope
231232

232233
def nestingLevel: Int = effectiveScope.nestingLevel

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,7 @@ object Denotations {
184184
type AsSeenFromResult <: Denotation
185185

186186
val symbol: Symbol =
187-
if symbolHint != null then symbolHint
188-
else this.asInstanceOf[Symbol]
187+
(if symbolHint != null then symbolHint else this).asInstanceOf[Symbol]
189188

190189
/** The type info.
191190
* The info is an instance of TypeType iff this is a type denotation

compiler/src/dotty/tools/dotc/core/GadtConstraint.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ class GadtConstraint private (
8585

8686
def externalize(tp: Type, theMap: TypeMap | Null = null)(using Context): Type = tp match
8787
case param: TypeParamRef =>
88-
val sym = reverseMapping(param)
89-
if sym != null then sym.typeRef else param
88+
val sym: Symbol | Null = reverseMapping(param)
89+
if sym != null then sym.uncheckedNN.typeRef else param
9090
case tp: TypeAlias => tp.derivedAlias(externalize(tp.alias, theMap))
9191
case tp => (if theMap == null then ExternalizeMap() else theMap).mapOver(tp)
9292

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ object SymDenotations {
9292
if (Config.checkNoSkolemsInInfo) assertNoSkolems(initInfo)
9393

9494
final def maybeOwner: Symbol =
95-
if ownerOrNull == null then NoSymbol else ownerOrNull
95+
if ownerOrNull == null then NoSymbol else ownerOrNull.asInstanceOf[Symbol]
9696

9797
// ------ Getting and setting fields -----------------------------
9898

@@ -104,7 +104,7 @@ object SymDenotations {
104104
/** The owner of the symbol; overridden in NoDenotation */
105105
final def owner: Symbol =
106106
assert(ownerOrNull != null, "NoDenotation.owner")
107-
ownerOrNull
107+
ownerOrNull.asInstanceOf[Symbol]
108108

109109
/** The flag set */
110110
final def flags(using Context): FlagSet = { ensureCompleted(); myFlags }
@@ -1648,7 +1648,7 @@ object SymDenotations {
16481648
val privateWithin1 = if (privateWithin != null) privateWithin else this.privateWithin
16491649
val annotations1 = if (annotations != null) annotations else this.annotations
16501650
val rawParamss1 = if rawParamss != null then rawParamss else this.rawParamss
1651-
val d = SymDenotation(symbol, symbol.lastKnownDenotation.common, owner, name, initFlags1, info1, privateWithin1)
1651+
val d = SymDenotation(symbol, symbol.lastKnownDenotation.common, owner, name, initFlags1, info1, privateWithin1.uncheckedNN)
16521652
d.annotations = annotations1
16531653
d.rawParamss = rawParamss1
16541654
d.registeredCompanion = registeredCompanion

0 commit comments

Comments
 (0)