Skip to content

Commit 07fded9

Browse files
Introduce conditionally mutable flags wrt completion
Some flags do not fall under the definition of the flags that are not mutated during completion. However, in practice, they are almost never mutated on completion and such an event is easy to predict. An example of such a flag is `deferred` which is set only when compiling opaque types – this is part of what makes opaque types work. It is reasonable, hence, to make sure denotations are counted as current even though they have some of such flags if when querying these flags we can predict that they will not change during completion.
1 parent e8e1f41 commit 07fded9

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

compiler/src/dotty/tools/dotc/core/Flags.scala

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ object Flags {
436436
/** Flags that are not (re)set when completing the denotation
437437
*/
438438
val FromStartFlags: FlagSet = commonFlags(
439-
Module, Package, Deferred, Method, Case,
439+
Module, Package, Method, Case,
440440
HigherKinded, Param, ParamAccessor,
441441
Scala2ExistentialCommon, Mutable, Opaque, Touched, JavaStatic,
442442
OuterOrCovariant, LabelOrContravariant, CaseAccessor,
@@ -451,6 +451,21 @@ object Flags {
451451
val AfterLoadFlags: FlagSet = commonFlags(
452452
FromStartFlags, AccessFlags, Final, AccessorOrSealed, LazyOrTrait, SelfName, JavaDefined)
453453

454+
/** Flags that are not mutated during completion when a certain
455+
* condition is satisfied
456+
*/
457+
object ConditionallyImmutableFlags {
458+
val flagsAndConditions: List[(Flag, (given Contexts.Context) => SymDenotations.SymDenotation => Boolean)] = List(
459+
Deferred -> { denot =>
460+
denot.is(Opaque) && denot.isType &&
461+
!denot.infoOrCompleter.isInstanceOf[SymbolLoader] // If it is loaded, we assume the opaque mechanism has already set the flags correctly
462+
}
463+
)
464+
465+
val flags: FlagSet = flagsAndConditions.map(_._1)
466+
.foldLeft(EmptyFlags) { (accum, next) => accum | next }
467+
}
468+
454469

455470
/** A value that's unstable unless complemented with a Stable flag */
456471
val UnstableValueFlags: FlagSet = Mutable | Method

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,19 @@ object SymDenotations {
201201
if (myFlags.is(Trait)) NoInitsInterface & bodyFlags // no parents are initialized from a trait
202202
else NoInits & bodyFlags & parentFlags)
203203

204-
private def isCurrent(fs: FlagSet) =
205-
fs <= (
204+
private def isCurrent(fs: FlagSet)(implicit ctx: Context): Boolean =
205+
val immutableFlags =
206206
if (myInfo.isInstanceOf[SymbolLoader]) FromStartFlags
207-
else AfterLoadFlags)
207+
else AfterLoadFlags
208+
val mutableFlagsBeingQueried = fs &~ immutableFlags
209+
210+
mutableFlagsBeingQueried.isEmpty || ( // All flags are immutable wrt completion
211+
mutableFlagsBeingQueried <= ConditionallyImmutableFlags.flags && // All the mutable flags being queried are not mutated during completion under certain conditions
212+
ConditionallyImmutableFlags.flagsAndConditions.forall { case (flag, condition) =>
213+
(flag & mutableFlagsBeingQueried).isEmpty || !condition(this)
214+
}
215+
)
216+
208217

209218
final def relevantFlagsFor(fs: FlagSet)(implicit ctx: Context) =
210219
if (isCurrent(fs)) myFlags else flags

0 commit comments

Comments
 (0)