Skip to content

Fix #4754: Don't generate inline accessor for constants #4760

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 4 commits into from
Jul 6, 2018
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
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/transform/AccessProxies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ abstract class AccessProxies {
/** Rewire reference to refer to `accessor` symbol */
private def rewire(reference: RefTree, accessor: Symbol)(implicit ctx: Context): Tree = {
reference match {
case Select(qual, _) => qual.select(accessor)
case Ident(name) => ref(accessor)
case Select(qual, _) if qual.tpe.derivesFrom(accessor.owner) => qual.select(accessor)
case _ => ref(accessor)
}
}.withPos(reference.pos)

Expand Down Expand Up @@ -161,8 +161,8 @@ object AccessProxies {
def hostForAccessorOf(accessed: Symbol)(implicit ctx: Context): Symbol = {
def recur(cls: Symbol): Symbol =
if (!cls.exists) NoSymbol
else if (cls.derivesFrom(accessed.owner)) cls
else if (cls.companionModule.moduleClass == accessed.owner) accessed.owner
else if (cls.derivesFrom(accessed.owner) ||
cls.companionModule.moduleClass == accessed.owner) cls
else recur(cls.owner)
recur(ctx.owner)
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/PostTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object PostTyper {

/** A macro transform that runs immediately after typer and that performs the following functions:
*
* (1) Add super accessors and protected accessors (@see SuperAccessors)
* (1) Add super accessors (@see SuperAccessors)
*
* (2) Convert parameter fields that have the same name as a corresponding
* public parameter field in a superclass to a forwarder to the superclass
Expand Down
16 changes: 10 additions & 6 deletions compiler/src/dotty/tools/dotc/typer/Inliner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,16 @@ object Inliner {
def accessorNameKind = InlineAccessorName

/** A definition needs an accessor if it is private, protected, or qualified private
* and it is not part of the tree that gets inlined. The latter test is implemented
* by excluding all symbols properly contained in the inlined method.
*/
* and it is not part of the tree that gets inlined. The latter test is implemented
* by excluding all symbols properly contained in the inlined method.
*
* Constant vals don't need accessors since they are inlined in FirstTransform.
*/
def needsAccessor(sym: Symbol)(implicit ctx: Context) =
sym.isTerm &&
(sym.is(AccessFlags) || sym.privateWithin.exists) &&
!sym.isContainedIn(inlineSym)
!sym.isContainedIn(inlineSym) &&
!(sym.isStable && sym.info.widenTermRefExpr.isInstanceOf[ConstantType])

def preTransform(tree: Tree)(implicit ctx: Context): Tree

Expand Down Expand Up @@ -124,7 +127,7 @@ object Inliner {
if needsAccessor(tree.symbol) && tree.isTerm && !tree.symbol.isConstructor =>
val (refPart, targs, argss) = decomposeCall(tree)
val qual = qualifier(refPart)
println(i"adding receiver passing inline accessor for $tree/$refPart -> (${qual.tpe}, $refPart: ${refPart.getClass}, [$targs%, %], ($argss%, %))")
inlining.println(i"adding receiver passing inline accessor for $tree/$refPart -> (${qual.tpe}, $refPart: ${refPart.getClass}, [$targs%, %], ($argss%, %))")

// Need to dealias in order to cagtch all possible references to abstracted over types in
// substitutions
Expand Down Expand Up @@ -542,9 +545,10 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {

override def ensureAccessible(tpe: Type, superAccess: Boolean, pos: Position)(implicit ctx: Context): Type = {
tpe match {
case tpe @ TypeRef(pre, _) if !tpe.symbol.isAccessibleFrom(pre, superAccess) =>
case tpe: NamedType if !tpe.symbol.isAccessibleFrom(tpe.prefix, superAccess) =>
tpe.info match {
case TypeAlias(alias) => return ensureAccessible(alias, superAccess, pos)
case info: ConstantType if tpe.symbol.isStable => return info
case _ =>
}
case _ =>
Expand Down
3 changes: 3 additions & 0 deletions tests/run/i4754.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Side effect
Side effect
12
16 changes: 16 additions & 0 deletions tests/run/i4754.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
object Foo {
private final val x = 1
private def y = 2
private def z: 3 = { println("Side effect"); 3 }
}

class Foo {
import Foo._
inline def foo = x + Foo.x + y + Foo.y + z + Foo.z
}

object Test {
def main(args: Array[String]): Unit = {
println((new Foo).foo)
}
}