-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add annotations phase #1693
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 annotations phase #1693
Conversation
* | ||
* TODO: Once we have fully bootstrapped, I would prefer if we expressed | ||
* unimport with an `override` modifier, and generalized it to all imports. | ||
* I believe this would be more transparent than the curren set of conditions. E.g. |
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.
Super-nitpick: curren => current
:)
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.
Another concern is about how annotation macros fit into this picture. Current implementation doesn't allow expansion during annotate
phase, as it returns Unit
. Adding/removing top-level definitions in macros can also be very tricky with indexing.
It seems a relative reliable way is to expand macros inside expand
during indexing phase -- and we need to restrict that annotation macros can't be used in the same compilation run when they're defined.
original match { | ||
case original: MemberDef => addAnnotations(denot.symbol, original) | ||
case _ => | ||
} |
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.
It's not clear to me why we need to addAnnotations
again for ValDef
and DefDef
here, as they are already handled by a call to annotate
when they are indexed (in ClassCompleter
and typedBlockStats
).
Is it just for breaking the cyclic dependence between Predef
and deprecated
in test compileStdLib
as commented before? Then maybe a comment here as well.
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.
Annotations, and classes or objects containing them, might be completed out of order as part of the annotations phase. It seems necessary that these symbols get annotated on completion, or otherwise we'd introduce a compilation order dependency.
// | ||
// `@ann` is evaluated in the context just outside `C`, where the `a.b` | ||
// import is visible but the `d.e` import is forgotten. This measure is necessary | ||
// in order to avoid cycles. |
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 lexical scope for @ann
is very counter-intuitive. If it's only some rare erroneous programs cause cycles, it seems justified to keep the intuitive scoping rules as a trade off.
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.
@odersky Can you provide an example of a program that leads to spurious cycles?
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.
@xeno-by I had lots of failing test cases in the regression tests. They failed with CyclicReference errors. I did not keep track of which ones.
@@ -6,7 +6,7 @@ import java.io.{ | |||
File, PrintWriter, PrintStream, StringWriter, Writer, OutputStream, | |||
ByteArrayOutputStream => ByteOutputStream | |||
} | |||
import java.lang.{Class, ClassLoader} | |||
import java.lang.{Class, ClassLoader, Thread, System, StringBuffer} |
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.
Is this something that should be handled by the rewriting tool?
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 missing context, what exactly do you mean by "this"?
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.
See commit message "Honor the new scheme where any explicit import of a root import will disable the root import."
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 sounds like a prime candidate for rewriting. I opened scalacenter/scalafix#21
@@ -1135,7 +1137,13 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit | |||
def completeAnnotations(mdef: untpd.MemberDef, sym: Symbol)(implicit ctx: Context): Unit = { | |||
// necessary to force annotation trees to be computed. | |||
sym.annotations.foreach(_.ensureCompleted) | |||
val annotCtx = ctx.outersIterator.dropWhile(_.owner == sym).next | |||
lazy val annotCtx = { |
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.
Would be nice to add a comment explaining why this is needed as the commit message does.
* that are already added to the symbol. | ||
*/ | ||
def addAnnotations(sym: Symbol, stat: MemberDef)(implicit ctx: Context) = { | ||
// (1) The context in which an annotation of a top-evel class or module is evaluated |
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.
typo: top-evel -> top-level
// (1) The context in which an annotation of a top-evel class or module is evaluated | ||
// is the closest enclosing context which has the enclosing package as owner. | ||
// (2) The context in which an annotation for any other symbol is evaluated is the | ||
// closest enclosing context which has the owner of the class enclpsing the symbol as owner. |
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.
typo: enclpsing -> enclosing
@@ -6,7 +6,7 @@ import java.io.{ | |||
File, PrintWriter, PrintStream, StringWriter, Writer, OutputStream, | |||
ByteArrayOutputStream => ByteOutputStream | |||
} | |||
import java.lang.{Class, ClassLoader} | |||
import java.lang.{Class, ClassLoader, Thread, System, StringBuffer} |
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.
See commit message "Honor the new scheme where any explicit import of a root import will disable the root import."
1a07ff3
to
bf84725
Compare
Rebased to master |
Had duplications of `import` before. Also: add import info when printing contexts.
We got a hard to track down error when changing to the new annotations elaboration scheme (should be in the next commit): When running `testNonCyclic`, `DotClass` was not found in object Trees even though it was imported from `util`. It turned out that the import was ignored because the `util` symbol was completing. This commit adds a warning when this happens. The warning currently applies only to named imports because several false negatives were encountered if we do this also on wildcard imports. I.e. we get a warning, but the searched after symbol is not a member of the wildcard qualifier. This commit also refactors namedImportRef, so that `site` is only computed when the name to reseolve appears in the selector list. That change made the previously observed error go away because less is now forced.
Honor the new scheme where any explicit import of a root import will disable the root import.
It was broken before, since it worked only on wildcard imports.
Got a "next on empty iterator" exception before.
If we want to do annotation macros right, we need to add annotations before completing definitions. This commit achieves that by adding a new "phase" between index and typecheck.
Need to evaluate annotation arguments in an expression context, since classes defined in asuch arguments should not be entered into enclosing class. Fixes scala#1647
This PR also fixes scala#1649
bf84725
to
e1d79a2
Compare
New phase for entering annotations
If we want to do annotation macros right, we need to add
annotations before completing definitions. This commit achieves
that by adding a new "phase" between index and typecheck.
Also: Fixes #1647 be tweaking the context in which we evaluate annotation argumnents
Review by @liufengyun or @olafurpg