Skip to content

Commit f7ac8df

Browse files
committed
Make sharing violations errors
and use ctx.log for other output.
1 parent 8cf7f0e commit f7ac8df

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

src/dotty/tools/dotc/transform/CheckReentrant.scala

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,23 @@ import NameOps._
2222
import StdNames._
2323

2424

25-
/** The first tree transform
26-
* - ensures there are companion objects for all classes except module classes
27-
* - eliminates some kinds of trees: Imports, NamedArgs
28-
* - stubs out native methods
25+
/** A no-op transform that checks whether the compiled sources are re-entrant.
26+
* If -Ycheck:reentrant is set, the phase makes sure that there are no variables
27+
* that are accessible from a global object. It excludes from checking paths that
28+
* are labeled with one of the annotations
29+
*
30+
* @sharable Indicating a class or val can be safely shared
31+
* @unshared Indicating an object will not be accessed from multiple threads
32+
*
33+
* Currently the analysis is only intended to check the dotty compiler itself. To make
34+
* it generally useful we'd need to add at least the following:
35+
*
36+
* - Handle polymorphic instantiation: We might instantiate a generic class
37+
* with a type that contains vars. If the class contains fields of the generic
38+
* type, this may constitute a path to a shared var, which currently goes undetected.
39+
* - Handle arrays: Array elements are currently ignored because they are often used
40+
* in an immutable way anyway. To do better, it would be helpful to have a type
41+
* for immutable array.
2942
*/
3043
class CheckReentrant extends MiniPhaseTransform { thisTransformer =>
3144
import ast.tpd._
@@ -50,7 +63,7 @@ class CheckReentrant extends MiniPhaseTransform { thisTransformer =>
5063
sym.hasAnnotation(unsharedAnnot())
5164

5265
def scanning(sym: Symbol)(op: => Unit)(implicit ctx: Context): Unit = {
53-
println(i"${" " * indent}scanning $sym")
66+
ctx.log(i"${" " * indent}scanning $sym")
5467
indent += 1
5568
try op
5669
finally indent -= 1
@@ -63,7 +76,9 @@ class CheckReentrant extends MiniPhaseTransform { thisTransformer =>
6376
for (sym <- cls.classInfo.decls)
6477
if (sym.isTerm && !sym.isSetter && !isIgnored(sym))
6578
if (sym.is(Mutable)) {
66-
println(i"GLOBAL ${sym.showLocated}: ${sym.info} <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
79+
ctx.error(
80+
i"""possible data race involving globally reachable ${sym.showLocated}: ${sym.info}
81+
| use -Ylog:checkReentrant+ to find out more about why the variable is reachable.""".stripMargin)
6782
shared += sym
6883
} else if (!sym.is(Method) || sym.is(Accessor | ParamAccessor)) {
6984
scanning(sym) {

0 commit comments

Comments
 (0)