Skip to content

Conversation

@milessabin
Copy link
Contributor

@milessabin milessabin commented Sep 11, 2018

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 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, which
always have empty trees in this case, were never detected as recursive.

Finally, 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.

@milessabin milessabin added this to the 2.13.0-RC1 milestone Sep 11, 2018
@milessabin milessabin requested a review from adriaanm September 11, 2018 11:14
Copy link
Contributor

@adriaanm adriaanm left a 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 = {
Copy link
Contributor

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?

Copy link
Contributor

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?

Copy link
Contributor Author

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))
Copy link
Contributor

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?

Copy link
Contributor Author

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).

Copy link
Contributor Author

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,
Copy link
Contributor

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 (

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())
))
), and call the ClassDef factory method at
def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], body: List[Tree], superPos: Position): ClassDef = {

@milessabin milessabin force-pushed the topic/byname-implicits-and-macros branch from a9dd3c0 to 45ef876 Compare October 28, 2018 18:38
@milessabin milessabin dismissed adriaanm’s stale review October 28, 2018 18:39

Addressed review comments

@milessabin
Copy link
Contributor Author

Also rebased.

@milessabin
Copy link
Contributor Author

The failure on Travis appears to be another instance of scala/scala-dev#570.

@SethTisue
Copy link
Member

SethTisue commented Nov 6, 2018

@milessabin rebasing again should fix Travis

@milessabin milessabin force-pushed the topic/byname-implicits-and-macros branch from 45ef876 to 3c70a51 Compare November 7, 2018 13:14
@milessabin
Copy link
Contributor Author

Rebased.

@milessabin
Copy link
Contributor Author

Travis failure this time is a gateway timeout ... I've restarted the job.

@milessabin
Copy link
Contributor Author

@adriaanm this is ready to go now ...

@SethTisue
Copy link
Member

new Travis failure is

[warn] 8 warnings found
[error] ## Exception when compiling 161 sources to /home/travis/build/scala/scala/build/quick/classes/reflect
[error] null
[error] scala.tools.nsc.typechecker.Typers$Typer.makeAccessible(Typers.scala:548)
[error] scala.tools.nsc.typechecker.Typers$Typer.$anonfun$typed1$60(Typers.scala:5074)

doesn't look familiar to me

@lrytz
Copy link
Member

lrytz commented Nov 8, 2018

This is the same SOE as initially reported in scala/scala-dev#570, if you look a little bit further down:

[error] java.lang.StackOverflowError
[error] 	at scala.tools.nsc.typechecker.Typers$Typer.makeAccessible(Typers.scala:548)
[error] 	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$typed1$60(Typers.scala:5074)
[error] 	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$silent$2(Typers.scala:717)
[error] 	at scala.tools.nsc.typechecker.Typers$Typer.silent(Typers.scala:717)
[error] 	at scala.tools.nsc.typechecker.Typers$Typer.typedSelect$1(Typers.scala:5074)
[error] 	at scala.tools.nsc.typechecker.Typers$Typer.typedSelectOrSuperCall$1(Typers.scala:5131)
[error] 	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5676)
[error] 	at scala.tools.nsc.transform.Erasure$Eraser.typed1(Erasure.scala:797)

I guess someone catches the SOE.

@milessabin
Copy link
Contributor Author

@lrytz am I right that the SOE isn't an issue for this PR, it's still scala/scala-dev#570?

@lrytz
Copy link
Member

lrytz commented Nov 8, 2018

yes!

@milessabin milessabin force-pushed the topic/byname-implicits-and-macros branch from 3c70a51 to c803691 Compare November 9, 2018 14:19
@milessabin
Copy link
Contributor Author

Rebased following #7375.

@milessabin
Copy link
Contributor Author

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.
@milessabin milessabin force-pushed the topic/byname-implicits-and-macros branch from c803691 to 371d87c Compare November 21, 2018 11:57
@milessabin
Copy link
Contributor Author

Rebased.

@adriaanm
Copy link
Contributor

Sorry about the delay.

@adriaanm adriaanm merged commit 046d96d into scala:2.13.x Nov 21, 2018
@milessabin
Copy link
Contributor Author

Thanks!

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.

4 participants