Skip to content

Commit d7a049b

Browse files
Lazy strategy for evaluating flags on denotations
Make sure that we complete denotations only in case we absolutely must to when evaluating predicates on flags.
1 parent 44ed627 commit d7a049b

File tree

2 files changed

+32
-12
lines changed

2 files changed

+32
-12
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ object Flags {
5454
def (x: FlagSet) ^ (y: FlagSet) =
5555
FlagSet((x.bits | y.bits) & KINDFLAGS | (x.bits ^ y.bits) & ~KINDFLAGS)
5656

57+
def (x: FlagSet) partitionByIntersection(y: FlagSet): (FlagSet, FlagSet) =
58+
val intersection = x & y
59+
val complement = x &~ y
60+
(intersection, complement)
61+
62+
5763
/** Does the given flag set contain the given flag?
5864
* This means that both the kind flags and the carrier bits have non-empty intersection.
5965
*/

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

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -204,34 +204,48 @@ object SymDenotations {
204204
if (isCurrent(fs)) myFlags else flags
205205

206206
/** Has this denotation one of given flag set? */
207-
final def is(flag: Flag)(implicit ctx: Context): Boolean =
208-
(if (isCurrent(flag)) myFlags else flags).is(flag)
209-
210-
/** Has this denotation one of the flags in `fs` set? */
211-
final def isOneOf(fs: FlagSet)(implicit ctx: Context): Boolean =
212-
(if (isCurrent(fs)) myFlags else flags).isOneOf(fs)
207+
final inline def is(flag: Flag)(implicit ctx: Context): Boolean =
208+
is(flag, EmptyFlags)
213209

214210
/** Has this denotation the given flag set, whereas none of the flags
215211
* in `butNot` are set?
216212
*/
217-
final def is(flag: Flag, butNot: FlagSet)(implicit ctx: Context): Boolean =
218-
is(flag) && !isOneOf(butNot)
213+
final inline def is(flag: Flag, butNot: FlagSet)(implicit ctx: Context): Boolean =
214+
isAllOf(flag, butNot)
215+
216+
/** Has this denotation one of the flags in `fs` set? */
217+
final inline def isOneOf(fs: FlagSet)(implicit ctx: Context): Boolean =
218+
isOneOf(fs, EmptyFlags)
219219

220220
/** Has this denotation one of the flags in `fs` set, whereas none of the flags
221221
* in `butNot` are set?
222222
*/
223223
final def isOneOf(fs: FlagSet, butNot: FlagSet)(implicit ctx: Context): Boolean =
224-
isOneOf(fs) && !isOneOf(butNot)
224+
val immutable = immutableFlags
225+
val (fsImmut, fsMut) = fs.partitionByIntersection(immutable)
226+
val (butNotImmut, butNotMut) = butNot.partitionByIntersection(immutable)
227+
228+
(butNotImmut & myFlags).isEmpty &&
229+
(!(fsImmut & myFlags).isEmpty || (!fsMut.isEmpty && !(fsMut & flags).isEmpty)) &&
230+
(butNotMut.isEmpty || (butNotMut & flags).isEmpty)
225231

226232
/** Has this denotation all of the flags in `fs` set? */
227-
final def isAllOf(fs: FlagSet)(implicit ctx: Context): Boolean =
228-
(if (isCurrent(fs)) myFlags else flags).isAllOf(fs)
233+
final inline def isAllOf(fs: FlagSet)(implicit ctx: Context): Boolean =
234+
isAllOf(fs, EmptyFlags)
229235

230236
/** Has this denotation all of the flags in `fs` set, whereas none of the flags
231237
* in `butNot` are set?
232238
*/
233239
final def isAllOf(fs: FlagSet, butNot: FlagSet)(implicit ctx: Context): Boolean =
234-
isAllOf(fs) && !isOneOf(butNot)
240+
val immutable = immutableFlags
241+
val (fsImmut, fsMut) = fs.partitionByIntersection(immutable)
242+
val (butNotImmut, butNotMut) = butNot.partitionByIntersection(immutable)
243+
244+
fsImmut <= myFlags &&
245+
(butNotImmut & myFlags).isEmpty &&
246+
(fsMut.isEmpty || fsMut <= flags) &&
247+
(butNotMut.isEmpty || (butNotMut & flags).isEmpty)
248+
235249

236250
/** The type info, or, if symbol is not yet completed, the completer */
237251
final def infoOrCompleter: Type = myInfo

0 commit comments

Comments
 (0)