-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add transparent methods #4622
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
Add transparent methods #4622
Conversation
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.
Hello, and thank you for opening this PR! 🎉
All contributors have signed the CLA, thank you! ❤️
Commit Messages
We want to keep history, but for that to actually be useful we have
some rules on how to format our commit messages (relevant xkcd).
Please stick to these guidelines for commit messages:
- Separate subject from body with a blank line
- When fixing an issue, start your commit message with
Fix #<ISSUE-NBR>:
- Limit the subject line to 72 characters
- Capitalize the subject line
- Do not end the subject line with a period
- Use the imperative mood in the subject line ("Add" instead of "Added")
- Wrap the body at 80 characters
- Use the body to explain what and why vs. how
adapted from https://chris.beams.io/posts/git-commit
Have an awesome day! ☀️
@gsps I think this is the right basis to build on for step 1. Can you review this with the aim to merge early and then we add the TypeOf abstractions on top? |
Looking through this PR I noticed lots of unrelated commits and finally saw that there's another PR that includes the prefix up to "Addressing reviewer comments". I guess I'll only do my review from that point on. |
@@ -363,7 +363,10 @@ object Flags { | |||
/** Symbol is a Java default method */ | |||
final val DefaultMethod = termFlag(38, "<defaultmethod>") | |||
|
|||
/** Symbol is a Java enum */ | |||
/** Labelled with `transparent` modifier */ | |||
final val Transparent = termFlag(39, "transparent") |
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.
Why not make transparent a commonFlag
, if we use it that way below anyways?
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.
Since there are no transparent
types, it should not apply to them.
@@ -779,7 +779,13 @@ object SymDenotations { | |||
|
|||
def isSkolem: Boolean = name == nme.SKOLEM | |||
|
|||
def isInlineMethod(implicit ctx: Context): Boolean = is(InlineMethod, butNot = Accessor) | |||
def isInlinedMethod(implicit ctx: Context): Boolean = |
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.
I think the method's and the flag's name should match (so probably isInlineMethod
, i.e. minus the d
).
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.
I was thinking if we keep something like inline
as a modifier we should rename it to inlined
instead. Then we don't have a clash with the @inline
annotation, and it's a bit cleaner. transparent
and inlined
are both adjectives, whereas it's a stretch to call inline
an adjective.
@@ -90,6 +90,11 @@ object Inliner { | |||
} | |||
} | |||
|
|||
def isLocal(sym: Symbol, inlineMethod: Symbol)(implicit ctx: Context) = |
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.
This doesn't seem to be used anywhere. (The following commit does use it.)
@@ -1113,7 +1113,7 @@ class Namer { typer: Typer => | |||
|
|||
// println(s"final inherited for $sym: ${inherited.toString}") !!! | |||
// println(s"owner = ${sym.owner}, decls = ${sym.owner.info.decls.show}") | |||
def isInline = sym.is(FinalOrInline, butNot = Method | Mutable) | |||
def isInline = sym.is(FinalOrInlineOrTransparent, butNot = Method | Mutable) |
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.
Not sure if it's worth adding Transparent
to the exception here, since the handling of return types of transparent methods in widenRhs
will have to be more different anyways (it should be allowed to infer a TermRef, for instance; think transparent def unapply(x: Foo) = x
)
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.
Yes, that was only done as a temporary measure because I could not decide yet whether Java final constants should be called inline(d)
or transparent
. Probably transparent
, but for now it's inline
.
@@ -1128,7 +1128,8 @@ class Namer { typer: Typer => | |||
// it would be erased to BoxedUnit. | |||
def dealiasIfUnit(tp: Type) = if (tp.isRef(defn.UnitClass)) defn.UnitType else tp | |||
|
|||
val rhsCtx = ctx.addMode(Mode.InferringReturnType) | |||
var rhsCtx = ctx.addMode(Mode.InferringReturnType) | |||
if (sym.isTransparentMethod) rhsCtx = rhsCtx.addMode(Mode.TransparentBody) |
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.
I'm not sure TransparentBody
should be a Mode. If it is, shouldn't it also be set in the other tree traversing helpers besides typer, i.e., TreeAccumulator
and MegaPhase#transformTree
? All of those have localContext
helpers (in case of typer its in NamerContextOps
, the other two are local defs) which currently set the owner, among other things.
As an alternative, we could deduce whether we are in a transparent context by walking the context's owner chain and checking for Transparent
. Ideally that query would be cached by the context (and its descendants).
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.
Good point. Since it's a single bit we cache, it could still go into the Mode
structure (context fields are a precious resource). But it could be maintained fully automatically. I'll do that change.
@@ -104,14 +94,14 @@ object Inliner { | |||
* to have the inlined method as owner. | |||
*/ | |||
def registerInlineInfo( | |||
sym: SymDenotation, treeExpr: Context => Tree)(implicit ctx: Context): Unit = { | |||
sym.unforcedAnnotation(defn.BodyAnnot) match { | |||
inlined: Symbol, treeExpr: Context => Tree)(implicit ctx: Context): Unit = { |
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.
Docs should be updated. Maybe call it inlineSym
, since it's not inlined at this point?
@@ -0,0 +1,31 @@ | |||
object Test extends App { |
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.
Maybe give this file and its '.check' companion a more descriptive name like transparent.scala
or TransparentToNat.scala
?
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.
I planned to extend this test with more typelevel operations as we go along.
super.transform(accessorIfNeeded(tree)) | ||
} | ||
|
||
override def transform(tree: Tree)(implicit ctx: Context): 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.
(I have no useful comment, but I will say that I don't understand Inliner well enough yet to really judge this change.)
@gsps Regarding the next step, I was wondering whether The downside is that currently annotations on types are forgotten in a large number of cases, which would not be correct in this case. On the other hand, there are a number of other possible annotations that conceptually should behave the same as Note: This would not affect surface syntax, where we'd still keep |
405ace0
to
2cd1590
Compare
@odersky Regarding your last comment, I think it would be more work to change the handling annotated type rather than simply adding a new type. It should maybe be done as a separate generalization step? I feel than TypeOf is going to have a large impact on typer than other potential annotations like |
2cd1590
to
101fe52
Compare
@OlivierBlanvillain I agree it would be easier to get started with a new form of type. But in the end, we will want to refactor to avoid the duplication. |
Currently we have both inline and transparent. It is expected that we will drop inline in the future.
- avoid computing owner of NoSymbol
This was the enclosing class instead of the method containing the annotation. Fixing this is surprisingly hard.
- premature optimization, we can just inspect the owner chain, - if we need it, it should be an automatically updated cache
2bae1f6
to
b359c7d
Compare
#4620 is in now. Rebased on top of current master. |
I believe if we can do it, it would be ultimately better to base this on |
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!
0th step, building on #4620: Add transparent methods.