Skip to content

Commit 0672b6d

Browse files
authored
Merge pull request #4804 from Medowhill/issue4404
Fix #4404: In LambdaLift, modify flags properly
2 parents fe8d050 + 7b27b34 commit 0672b6d

File tree

7 files changed

+82
-2
lines changed

7 files changed

+82
-2
lines changed

compiler/src/dotty/tools/dotc/transform/LambdaLift.scala

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,11 +338,23 @@ object LambdaLift {
338338
else (topClass, JavaStatic)
339339
}
340340
else (lOwner, EmptyFlags)
341+
// Drop Module because class is no longer a singleton in the lifted context.
342+
var initFlags = local.flags &~ Module | Private | Lifted | maybeStatic
343+
if (local is Method) {
344+
if (newOwner is Trait)
345+
// Drop Final when a method is lifted into a trait.
346+
// According to the JVM specification, a method declared inside interface cannot have the final flag.
347+
// "Methods of interfaces may have any of the flags in Table 4.6-A set except ACC_PROTECTED, ACC_FINAL, ..."
348+
// (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6)
349+
initFlags = initFlags &~ Final
350+
else
351+
// Add Final when a method is lifted into a class.
352+
initFlags = initFlags | Final
353+
}
341354
local.copySymDenotation(
342355
owner = newOwner,
343356
name = newName(local),
344-
initFlags = local.flags &~ Module &~ Final | Private | Lifted | maybeStatic,
345-
// drop Module because class is no longer a singleton in the lifted context.
357+
initFlags = initFlags,
346358
info = liftedInfo(local)).installAfter(thisPhase)
347359
}
348360
for (local <- free.keys)

tests/run/i4404a.check

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
false
2+
false
3+
false
4+
true
5+
false
6+
true
7+
true
8+
true

tests/run/i4404a.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import java.lang.reflect.Modifier
2+
3+
class Car
4+
final class Volvo extends Car
5+
6+
object Car {
7+
val car = new Car {}
8+
}
9+
10+
object Test {
11+
def main(args: Array[String]) = {
12+
List(new Car, new Volvo, Car, Car.car)
13+
.map(_.getClass.getModifiers)
14+
.foreach { m =>
15+
println(Modifier.isPrivate(m))
16+
println(Modifier.isFinal(m))
17+
}
18+
}
19+
}

tests/run/i4404b.check

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
true
2+
true

tests/run/i4404b.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import java.lang.reflect.Modifier
2+
3+
object Test {
4+
val x = {
5+
final class Foo
6+
new Foo
7+
}
8+
9+
def main(args: Array[String]) = {
10+
val m = x.getClass.getModifiers
11+
println(Modifier.isPrivate(m))
12+
println(Modifier.isFinal(m))
13+
}
14+
}

tests/run/i4404c.check

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
false
2+
true

tests/run/i4404c.scala

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import java.lang.reflect.Modifier
2+
3+
trait T {
4+
def f = {
5+
def f0 = ()
6+
}
7+
}
8+
9+
class C {
10+
def g = {
11+
def g0 = ()
12+
}
13+
}
14+
15+
object Test {
16+
def main(args: Array[String]) = {
17+
List((new T {}).getClass.getInterfaces.head, (new C).getClass)
18+
.map(_.getDeclaredMethods)
19+
.foreach { ms =>
20+
println(ms.exists(m => Modifier.isFinal(m.getModifiers)))
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)