Skip to content

Commit

Permalink
Merge pull request #1095 from gkossakowski/inliner-access-levels
Browse files Browse the repository at this point in the history
Moved inline logic before pickler.
  • Loading branch information
VladUreche committed Aug 9, 2012
2 parents 5fc4057 + e6b4204 commit 2fd4df8
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 76 deletions.
11 changes: 1 addition & 10 deletions src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -497,16 +497,7 @@ abstract class ExplicitOuter extends InfoTransform
else atPos(tree.pos)(outerPath(outerValue, currentClass.outerClass, sym)) // (5)

case Select(qual, name) =>
/** return closest enclosing method, unless shadowed by an enclosing class;
* no use of closures here in the interest of speed.
*/
def closestEnclMethod(from: Symbol): Symbol =
if (from.isSourceMethod) from
else if (from.isClass) NoSymbol
else closestEnclMethod(from.owner)

if (currentClass != sym.owner ||
(closestEnclMethod(currentOwner) hasAnnotation ScalaInlineClass))
if (currentClass != sym.owner)
sym.makeNotPrivate(sym.owner)

val qsym = qual.tpe.widen.typeSymbol
Expand Down
3 changes: 0 additions & 3 deletions src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
/** the following two members override abstract members in Transform */
val phaseName: String = "extmethods"

/** The following flags may be set by this phase: */
override def phaseNewFlags: Long = notPRIVATE

def newTransformer(unit: CompilationUnit): Transformer =
new Extender(unit)

Expand Down
143 changes: 80 additions & 63 deletions src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
/** the following two members override abstract members in Transform */
val phaseName: String = "superaccessors"

/** The following flags may be set by this phase: */
override def phaseNewFlags: Long = notPRIVATE

protected def newTransformer(unit: CompilationUnit): Transformer =
new SuperAccTransformer(unit)

Expand Down Expand Up @@ -192,9 +195,11 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
}
super.transform(tree)

case ModuleDef(_, _, _) =>
checkCompanionNameClashes(sym)
super.transform(tree)

case Template(_, _, body) =>
val ownAccDefs = new ListBuffer[Tree]
accDefs(currentOwner) = ownAccDefs
Expand All @@ -221,82 +226,92 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
typeDef.symbol.deSkolemize.setFlag(SPECIALIZED)
typeDef

case sel @ Select(qual @ This(_), name) =>
// warn if they are selecting a private[this] member which
// also exists in a superclass, because they may be surprised
// to find out that a constructor parameter will shadow a
// field. See SI-4762.
if (settings.lint.value) {
if (sym.isPrivateLocal && sym.paramss.isEmpty) {
qual.symbol.ancestors foreach { parent =>
parent.info.decls filterNot (x => x.isPrivate || x.hasLocalFlag) foreach { m2 =>
if (sym.name == m2.name && m2.isGetter && m2.accessed.isMutable) {
unit.warning(sel.pos,
sym.accessString + " " + sym.fullLocationString + " shadows mutable " + m2.name
+ " inherited from " + m2.owner + ". Changes to " + m2.name + " will not be visible within "
+ sym.owner + " - you may want to give them distinct names."
)
case sel @ Select(qual, name) =>
/** return closest enclosing method, unless shadowed by an enclosing class;
* no use of closures here in the interest of speed.
*/
def closestEnclMethod(from: Symbol): Symbol =
if (from.isSourceMethod) from
else if (from.isClass) NoSymbol
else closestEnclMethod(from.owner)

if (closestEnclMethod(currentOwner) hasAnnotation definitions.ScalaInlineClass)
sym.makeNotPrivate(sym.owner)

qual match {
case This(_) =>
// warn if they are selecting a private[this] member which
// also exists in a superclass, because they may be surprised
// to find out that a constructor parameter will shadow a
// field. See SI-4762.
if (settings.lint.value) {
if (sym.isPrivateLocal && sym.paramss.isEmpty) {
qual.symbol.ancestors foreach { parent =>
parent.info.decls filterNot (x => x.isPrivate || x.hasLocalFlag) foreach { m2 =>
if (sym.name == m2.name && m2.isGetter && m2.accessed.isMutable) {
unit.warning(sel.pos,
sym.accessString + " " + sym.fullLocationString + " shadows mutable " + m2.name
+ " inherited from " + m2.owner + ". Changes to " + m2.name + " will not be visible within "
+ sym.owner + " - you may want to give them distinct names.")
}
}
}
}
}
}
}

// direct calls to aliases of param accessors to the superclass in order to avoid
// duplicating fields.
if (sym.isParamAccessor && sym.alias != NoSymbol) {
val result = (localTyper.typedPos(tree.pos) {
Select(Super(qual, tpnme.EMPTY) setPos qual.pos, sym.alias)
}).asInstanceOf[Select]
debuglog("alias replacement: " + tree + " ==> " + result);//debug
localTyper.typed(gen.maybeMkAsInstanceOf(transformSuperSelect(result), sym.tpe, sym.alias.tpe, true))
}
else {
/** A trait which extends a class and accesses a protected member
* of that class cannot implement the necessary accessor method
* because its implementation is in an implementation class (e.g.
* Foo$class) which inherits nothing, and jvm access restrictions
* require the call site to be in an actual subclass. So non-trait
* classes inspect their ancestors for any such situations and
* generate the accessors. See SI-2296.
*/
// FIXME - this should be unified with needsProtectedAccessor, but some
// subtlety which presently eludes me is foiling my attempts.
val shouldEnsureAccessor = (
currentClass.isTrait
&& sym.isProtected
&& sym.enclClass != currentClass
&& !sym.owner.isTrait
&& (sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass)
&& (qual.symbol.info.member(sym.name) ne NoSymbol)
)
if (shouldEnsureAccessor) {
log("Ensuring accessor for call to protected " + sym.fullLocationString + " from " + currentClass)
ensureAccessor(sel)
}
else
mayNeedProtectedAccessor(sel, List(EmptyTree), false)
}
// direct calls to aliases of param accessors to the superclass in order to avoid
// duplicating fields.
if (sym.isParamAccessor && sym.alias != NoSymbol) {
val result = (localTyper.typedPos(tree.pos) {
Select(Super(qual, tpnme.EMPTY) setPos qual.pos, sym.alias)
}).asInstanceOf[Select]
debuglog("alias replacement: " + tree + " ==> " + result); //debug
localTyper.typed(gen.maybeMkAsInstanceOf(transformSuperSelect(result), sym.tpe, sym.alias.tpe, true))
} else {
/**
* A trait which extends a class and accesses a protected member
* of that class cannot implement the necessary accessor method
* because its implementation is in an implementation class (e.g.
* Foo$class) which inherits nothing, and jvm access restrictions
* require the call site to be in an actual subclass. So non-trait
* classes inspect their ancestors for any such situations and
* generate the accessors. See SI-2296.
*/
// FIXME - this should be unified with needsProtectedAccessor, but some
// subtlety which presently eludes me is foiling my attempts.
val shouldEnsureAccessor = (
currentClass.isTrait
&& sym.isProtected
&& sym.enclClass != currentClass
&& !sym.owner.isTrait
&& (sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass)
&& (qual.symbol.info.member(sym.name) ne NoSymbol))
if (shouldEnsureAccessor) {
log("Ensuring accessor for call to protected " + sym.fullLocationString + " from " + currentClass)
ensureAccessor(sel)
} else
mayNeedProtectedAccessor(sel, List(EmptyTree), false)
}

case sel @ Select(Super(_, mix), name) =>
if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) {
if (!settings.overrideVars.value)
unit.error(tree.pos, "super may be not be used on "+ sym.accessedOrSelf)
}
else if (isDisallowed(sym)) {
unit.error(tree.pos, "super not allowed here: use this." + name.decode + " instead")
case Super(_, mix) =>
if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) {
if (!settings.overrideVars.value)
unit.error(tree.pos, "super may be not be used on " + sym.accessedOrSelf)
} else if (isDisallowed(sym)) {
unit.error(tree.pos, "super not allowed here: use this." + name.decode + " instead")
}
transformSuperSelect(sel)

case _ =>
mayNeedProtectedAccessor(sel, List(EmptyTree), true)
}
transformSuperSelect(sel)

case DefDef(mods, name, tparams, vparamss, tpt, rhs) if tree.symbol.isMethodWithExtension =>
treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, withInvalidOwner(transform(rhs)))

case TypeApply(sel @ Select(qual, name), args) =>
mayNeedProtectedAccessor(sel, args, true)

case sel @ Select(qual, name) =>
mayNeedProtectedAccessor(sel, List(EmptyTree), true)

case Assign(lhs @ Select(qual, name), rhs) =>
if (lhs.symbol.isVariable &&
lhs.symbol.isJavaDefined &&
Expand All @@ -311,10 +326,12 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case Apply(fn, args) =>
assert(fn.tpe != null, tree)
treeCopy.Apply(tree, transform(fn), transformArgs(fn.tpe.params, args))

case Function(vparams, body) =>
withInvalidOwner {
treeCopy.Function(tree, vparams, transform(body))
}

case _ =>
super.transform(tree)
}
Expand Down
1 change: 1 addition & 0 deletions test/files/pos/inline-access-levels.flags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-optimise -Xfatal-warnings -Yinline-warnings
10 changes: 10 additions & 0 deletions test/files/pos/inline-access-levels/A_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package test

object A {

private var x: Int = 0

@inline def actOnX(f: Int => Int) = {
x = f(x)
}
}
11 changes: 11 additions & 0 deletions test/files/pos/inline-access-levels/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package test

object Test {

def main(args: Array[String]) {

A.actOnX(_ + 1)

}

}

0 comments on commit 2fd4df8

Please sign in to comment.