Skip to content

Commit 2e45946

Browse files
committed
Handle object access semantics depending on locations
1 parent 8ebaded commit 2e45946

File tree

7 files changed

+50
-22
lines changed

7 files changed

+50
-22
lines changed

compiler/src/dotty/tools/dotc/transform/init/Checking.scala

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -227,14 +227,19 @@ object Checking {
227227
else
228228
Errors.empty
229229

230-
case pot @ (_: Hot | _: Global) =>
231-
val cls = pot match
232-
case hot: Hot => hot.classSymbol
233-
case obj: Global => obj.moduleClass
234-
val target = resolve(cls, sym)
235-
state.dependencies += StaticCall(cls, target)(pot.source)
230+
case hot: Hot =>
231+
val target = resolve(hot.classSymbol, sym)
232+
state.dependencies += StaticCall(hot.classSymbol, target)(pot.source)
236233
Errors.empty
237234

235+
case obj: Global =>
236+
val target = resolve(obj.moduleClass, sym)
237+
if obj.enclosingClass == state.thisClass && obj.moduleClass == state.thisClass then
238+
check(MethodCall(ThisRef()(obj.source), target)(eff.source))
239+
else
240+
state.dependencies += StaticCall(obj.moduleClass, target)(pot.source)
241+
Errors.empty
242+
238243
case _: Cold =>
239244
CallCold(sym, eff.source, state.path).toErrors
240245

@@ -281,6 +286,8 @@ object Checking {
281286
// or all fields are already initialized
282287
val target = resolve(obj.moduleClass, field)
283288
if (target.is(Flags.Lazy)) check(MethodCall(obj, target)(eff.source))
289+
else if obj.enclosingClass == state.thisClass && obj.moduleClass == state.thisClass then
290+
check(FieldAccess(ThisRef()(obj.source), target)(eff.source))
284291
else Errors.empty
285292

286293
case _: Cold =>
@@ -378,7 +385,8 @@ object Checking {
378385

379386
private def checkAccessGlobal(eff: AccessGlobal)(using state: State): Errors =
380387
val obj = eff.potential
381-
state.dependencies += ObjectAccess(obj.symbol)(eff.source)
388+
if obj.enclosingClass != obj.moduleClass then
389+
state.dependencies += ObjectAccess(obj.symbol)(eff.source)
382390
Errors.empty
383391

384392
private def expand(pot: Potential)(using state: State): Summary = trace("expand " + pot.show, init, _.asInstanceOf[Summary].show) {

compiler/src/dotty/tools/dotc/transform/init/CycleChecker.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ import Errors._, Potentials._, Effects._
1717

1818
import scala.collection.mutable
1919

20-
21-
2220
/** The dependencies of a static object or a class
2321
*
2422
* This class is used in checking cyclic initialization of static objects.

compiler/src/dotty/tools/dotc/transform/init/Potentials.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,11 @@ object Potentials {
159159
"Fun[pots = " + potentials.map(_.show).mkString(";") + ", effs = " + effects.map(_.show).mkString(";") + "]"
160160
}
161161

162-
/** Reference to a global object */
163-
case class Global(symbol: Symbol)(val source: Tree) extends Refinable {
162+
/** Reference to a global object
163+
*
164+
* @param enclosingClass The class where the reference appears in
165+
*/
166+
case class Global(symbol: Symbol, enclosingClass: ClassSymbol)(val source: Tree) extends Refinable {
164167
def show(using Context): String = symbol.show
165168

166169
def moduleClass(using Context): ClassSymbol = symbol.moduleClass.asClass

compiler/src/dotty/tools/dotc/transform/init/Summarization.scala

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ object Summarization {
4646
else if (!sym.exists) // polymorphic function apply and structural types
4747
Summary(pots.promote(expr) ++ effs)
4848
else if (sym.is(Flags.Module) && sym.isStatic)
49-
Summary(effs) + Global(sym)(expr)
49+
val enclosing = env.ctx.owner.lexicallyEnclosingClass.asClass
50+
Summary(effs) + Global(sym, enclosing)(expr)
5051
else {
5152
val Summary(pots2, effs2) = pots.select(expr.symbol, expr)
5253
Summary(pots2, effs ++ effs2)
@@ -249,7 +250,8 @@ object Summarization {
249250
// self reference to an object inside the object
250251
Summary(ThisRef()(source))
251252
else
252-
val pot = Global(tmref.symbol)(source)
253+
val enclosing = env.ctx.owner.lexicallyEnclosingClass.asClass
254+
val pot = Global(tmref.symbol, enclosing)(source)
253255
Summary(pot) + AccessGlobal(pot)
254256

255257
case tmref: TermRef =>
@@ -261,16 +263,14 @@ object Summarization {
261263
}
262264

263265
case ThisType(tref) =>
266+
val enclosing = env.ctx.owner.lexicallyEnclosingClass.asClass
264267
if tref.symbol.is(Flags.Module, butNot = Flags.Package)
265268
&& tref.symbol.isStatic
266-
&& env.ctx.owner.isStatic
267-
&& tref.symbol != env.ctx.owner
268269
then
269270
val sym = tref.symbol.sourceModule
270-
val pot = Global(sym)(source)
271+
val pot = Global(sym, enclosing)(source)
271272
Summary(pot) + AccessGlobal(pot)
272273
else
273-
val enclosing = env.ctx.owner.lexicallyEnclosingClass.asClass
274274
val cls = tref.symbol.asClass
275275
resolveThis(cls, ThisRef()(source), enclosing, source)
276276

@@ -312,7 +312,8 @@ object Summarization {
312312
else if (pot.size > 2) Summary(Promote(pot)(source))
313313
else if (cls.is(Flags.Module) && !cur.ownersIterator.exists(_ == cls)) {
314314
// Dotty uses O$.this outside of the object O
315-
val pot = Global(cls.sourceModule)(source)
315+
val enclosing = env.ctx.owner.lexicallyEnclosingClass.asClass
316+
val pot = Global(cls.sourceModule, enclosing)(source)
316317
Summary(pot) + AccessGlobal(pot)
317318
}
318319
else {

tests/init/neg/features-trees2.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
object Trees {
1+
object Trees { // error
22
class ValDef { counter += 1 }
33
class EmptyValDef extends ValDef
44
val theEmptyValDef = new EmptyValDef
5-
private var counter = 0 // error
5+
private var counter = 0
66
}

tests/init/neg/global-cycle7.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
object A { // error
2+
val n: Int = B.m
3+
}
4+
5+
object B {
6+
val m: Int = A.n
7+
}
8+
9+
abstract class TokensCommon {
10+
def maxToken: Int
11+
12+
val tokenString, debugString: Array[String] = new Array[String](maxToken + 1)
13+
}
14+
15+
object JavaTokens extends TokensCommon {
16+
final def maxToken: Int = DOUBLE
17+
final val DOUBLE = 188
18+
}

tests/init/neg/inner9.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
object Flags {
1+
object Flags { // error
22
class Inner {
33
println(b)
44
}
55

66
new Flags.Inner
77

8-
val b = 5 // error
8+
val b = 5
99
}
1010

1111
object Flags2 {

0 commit comments

Comments
 (0)