Skip to content

Commit 6b42afa

Browse files
oderskyWojciechMazur
authored andcommitted
Fix test and add more comments
[Cherry-picked 5b8e6c9]
1 parent 18201cc commit 6b42afa

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

compiler/src/dotty/tools/dotc/transform/Dependencies.scala

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -181,32 +181,47 @@ abstract class Dependencies(root: ast.tpd.Tree, @constructorOnly rootContext: Co
181181
if enclClass.isContainedIn(thisClass) then thisClass
182182
else enclClass) // unknown this reference, play it safe and assume the narrowest possible owner
183183

184+
/** Set the first owner of a local method or class that's nested inside a term.
185+
* This is either the enclosing package or the enclosing class. If the former,
186+
* the method will be be translated to a static method of its toplevel class.
187+
* In that case, we might later re-adjust the owner to a nested class via
188+
* `narrowTo` when we see that the method refers to the this-type of that class.
189+
* We choose the enclosing package when there's something potentially to gain from this
190+
* and when it is safe to do so
191+
*/
184192
def setLogicOwner(local: Symbol) =
185193
val encClass = local.owner.enclosingClass
194+
// When to [efer enclosing class over enclosing package:
186195
val preferEncClass =
187196
encClass.isStatic
188-
// non-static classes can capture owners, so should be avoided
197+
// If class is not static, we try to hoist the method out of
198+
// the class to avoid the outer pointer.
189199
&& (encClass.isProperlyContainedIn(local.topLevelClass)
190-
// can be false for symbols which are defined in some weird combination of supercalls.
200+
// If class is nested in an outer object, we prefer to leave the method in the class,
201+
// since putting it in the outer object makes access more complicated
191202
|| encClass.is(ModuleClass, butNot = Package)
192-
// needed to not cause deadlocks in classloader. see t5375.scala
203+
// If class is an outermost object we also want to avoid making the
204+
// method static since that could cause deadlocks in interacting
205+
// with class initialization. See deadlock.scala
193206
)
194207
&& (!sym.isAnonymousFunction || sym.owner.ownersIterator.exists(_.isConstructor))
195-
// For anonymous functions in static objects, we prefer them to be static because
196-
// that means lambdas are memoized and can be serialized even if the enclosing object
208+
// The previous conditions mean methods in static objects and nested static classes
209+
// don't get lifted out to be static. In general it is prudent to do that. However,
210+
// for anonymous functions, we prefer them to be static because that means lambdas
211+
// are memoized and can be serialized even if the enclosing object or class
197212
// is not serializable. See run/lambda-serialization-gc.scala and run/i19224.scala.
198213
// On the other hand, we don't want to lift anonymous functions from inside the
199-
// object constructor to be static since that can cause deadlocks by its interaction
200-
// with class initialization. See run/deadlock.scala, which works in Scala 3
201-
// but deadlocks in Scala 2.
214+
// object or class constructor to be static since that can cause again deadlocks
215+
// by its interaction with class initialization. See run/deadlock.scala, which works
216+
// in Scala 3 but deadlocks in Scala 2.
202217
||
203218
/* Scala.js: Never move any member beyond the boundary of a DynamicImportThunk.
204219
* DynamicImportThunk subclasses are boundaries between the eventual ES modules
205220
* that can be dynamically loaded. Moving members across that boundary changes
206221
* the dynamic and static dependencies between ES modules, which is forbidden.
207222
*/
208223
ctx.settings.scalajs.value && encClass.isSubClass(jsdefn.DynamicImportThunkClass)
209-
224+
210225
logicOwner(sym) = if preferEncClass then encClass else local.enclosingPackageClass
211226

212227
tree match

tests/run/i19224.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ object Test extends App {
2020
assert(t1.x() == t2.x()) // true on Scala 2, was false on Scala 3...
2121
}
2222
}
23+
class C {
24+
def x(): Int => String = (i: Int) => i.toString
25+
}

0 commit comments

Comments
 (0)