Skip to content

Commit 6ec4b0a

Browse files
committed
Merge pull request #607 from dotty-staging/fix/datarace-flags
Fix/datarace flags
2 parents b2634a8 + 397dfd6 commit 6ec4b0a

16 files changed

+91
-34
lines changed

src/dotty/tools/dotc/core/classfile/ClassfileConstants.scala

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -329,55 +329,50 @@ object ClassfileConstants {
329329
final val impdep1 = 0xfe
330330
final val impdep2 = 0xff
331331

332+
import Flags._
332333
abstract class FlagTranslation {
333-
import Flags._
334334

335-
private var isAnnotation = false
336-
private var isClass = false
337-
private def initFields(flags: Int) = {
338-
isAnnotation = (flags & JAVA_ACC_ANNOTATION) != 0
339-
isClass = false
340-
}
335+
protected def baseFlags(jflags: Int) = EmptyFlags
336+
protected def isClass: Boolean = false
341337

342338
private def translateFlag(jflag: Int): FlagSet = (jflag: @switch) match {
343339
case JAVA_ACC_PRIVATE => Private
344340
case JAVA_ACC_PROTECTED => Protected
345341
case JAVA_ACC_FINAL => Final
346342
case JAVA_ACC_SYNTHETIC => Synthetic
347343
case JAVA_ACC_STATIC => JavaStatic
348-
case JAVA_ACC_ABSTRACT => if (isAnnotation) EmptyFlags else if (isClass) Abstract else Deferred
349-
case JAVA_ACC_INTERFACE => if (isAnnotation) EmptyFlags else PureInterfaceCreationFlags | JavaDefined
344+
case JAVA_ACC_ABSTRACT => if (isClass) Abstract else Deferred
345+
case JAVA_ACC_INTERFACE => PureInterfaceCreationFlags | JavaDefined
350346
case _ => EmptyFlags
351347
}
352348

353349
private def addFlag(base: FlagSet, jflag: Int): FlagSet =
354350
if (jflag == 0) base else base | translateFlag(jflag)
355351

356352
private def translateFlags(jflags: Int, baseFlags: FlagSet): FlagSet = {
353+
val nflags =
354+
if ((jflags & JAVA_ACC_ANNOTATION) == 0) jflags
355+
else jflags & ~(JAVA_ACC_ABSTRACT | JAVA_ACC_INTERFACE) // annotations are neither abstract nor interfaces
357356
var res: FlagSet = baseFlags | JavaDefined
358-
res = addFlag(res, jflags & JAVA_ACC_PRIVATE)
359-
res = addFlag(res, jflags & JAVA_ACC_PROTECTED)
360-
res = addFlag(res, jflags & JAVA_ACC_FINAL)
361-
res = addFlag(res, jflags & JAVA_ACC_SYNTHETIC)
362-
res = addFlag(res, jflags & JAVA_ACC_STATIC)
363-
res = addFlag(res, jflags & JAVA_ACC_ABSTRACT)
364-
res = addFlag(res, jflags & JAVA_ACC_INTERFACE)
357+
res = addFlag(res, nflags & JAVA_ACC_PRIVATE)
358+
res = addFlag(res, nflags & JAVA_ACC_PROTECTED)
359+
res = addFlag(res, nflags & JAVA_ACC_FINAL)
360+
res = addFlag(res, nflags & JAVA_ACC_SYNTHETIC)
361+
res = addFlag(res, nflags & JAVA_ACC_STATIC)
362+
res = addFlag(res, nflags & JAVA_ACC_ABSTRACT)
363+
res = addFlag(res, nflags & JAVA_ACC_INTERFACE)
365364
res
366365
}
367366

368-
def classFlags(jflags: Int): FlagSet = {
369-
initFields(jflags)
370-
isClass = true
371-
translateFlags(jflags, EmptyFlags)
372-
}
373-
def fieldFlags(jflags: Int): FlagSet = {
374-
initFields(jflags)
375-
translateFlags(jflags, if ((jflags & JAVA_ACC_FINAL) == 0) Mutable else EmptyFlags)
376-
}
377-
def methodFlags(jflags: Int): FlagSet = {
378-
initFields(jflags)
379-
translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) Bridge else EmptyFlags)
380-
}
367+
def flags(jflags: Int): FlagSet = translateFlags(jflags, baseFlags(jflags))
368+
}
369+
val classTranslation = new FlagTranslation {
370+
override def isClass = true
371+
}
372+
val fieldTranslation = new FlagTranslation {
373+
override def baseFlags(jflags: Int) = if ((jflags & JAVA_ACC_FINAL) == 0) Mutable else EmptyFlags
374+
}
375+
val methodTranslation = new FlagTranslation {
376+
override def baseFlags(jflags: Int) = if ((jflags & JAVA_ACC_BRIDGE) != 0) Bridge else EmptyFlags
381377
}
382-
object FlagTranslation extends FlagTranslation { }
383378
}

src/dotty/tools/dotc/core/classfile/ClassfileParser.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class ClassfileParser(
8989
def parseClass()(implicit ctx: Context): Option[Embedded] = {
9090
val jflags = in.nextChar
9191
val isAnnotation = hasAnnotation(jflags)
92-
val sflags = FlagTranslation.classFlags(jflags)
92+
val sflags = classTranslation.flags(jflags)
9393
val nameIdx = in.nextChar
9494
currentClassName = pool.getClassName(nameIdx)
9595

@@ -163,8 +163,8 @@ class ClassfileParser(
163163
val start = indexCoord(in.bp)
164164
val jflags = in.nextChar
165165
val sflags =
166-
if (method) Flags.Method | FlagTranslation.methodFlags(jflags)
167-
else FlagTranslation.fieldFlags(jflags)
166+
if (method) Flags.Method | methodTranslation.flags(jflags)
167+
else fieldTranslation.flags(jflags)
168168
val name = pool.getName(in.nextChar)
169169
if (!(sflags is Flags.Private) || name == nme.CONSTRUCTOR || ctx.settings.optimise.value) {
170170
val member = ctx.newSymbol(
@@ -632,7 +632,7 @@ class ClassfileParser(
632632
getOwner(jflags),
633633
entry.originalName,
634634
new ClassfileLoader(file),
635-
FlagTranslation.classFlags(jflags),
635+
classTranslation.flags(jflags),
636636
getScope(jflags))
637637
}
638638

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

tests/pos/intersection.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
object intersection {
2+
3+
class A
4+
class B
5+
6+
val x: A => Unit = ???
7+
val y: B => Unit = ???
8+
9+
val z = if (???) x else y
10+
11+
val a: A & B => Unit = z
12+
val b: (A => Unit) | (B => Unit) = z
13+
14+
15+
16+
17+
type needsA = A => Nothing
18+
type needsB = B => Nothing
19+
}

tests/pos/jon.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// This one blows up with a huge type in Scala 2.
2+
// Reported by Jon Pretty in his talk on Scala type inference.
3+
object Test {
4+
5+
val x = List(List, Vector)
6+
7+
val y: List[scala.collection.generic.SeqFactory] = x
8+
}

tests/pos/pets.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Representing the current type
2+
trait Pet {
3+
type This <: Pet
4+
def name: String
5+
def renamed(newName: String): This
6+
}
7+
8+
case class Fish(name: String, age: Int) extends Pet {
9+
type This = Fish
10+
def renamed(newName: String): Fish = copy(name = newName)
11+
}
12+
13+
case class Kitty(name: String, age: Int) extends Pet {
14+
type This = Kitty
15+
def renamed(newName: String): Kitty = copy(name = newName)
16+
}
17+
18+
object Test {
19+
def esquire[A <: Pet](a: A): a.This = a.renamed(a.name + ", Esq.")
20+
val f: Fish = esquire(new Fish("bob", 22))
21+
}

tests/pos/sort.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
object sorting {
2+
3+
val xs: Array[String] = ???
4+
5+
java.util.Arrays.sort(xs, ???)
6+
7+
}

tests/pos/staleSymbol.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
object intersection {
2+
3+
class A
4+
class B
5+
6+
val x: A => Unit = ???
7+
}

0 commit comments

Comments
 (0)