-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #3476: Add Artifact
flag to closures
#3503
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
Conversation
That should indeed fix #3476 but why was the generic signature here wrong in the first place? Couldn't the same issue exist for non-closures? Also, could |
I think that the reason why the signatures are wrong for those nodes is because they are transformed again after Note that scalac also generates a signature that doesn't correspond to the class Foo {
def m[T](x: T): Int => T = (y: Int) => x
}
The discrepancy is not caught by |
@smarter I've been looking into the wrong signatures for lifted methods and classes. I've noticed that lifted methods do not get the Lifted classes are another story. In this example, scalac gives the class the outer reference during class Foo {
def m[T](x: T): Int => T = {
def bar(y: Int) = x
class buzz[U](z: Int) { def boo = x.toString + z.toString }
bar _
}
} I'm not sure what to do here. |
@@ -444,6 +444,7 @@ object LambdaLift { | |||
|
|||
def liftDef(tree: MemberDef)(implicit ctx: Context): Tree = { | |||
val buf = liftedDefs(tree.symbol.owner) | |||
tree.symbol.setFlag(Lifted) |
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 would be better to set the flag when the denotation is transformed in liftLocals: https://github.com/Duhemm/dotty/blob/ee2d91e5e93be553751a2156e911540a66afb1da/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala#L344
When a class is lifted from a method it should not get a generic signature since there is no reason to call it from outside (in fact, we should probably emit them as private classes). When a class is lifted from another class it should get a generic signature, but this seems to already be working correctly: class Foo(x: Int) {
class buzz[U](z: U) { def boo = x.toString + z.toString }
} |
Ping ? |
This way, we will not generate generic java signatures for closures. Note that scalac also marks closures as `Artifact` during `UnCurry`. See: - https://github.com/scala/scala/blob/7c8e4ac0797872190f67d1738251ded1980d8d77/src/compiler/scala/tools/nsc/ast/TreeGen.scala#L260-L272 - https://github.com/scala/scala/blob/7c8e4ac0797872190f67d1738251ded1980d8d77/src/compiler/scala/tools/nsc/transform/UnCurry.scala#L221-L222
@smarter I've addressed your comment and added a test. |
Which comment exactly? I just tried the example from #3503 (comment) and you're still generating a generic signature for the local class |
@@ -500,7 +500,8 @@ object GenericSignatures { | |||
case PolyType(_, _) => | |||
true | |||
case ClassInfo(_, _, parents, _, _) => | |||
foldOver(tp.typeParams.nonEmpty, parents) | |||
// Local classes don't need a signature | |||
!tp.classSymbol.owner.is(Method) && foldOver(tp.typeParams.nonEmpty, parents) |
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.
SymUtils::isLocal
@smarter Sorry, I meant this one: #3503 (comment). I've changed the PR so that no signature is generated for local classes. However, the constructor of local classes may still get a wrong signature. I imagine that this is okay, since scalac will also generate a signature that doesn't match the descriptor: dotc:
scalac:
Finally, not generating signatures for local classes means that code such as: def foo = {
class Foo[U, T <: java.util.List[U]]
classOf[Foo[_, _]].getTypeParameters().mkString(", ")
} will produce different outputs when compiled with scalac or dotc. I don't think this is really a valid use case, but it may be a surprising behavior. |
To be consistent, the methods inside a local class should not get signatures either. |
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.
- Please add more testcases (class inside method, class inside class inside method, ...)
- Is it possible to improve
-Xverify-signature
to catch the kind of invalid signatures we were generating before this PR?
I've changed the PR to avoid generating signatures for all local symbols, and added more test cases. I'd be happy to improve What do you think? Could we leave that for another PR? |
Sure. |
test performance please |
performance test scheduled: 1 job(s) in queue, 1 running. |
Performance test finished successfully: Visit http://dotty-bench.epfl.ch/3503/ to see the changes. Benchmarks is based on merging with master (3cba055) |
This way, we will not generate generic java signatures for closures.
Note that scalac also marks closures as
Artifact
duringUnCurry
.See: