-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Fix interactions between macros and by-name implicits #7199
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 interactions between macros and by-name implicits #7199
Conversation
adriaanm
left a comment
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.
Let's see if we can refine this a bit. Could you also split out the different fixes into separate commits?
| else { | ||
| val typer = newTyper(this) | ||
|
|
||
| def changeNonLocalOwners(tree: Tree, newowner: Symbol): 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.
Could you move this closer to class ChangeOwnerTraverser, so that it's more discoverable for potential future usage?
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, after some refactoring, this could be a subclass of ChangeOwnerTraverser?
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've moved this next to ChangeOwnerTraverser and lifted the LocalOwnerTraverser out. It doesn't really work as a subclass of the former.
| } | ||
| val vname = newTermName(typer.fresh.newName("lazyDefns$")) | ||
| val vdef0 = | ||
| ValDef(Modifiers(FINAL | SYNTHETIC), vname, Ident(cname), New(Ident(cname), Nil)) |
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.
Could include a signature for the valdef. It's simply cdef.symbol.tpe_*, right?
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 do you mean by that? The ValDef has a tpt: Ident(cname).
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.
Ahh ... OK, I think I get it :-)
|
|
||
| val cname = newTypeName(typer.fresh.newName("LazyDefns$")) | ||
| val cdef0 = | ||
| ClassDef(Modifiers(FINAL | SYNTHETIC), cname, Nil, |
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.
If possible, it would be preferable to use an approach closer to the one in synthesizePartialFunction (
scala/src/compiler/scala/tools/nsc/typechecker/Typers.scala
Lines 2805 to 2814 in 036143b
| anonClass setInfo ClassInfoType(parents(matchResTp), newScope, anonClass) | |
| List(applyMeth, isDefinedAtMethod) | |
| } | |
| members foreach (m => anonClass.info.decls enter m.symbol) | |
| val typedBlock = typedPos(tree.pos, mode, pt) { | |
| Block(ClassDef(anonClass, NoMods, ListOfNil, members, tree.pos.focus), atPos(tree.pos.focus)( | |
| Apply(Select(New(Ident(anonClass.name).setSymbol(anonClass)), nme.CONSTRUCTOR), List()) | |
| )) |
| def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], body: List[Tree], superPos: Position): ClassDef = { |
a9dd3c0 to
45ef876
Compare
|
Also rebased. |
|
The failure on Travis appears to be another instance of scala/scala-dev#570. |
|
@milessabin rebasing again should fix Travis |
45ef876 to
3c70a51
Compare
|
Rebased. |
|
Travis failure this time is a gateway timeout ... I've restarted the job. |
|
@adriaanm this is ready to go now ... |
|
new Travis failure is doesn't look familiar to me |
|
This is the same SOE as initially reported in scala/scala-dev#570, if you look a little bit further down: I guess someone catches the SOE. |
|
@lrytz am I right that the SOE isn't an issue for this PR, it's still scala/scala-dev#570? |
|
yes! |
3c70a51 to
c803691
Compare
|
Rebased following #7375. |
|
@SethTisue The failure I'm seeing here is a gateway timeout: https://travis-ci.org/scala/scala/jobs/452899122#L5233. |
An unnecessary check in Implicits.scala excludes implicit expansion sites with empty trees when attempting to determine if an implicit resolution was recursive meant that implicit macros, which always have empty trees in this case, were never detected as recursive.
While prototyping a version of shapeless which replaces Lazy with by-name implicits it emerged that implicit resolutions which involve both by-name implicits and implicit macros can produce dictionaries which type checked but which had broken owner chains. This had been anticipated (see 5dd9909) but the ownership change performed there wasn't thoroughgoing enough. The implicit dictionary is now encoded as, final class LazyDefns$n extends java.io.Serializable { final val rec$m ... } val lazyDefns$n = new LazyDefns$ lazyDefns$n.rec$m rather than as an object, to eliminate the unecessary overhead of object lazy initialization and to allow serialzation in rare cases where the enclosing value is captured. With this commit a Lazy-free shapeless build is possible.
c803691 to
371d87c
Compare
|
Rebased. |
|
Sorry about the delay. |
|
Thanks! |
While prototyping a version of shapeless which replaces
Lazywith by-name implicits it emerged that implicit resolutions which involve both by-name implicits and implicit macros can produce dictionarieswhich type check but which have broken owner chains.
This had been anticipated (see 5dd9909) but the ownership change performed there wasn't thoroughgoing enough.
In addition, an unnecessary check in
Implicits.scala, excluding implicit expansion sites with empty trees when attempting to determine if an implicit resolution was recursive, meant that implicit macros, whichalways have empty trees in this case, were never detected as recursive.
Finally, the implicit dictionary is now encoded as,
rather than as an object, to eliminate the unecessary overhead of object lazy initialization and to allow serialzation in rare cases where the enclosing value is captured.
With this commit a
Lazy-free shapeless build is possible.