forked from scala/scala3
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix scala#8033: Eliminate unused outer accessors
- Loading branch information
Showing
5 changed files
with
97 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
compiler/src/dotty/tools/dotc/transform/ElimOuterAccessors.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package dotty.tools.dotc | ||
package transform | ||
|
||
import core._ | ||
import MegaPhase.MiniPhase | ||
import dotty.tools.dotc.core.Contexts.Context | ||
import ast._ | ||
import Trees._ | ||
import Flags._ | ||
import Symbols._ | ||
import Decorators._ | ||
import DenotTransformers._ | ||
import collection.mutable | ||
|
||
object ElimOuterAccessors: | ||
val name: String = "elimOuterAccessors" | ||
|
||
/** Drops outer accessors of final classes that are unused */ | ||
class ElimOuterAccessors extends MiniPhase with IdentityDenotTransformer: | ||
thisPhase => | ||
import tpd._ | ||
|
||
override def phaseName: String = ElimOuterAccessors.name | ||
|
||
override def changesMembers: Boolean = true // the phase drops outer accessors | ||
|
||
private def mightBeDropped(sym: Symbol)(using Context) = | ||
sym.is(OuterAccessor) && !sym.owner.isExtensibleClass | ||
|
||
/** The accessed outer accessors that might otherwise be dropped */ | ||
private val retainedAccessors = mutable.Set[Symbol]() | ||
|
||
private def markAccessed(tree: RefTree)(implicit ctx: Context): Tree = | ||
val sym = tree.symbol | ||
if mightBeDropped(sym) then retainedAccessors += sym | ||
tree | ||
|
||
def transformStat(tree: Tree)(using Context): Tree = | ||
val sym = tree.symbol | ||
if mightBeDropped(sym) && !retainedAccessors.remove(sym) then | ||
sym.dropAfter(thisPhase) | ||
EmptyTree | ||
else | ||
tree | ||
|
||
override def transformIdent(tree: Ident)(using Context): Tree = | ||
markAccessed(tree) | ||
|
||
override def transformSelect(tree: Select)(using Context): Tree = | ||
markAccessed(tree) | ||
|
||
override def transformTemplate(tree: Template)(using Context): Tree = | ||
cpy.Template(tree)(body = tree.body.map(transformStat).filter(_ != EmptyTree)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
trait Okay extends Serializable { | ||
def okay: Okay | ||
} | ||
|
||
class Foo { | ||
def okay1: Okay = new Okay() { | ||
val okay: Okay = this | ||
} | ||
def okay2: Okay = new Okay { | ||
val okay: Okay = okay1 | ||
} | ||
} | ||
|
||
object Test { | ||
def main(args: Array[String]): Unit = { | ||
val foo = new Foo | ||
println(roundTrip(foo.okay1)) | ||
println(roundTrip(foo.okay2)) | ||
} | ||
|
||
def roundTrip[A](a: A): A = { | ||
import java.io._ | ||
|
||
val aos = new ByteArrayOutputStream() | ||
val oos = new ObjectOutputStream(aos) | ||
oos.writeObject(a) | ||
oos.close() | ||
val ais = new ByteArrayInputStream(aos.toByteArray()) | ||
val ois: ObjectInputStream = new ObjectInputStream(ais) | ||
val newA = ois.readObject() | ||
ois.close() | ||
newA.asInstanceOf[A] | ||
} | ||
} |