Skip to content
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

Fix #2772: Special case Devalify for java.lang.System.* #2781

Merged
merged 7 commits into from
Jun 25, 2017

Conversation

OlivierBlanvillain
Copy link
Contributor

@smarter thanks for the nice minimization!

Also update DropNoEffects to keep Select on static java field, to make sure a
Java class doesn't end up in value position. That's another bug than the one
reported in scala#2772, but it got triggered by the new test case.
false
} else
readingOnlyVals(qual)

case t: Ident if !t.symbol.is(Mutable) && !t.symbol.is(Method) && !t.symbol.info.dealias.isInstanceOf[ExprType] =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing says that there might not be an Ident corresponding to System.in, and in that case you would still inline it. Maybe add a isReallyMutable instead that you would use everywhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation of this case calls desugarIdent and recuse, I think the case where the Ident is System.in is covered.

@DarkDimius Could you explain why we even need this desugarIdent, why not use Select everywhere directly? Also where would be the proper was to move that function to factor out the version that's currently copy pasted in the backend?

case Select(rec, _) if t.symbol.is(Method) =>
if (t.symbol.isGetter && !t.symbol.is(Mutable)) readingOnlyVals(rec) // getter of a immutable field
if (t.symbol.isGetter && !t.symbol.is(Mutable))
readingOnlyVals(rec) // getter of a immutable field
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: a -> an

@smarter
Copy link
Member

smarter commented Jun 19, 2017

This also won't work if someone uses reflection to mutate a final field. I suggest creating a documentation page for -optimize to list all the things you're not allowed to do in your code for it to work.

@OlivierBlanvillain
Copy link
Contributor Author

I went thought all usages of Mutable inside the localopt package and I found another potential but in DropGoodCasts, thanks for the suggestion! (All other uses of is(Mutable) shouldn't be affect by this System.stuff because it checks on safe things such as ValDefs).

@OlivierBlanvillain
Copy link
Contributor Author

(I will later properly populate this documentation with content from the semester project report)

@@ -164,7 +164,17 @@ class Devalify extends Optimisation {
case _ => t
}

def readingOnlyVals(t: Tree)(implicit ctx: Context): Boolean = dropCasts(t) match {
def readingOnlyVals(t: Tree)(implicit ctx: Context): Boolean = {
def isGetterOfAImmutableField = t.symbol.isGetter && !t.symbol.is(Mutable)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of An ImmutableField

@@ -146,4 +146,15 @@ object Simplify {
case _ => None
}
}

// System.in is static final fields that, for legacy reasons, must be
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is -> is a
fields -> field

This description is a bit confusing: it starts by talking just about System.in and then mention the rest.
The name of the method is also not great, it's too easy to confuse with is(Mutable), I would call it something like isEffectivelyMutable, isReallyMutable or isChanging

// https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.5.4
def isMutable(t: Tree)(implicit ctx: Context): Boolean = t match {
case _ if t.symbol.is(Mutable) => true
case s: Symbol => (s.symbol == defn.SystemModule)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you want s.owner.symbol here.


The Dotty compiler implements several local optimisations to generate faster bytecode. These optimisations can be enabled by compiling with the `-optimise` flag. The current best source of documentation about what tree transformations are performed under `-optimise` is the Scaladoc classes in the [localopt package](https://github.com/lampepfl/dotty/tree/master/compiler/src/dotty/tools/dotc/transform/localopt).

Local optimisations assumes no use of Java Reflection to mutate static final fields.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about non-static final fields, are those safe to mutate?

*/
def isEffectivelyMutable(t: Tree)(implicit ctx: Context): Boolean = t match {
case _ if t.symbol.is(Mutable) => true
case s: Select => (s.symbol == defn.SystemModule)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still looks wrong to me, s may be System.in, so you need to look at the owner

@smarter smarter merged commit 45e4030 into scala:master Jun 25, 2017
@allanrenucci allanrenucci deleted the final-not-final branch December 14, 2017 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants