Skip to content

Commit

Permalink
Refactor hasOnlyLocalInstantiation to use isLocalToCompilationUnit (#…
Browse files Browse the repository at this point in the history
…19886)

Refactor hasOnlyLocalInstantiation to use isLocalToCompilationUnit
  • Loading branch information
dwijnand authored Mar 16, 2024
2 parents 3d5cf9c + f8a5583 commit 9ef24bf
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 7 deletions.
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1208,8 +1208,8 @@ object SymDenotations {

final def isLocalToCompilationUnit(using Context): Boolean =
is(Private)
|| owner.ownersIterator.exists(_.isTerm)
|| accessBoundary(defn.RootClass).isContainedIn(symbol.topLevelClass)
|| owner.ownersIterator.takeWhile(!_.isStaticOwner).exists(_.isTerm)
|| accessBoundary(defn.RootClass).isProperlyContainedIn(symbol.topLevelClass)

final def isTransparentClass(using Context): Boolean =
is(TransparentType)
Expand Down
9 changes: 4 additions & 5 deletions compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -218,18 +218,17 @@ object ExplicitOuter {
*/
private def needsOuterAlways(cls: ClassSymbol)(using Context): Boolean =
needsOuterIfReferenced(cls) &&
(!hasLocalInstantiation(cls) || // needs outer because we might not know whether outer is referenced or not
(!hasOnlyLocalInstantiation(cls) || // needs outer because we might not know whether outer is referenced or not
cls.mixins.exists(needsOuterIfReferenced) || // needs outer for parent traits
cls.info.parents.exists(parent => // needs outer to potentially pass along to parent
needsOuterIfReferenced(parent.classSymbol.asClass)))

/** Class is only instantiated in the compilation unit where it is defined */
private def hasLocalInstantiation(cls: ClassSymbol)(using Context): Boolean =
private def hasOnlyLocalInstantiation(cls: ClassSymbol)(using Context): Boolean =
// Modules are normally locally instantiated, except if they are declared in a trait,
// in which case they will be instantiated in the classes that mix in the trait.
cls.owner.ownersIterator.takeWhile(!_.isStaticOwner).exists(_.isTerm)
|| cls.is(Private, butNot = Module)
|| cls.is(Module) && !cls.owner.is(Trait)
if cls.is(Module) then !cls.owner.is(Trait)
else cls.isLocalToCompilationUnit

/** The outer parameter accessor of cass `cls` */
private def outerParamAccessor(cls: ClassSymbol)(using Context): TermSymbol =
Expand Down
2 changes: 2 additions & 0 deletions tests/generic-java-signatures/outer-ref-elimination.check
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ List(public T6$$anon$3$C6())
List(public T7$C7$1())
List(public T8$$anon$4$C8())
List(public T9$C9$1(T9))
List(public T10$C10(T10))
List(public T11$D11$C11())
6 changes: 6 additions & 0 deletions tests/generic-java-signatures/outer-ref-elimination.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ class T8 { def t8(): Unit = new AnyRef { class C8; test(classOf[C8]) } }
// the field x.
class T9 { var x = 451; def t9(): Unit = { class C9 {def getX = x}; test(classOf[C9])} }

class T10 { private[T10] class C10; test(classOf[C10]) }

class T11 { class D11 { private[D11] class C11; test(classOf[C11]) } }

object Test {
def main(args: Array[String]): Unit = {
T1
Expand All @@ -37,5 +41,7 @@ object Test {
new T7().t7()
new T8().t8()
new T9().t9()
new T10()
val t11 = new T11(); new t11.D11()
}
}

0 comments on commit 9ef24bf

Please sign in to comment.