Skip to content

Make inline vals effectively erased #8836

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

Conversation

nicolasstucki
Copy link
Contributor

Inline vals are erased unless they implement a non-inline interface.
This follows are the same rules used for defs.

@nicolasstucki nicolasstucki self-assigned this Apr 29, 2020
@nicolasstucki nicolasstucki force-pushed the make-inline-vals-effectively-erased branch 11 times, most recently from e913d4c to eb39009 Compare April 30, 2020 14:22
@nicolasstucki nicolasstucki marked this pull request as ready for review April 30, 2020 15:31
Copy link
Contributor

@liufengyun liufengyun left a comment

Choose a reason for hiding this comment

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

Otherwise, LGTM

/** Is this a Scala 2 macro */
final def isScala2Macro(implicit ctx: Context): Boolean = is(Macro) && symbol.owner.is(Scala2x)

/** An erased value or an inline method.
*/
def isEffectivelyErased(implicit ctx: Context): Boolean =
is(Erased) || isInlineMethod && !isRetainedInlineMethod
is(Erased) || is(Inline) && !isRetainedInline && !hasAnnotation(defn.ScalaStaticAnnot)
Copy link
Contributor

Choose a reason for hiding this comment

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

What we need the test !hasAnnotation(defn.ScalaStaticAnnot)?

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 @static annotation is supposed to guarantee that the field is emitted in the bytecode with the original signature. Hence we cannot remove the definition. There was one bytecode test with a final val that failed without this test.

@nicolasstucki nicolasstucki force-pushed the make-inline-vals-effectively-erased branch from 327ef1b to 21a9bf0 Compare May 1, 2020 05:39
@nicolasstucki nicolasstucki requested a review from liufengyun May 1, 2020 05:54
Inline vals are erased unless they implement a non-inline interface.
This follows are the same rules used for defs.
@nicolasstucki nicolasstucki force-pushed the make-inline-vals-effectively-erased branch from 2c3f6c9 to 01ca6e6 Compare May 1, 2020 07:36
Copy link
Contributor

@liufengyun liufengyun left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -34,19 +35,26 @@ class PruneErasedDefs extends MiniPhase with SymTransformer { thisTransform =>

override def transformApply(tree: Apply)(implicit ctx: Context): Tree =
if (tree.fun.tpe.widen.isErasedMethod)
cpy.Apply(tree)(tree.fun, tree.args.map(arg => ref(defn.Predef_undefined)))
cpy.Apply(tree)(tree.fun, tree.args.map(trivialErasedTree))
else tree
Copy link
Contributor

Choose a reason for hiding this comment

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

In PostTyper, we also have logic to erase arguments. Is there a duplication of code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We keep in TASTy the contents of the erased trees. These are erased here. In PostTyper we only remove contents of erased definitions that were generated by inlining code (i.e. needed for typing). I will recheck what happens if we don't remove them in PostTyper, but fur sure the TASTy will increase.

@nicolasstucki nicolasstucki merged commit d757454 into scala:master May 1, 2020
@nicolasstucki nicolasstucki deleted the make-inline-vals-effectively-erased branch May 1, 2020 12:06
@bishabosha
Copy link
Member

bishabosha commented Jun 15, 2020

This also affects final val msg = "Hello, World", so its not available to Scala 2

@nicolasstucki
Copy link
Contributor Author

These get erased after pickling. They should be available in the TASTy.

@bishabosha
Copy link
Member

bishabosha commented Jun 15, 2020

I was hoping to be able to constant fold it but it seems scalac doesn't always do that,
e.g.

object HelloWorld {
  final val msg = "Hello World"
}

object Test {
  def foo = HelloWorld.msg // replaced by `"Hello World"`
  def bar = (HelloWorld.msg: "Hello World") // calls HelloWorld$.MODULE$.msg()
  def baz(m: HelloWorld.msg.type) = m
  def testBaz = baz(HelloWorld.msg) // calls HelloWorld$.MODULE$.msg()
}

@bishabosha
Copy link
Member

scala/bug#12040

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.

3 participants