@@ -22,10 +22,23 @@ import NameOps._
22
22
import StdNames ._
23
23
24
24
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.
29
42
*/
30
43
class CheckReentrant extends MiniPhaseTransform { thisTransformer =>
31
44
import ast .tpd ._
@@ -50,7 +63,7 @@ class CheckReentrant extends MiniPhaseTransform { thisTransformer =>
50
63
sym.hasAnnotation(unsharedAnnot())
51
64
52
65
def scanning (sym : Symbol )(op : => Unit )(implicit ctx : Context ): Unit = {
53
- println (i " ${" " * indent}scanning $sym" )
66
+ ctx.log (i " ${" " * indent}scanning $sym" )
54
67
indent += 1
55
68
try op
56
69
finally indent -= 1
@@ -63,7 +76,9 @@ class CheckReentrant extends MiniPhaseTransform { thisTransformer =>
63
76
for (sym <- cls.classInfo.decls)
64
77
if (sym.isTerm && ! sym.isSetter && ! isIgnored(sym))
65
78
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)
67
82
shared += sym
68
83
} else if (! sym.is(Method ) || sym.is(Accessor | ParamAccessor )) {
69
84
scanning(sym) {
0 commit comments