Skip to content

Commit 7a963e0

Browse files
committed
Default to BestEffort mode
1 parent 4247597 commit 7a963e0

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

compiler/src/dotty/tools/dotc/transform/init/Objects.scala

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,19 @@ class Objects(using Context @constructorOnly):
8181
val allowList: Set[Symbol] = Set(SetNode_EmptySetNode, HashSet_EmptySet, Vector_EmptyIterator, MapNode_EmptyMapNode, HashMap_EmptyMap,
8282
ManifestFactory_ObjectTYPE, ManifestFactory_NothingTYPE, ManifestFactory_NullTYPE)
8383

84+
/**
85+
* Whether the analysis work in best-effort mode in contrast to aggressive mode.
86+
*
87+
* - In best-effort mode, the analysis tries to be fast, useful and unobtrusive.
88+
* - In the aggressive mode, the analysis tries to be sound and verbose by spending more check time.
89+
*
90+
* In both mode, there is a worst-case guarantee based on a quota on the
91+
* number of method calls in initializing a global object.
92+
*
93+
* We use a patch to set `BestEffort` to `false` in testing community projects.
94+
*/
95+
val BestEffort: Boolean = true
96+
8497
// ----------------------------- abstract domain -----------------------------
8598

8699
/** Syntax for the data structure abstraction used in abstract domain:
@@ -370,8 +383,14 @@ class Objects(using Context @constructorOnly):
370383

371384
val hasError = ctx.reporter.pendingMessages.nonEmpty
372385
if cache.hasChanged && !hasError then
373-
cache.prepareForNextIteration()
374-
iterate()
386+
if count <= 3 then
387+
cache.prepareForNextIteration()
388+
iterate()
389+
else
390+
if !BestEffort then
391+
report.warning("Giving up checking initializatino of " + classSym + " due to complex code", classSym.sourcePos)
392+
data.checkedObjects += obj
393+
obj
375394
else
376395
data.checkedObjects += obj
377396
obj
@@ -959,15 +978,11 @@ class Objects(using Context @constructorOnly):
959978
if !map.contains(sym) then map.updated(sym, value)
960979
else map.updated(sym, map(sym).join(value))
961980

962-
/** Check if the checker option reports warnings about unknown code
963-
*/
964-
val reportUnknown: Boolean = false
965-
966981
def reportWarningForUnknownValue(msg: => String, pos: SrcPos)(using Context): Value =
967-
if reportUnknown then
968-
report.warning(msg, pos)
982+
if BestEffort then
969983
Bottom
970984
else
985+
report.warning(msg, pos)
971986
UnknownValue
972987

973988
/** Handle method calls `e.m(args)`.
@@ -1122,7 +1137,7 @@ class Objects(using Context @constructorOnly):
11221137
value
11231138
else
11241139
// In future, we will have Tasty for stdlib classes and can abstractly interpret that Tasty.
1125-
// For now, return `UnknownValue` to ensure soundness and trigger a warning when reportUnknown = true.
1140+
// For now, return `UnknownValue` to ensure soundness and trigger a warning when BestEffort = false.
11261141
UnknownValue
11271142
end if
11281143
end if

0 commit comments

Comments
 (0)