-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Make inline vals effectively erased #8836
Conversation
e913d4c
to
eb39009
Compare
There was a problem hiding this 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) |
There was a problem hiding this comment.
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)
?
There was a problem hiding this comment.
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.
327ef1b
to
21a9bf0
Compare
Inline vals are erased unless they implement a non-inline interface. This follows are the same rules used for defs.
2c3f6c9
to
01ca6e6
Compare
There was a problem hiding this 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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
This also affects |
These get erased after pickling. They should be available in the TASTy. |
I was hoping to be able to constant fold it but it seems scalac doesn't always do that, 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()
} |
Inline vals are erased unless they implement a non-inline interface.
This follows are the same rules used for defs.