Skip to content

Do not remove accessors to early #13484

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions compiler/src/dotty/tools/dotc/CompilationUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ class CompilationUnit protected (val source: SourceFile) {
*/
var needsQuotePickling: Boolean = false

/** A structure containing a temporary map for generating inline accessors */
val inlineAccessors: InlineAccessors = new InlineAccessors

var suspended: Boolean = false
var suspendedAtInliningPhase: Boolean = false

Expand Down
7 changes: 2 additions & 5 deletions compiler/src/dotty/tools/dotc/transform/AccessProxies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,9 @@ abstract class AccessProxies {
*/
protected def passReceiverAsArg(accessorName: Name)(using Context): Boolean = false

/** The accessor definitions that need to be added to class `cls`
* As a side-effect, this method removes entries from the `accessedBy` map.
* So a second call of the same method will yield the empty list.
*/
/** The accessor definitions that need to be added to class `cls` */
private def accessorDefs(cls: Symbol)(using Context): Iterator[DefDef] =
for (accessor <- cls.info.decls.iterator; accessed <- accessedBy.remove(accessor).toOption) yield
for accessor <- cls.info.decls.iterator; accessed <- accessedBy.get(accessor) yield
DefDef(accessor.asTerm, prefss => {
def numTypeParams = accessed.info match {
case info: PolyType => info.paramNames.length
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/transform/Inlining.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import SymUtils._
import NameKinds._
import dotty.tools.dotc.ast.tpd
import typer.Implicits.SearchFailureType
import typer.PrepareInlineable

import scala.collection.mutable
import dotty.tools.dotc.core.Annotations._
Expand Down
20 changes: 15 additions & 5 deletions compiler/src/dotty/tools/dotc/transform/ProtectedAccessors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import core.Decorators._
import core.Names.TermName
import MegaPhase.MiniPhase
import config.Printers.transforms
import dotty.tools.dotc.util.Property

/** Add accessors for all protected accesses. An accessor is needed if
* according to the rules of the JVM a protected class member is not accessible
Expand Down Expand Up @@ -50,7 +51,15 @@ class ProtectedAccessors extends MiniPhase {

override def phaseName: String = ProtectedAccessors.name

object Accessors extends AccessProxies {
private val AccessorsKey = new Property.Key[Accessors]

private def accessors(using Context): Accessors =
ctx.property(AccessorsKey).get

override def prepareForUnit(tree: Tree)(using Context): Context =
ctx.fresh.setProperty(AccessorsKey, new Accessors)

private class Accessors extends AccessProxies {
val insert: Insert = new Insert {
def accessorNameOf(name: TermName, site: Symbol)(using Context): TermName = ProtectedAccessorName(name)
def needsAccessor(sym: Symbol)(using Context) = ProtectedAccessors.needsAccessor(sym)
Expand All @@ -66,19 +75,20 @@ class ProtectedAccessors extends MiniPhase {
}

override def transformIdent(tree: Ident)(using Context): Tree =
Accessors.insert.accessorIfNeeded(tree)
accessors.insert.accessorIfNeeded(tree)

override def transformSelect(tree: Select)(using Context): Tree =
Accessors.insert.accessorIfNeeded(tree)
accessors.insert.accessorIfNeeded(tree)

override def transformAssign(tree: Assign)(using Context): Tree =
tree.lhs match {
case lhs: RefTree if lhs.name.is(ProtectedAccessorName) =>
cpy.Apply(tree)(Accessors.insert.useSetter(lhs), tree.rhs :: Nil)
cpy.Apply(tree)(accessors.insert.useSetter(lhs), tree.rhs :: Nil)
case _ =>
tree
}

override def transformTemplate(tree: Template)(using Context): Tree =
cpy.Template(tree)(body = Accessors.addAccessorDefs(tree.symbol.owner, tree.body))
cpy.Template(tree)(body = accessors.addAccessorDefs(tree.symbol.owner, tree.body))

}
15 changes: 14 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ import dotty.tools.dotc.transform.TreeMapWithStages._
object PrepareInlineable {
import tpd._

private val InlineAccessorsKey = new Property.Key[InlineAccessors]

def initContext(ctx: Context): Context =
ctx.fresh.setProperty(InlineAccessorsKey, new InlineAccessors)

def makeInlineable(tree: Tree)(using Context): Tree =
ctx.property(InlineAccessorsKey).get.makeInlineable(tree)

def addAccessorDefs(cls: Symbol, body: List[Tree])(using Context): List[Tree] =
ctx.property(InlineAccessorsKey) match
case Some(inlineAccessors) => inlineAccessors.addAccessorDefs(cls, body)
case _ => body

class InlineAccessors extends AccessProxies {

/** If an inline accessor name wraps a unique inline name, this is taken as indication
Expand Down Expand Up @@ -251,7 +264,7 @@ object PrepareInlineable {
if inlined.isInlineMethod then
inlinedBody = dropInlineIfError(inlined,
checkInlineMethod(inlined,
ctx.compilationUnit.inlineAccessors.makeInlineable(inlinedBody)))
PrepareInlineable.makeInlineable(inlinedBody)))
inlining.println(i"Body to inline for $inlined: $inlinedBody")
inlinedBody
})
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ trait QuotesAndSplices {
}

private def makeInlineable(tree: Tree)(using Context): Tree =
ctx.compilationUnit.inlineAccessors.makeInlineable(tree)
PrepareInlineable.makeInlineable(tree)

/** Translate `${ t: Expr[T] }` into expression `t.splice` while tracking the quotation level in the context */
def typedSplice(tree: untpd.Splice, pt: Type)(using Context): Tree = {
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2461,7 +2461,7 @@ class Typer extends Namer
// 4. Polymorphic type defs override nothing.

protected def addAccessorDefs(cls: Symbol, body: List[Tree])(using Context): List[Tree] =
ctx.compilationUnit.inlineAccessors.addAccessorDefs(cls, body)
PrepareInlineable.addAccessorDefs(cls, body)

/** If this is a real class, make sure its first parent is a
* constructor call. Cannot simply use a type. Overridden in ReTyper.
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/TyperPhase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ class TyperPhase(addRootImports: Boolean = true) extends Phase {
override def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] =
val unitContexts =
for unit <- units yield
val newCtx = ctx.fresh.setPhase(this.start).setCompilationUnit(unit)
val newCtx0 = ctx.fresh.setPhase(this.start).setCompilationUnit(unit)
val newCtx = PrepareInlineable.initContext(newCtx0)
report.inform(s"typing ${unit.source}")
if (addRootImports)
newCtx.withRootImports
Expand Down
7 changes: 7 additions & 0 deletions tests/pos/i13476.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
private object Foo:
inline def d(arg : Int): Unit = {}
transparent inline def haha() : Unit = {}

export Foo.*

@main def main : Unit = haha()