Skip to content

Commit 8b2f9a5

Browse files
committed
Make FlagSet an opaque type
Make FlagSet an opaque type and all flag ops extension methods
1 parent 6afb659 commit 8b2f9a5

File tree

3 files changed

+111
-86
lines changed

3 files changed

+111
-86
lines changed

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

Lines changed: 82 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -5,121 +5,132 @@ import language.implicitConversions
55

66
object Flags {
77

8-
/** A FlagSet represents a set of flags. Flags are encoded as follows:
9-
* The first two bits indicate whether a flagset applies to terms,
10-
* to types, or to both. Bits 2..63 are available for properties
11-
* and can be doubly used for terms and types.
12-
*/
13-
case class FlagSet(val bits: Long) extends AnyVal {
8+
object opaques {
9+
10+
/** A FlagSet represents a set of flags. Flags are encoded as follows:
11+
* The first two bits indicate whether a flagset applies to terms,
12+
* to types, or to both. Bits 2..63 are available for properties
13+
* and can be doubly used for terms and types.
14+
*/
15+
opaque type FlagSet = Long
16+
def FlagSet(bits: Long): FlagSet = bits.asInstanceOf // !!!
17+
def toBits(fs: FlagSet): Long = fs
18+
}
19+
type FlagSet = opaques.FlagSet
20+
def FlagSet(bits: Long): FlagSet = opaques.FlagSet(bits)
21+
22+
implicit object FlagOps {
23+
24+
def (xs: FlagSet) bits: Long = opaques.toBits(xs)
1425

15-
/** The union of this flag set and the given flag set
26+
/** The union of the given flag sets.
1627
* Combining two FlagSets with `|` will give a FlagSet
1728
* that has the intersection of the applicability to terms/types
1829
* of the two flag sets. It is checked that the intersection is not empty.
1930
*/
20-
def | (that: FlagSet): FlagSet =
21-
if (bits == 0) that
22-
else if (that.bits == 0) this
31+
def (x: FlagSet) | (that: FlagSet): FlagSet =
32+
if (x.bits == 0) that
33+
else if (that.bits == 0) x
2334
else {
24-
val tbits = bits & that.bits & KINDFLAGS
35+
val tbits = x.bits & that.bits & KINDFLAGS
2536
if (tbits == 0)
26-
assert(false, s"illegal flagset combination: $this and $that")
27-
FlagSet(tbits | ((this.bits | that.bits) & ~KINDFLAGS))
37+
assert(false, s"illegal flagset combination: $x and $that")
38+
FlagSet(tbits | ((x.bits | that.bits) & ~KINDFLAGS))
2839
}
2940

30-
/** The intersection of this flag set and the given flag set */
31-
def & (that: FlagSet): FlagSet = FlagSet(bits & that.bits)
41+
/** The intersection of the given flag sets */
42+
def (x: FlagSet) & (that: FlagSet): FlagSet = FlagSet(x.bits & that.bits)
3243

33-
/** The intersection of this flag set with the complement of the given flag set */
34-
def &~ (that: FlagSet): FlagSet = {
35-
val tbits = bits & KINDFLAGS
36-
if ((tbits & that.bits) == 0) this
37-
else FlagSet(tbits | ((this.bits & ~that.bits) & ~KINDFLAGS))
44+
/** The intersection of a flag set with the complement of another flag set */
45+
def (x: FlagSet) &~ (that: FlagSet): FlagSet = {
46+
val tbits = x.bits & KINDFLAGS
47+
if ((tbits & that.bits) == 0) x
48+
else FlagSet(tbits | ((x.bits & ~that.bits) & ~KINDFLAGS))
3849
}
3950

40-
def ^ (that: FlagSet) =
41-
FlagSet((bits | that.bits) & KINDFLAGS | (bits ^ that.bits) & ~KINDFLAGS)
51+
def (x: FlagSet) ^ (that: FlagSet) =
52+
FlagSet((x.bits | that.bits) & KINDFLAGS | (x.bits ^ that.bits) & ~KINDFLAGS)
4253

43-
/** Does this flag set have a non-empty intersection with the given flag set?
54+
/** Does a given flag set have a non-empty intersection with another flag set?
4455
* This means that both the kind flags and the carrier bits have non-empty intersection.
4556
*/
46-
def is(flags: FlagSet): Boolean = {
57+
def (x: FlagSet) is(flags: FlagSet): Boolean = {
4758
assert(flags.numFlags == 1)
48-
val fs = bits & flags.bits
59+
val fs = x.bits & flags.bits
4960
(fs & KINDFLAGS) != 0 && (fs & ~KINDFLAGS) != 0
5061
}
5162

52-
/** Does this flag set have a non-empty intersection with the given flag set,
63+
/** Does a given flag set have a non-empty intersection with another flag set,
5364
* and at the same time contain none of the flags in the `butNot` set?
5465
*/
55-
def is(flags: FlagSet, butNot: FlagSet): Boolean = is(flags) && !isOneOf(butNot)
66+
def (x: FlagSet) is(flags: FlagSet, butNot: FlagSet): Boolean = x.is(flags) && !x.isOneOf(butNot)
5667

57-
def isOneOf(flags: FlagSet): Boolean = {
58-
val fs = bits & flags.bits
68+
def (x: FlagSet) isOneOf(flags: FlagSet): Boolean = {
69+
val fs = x.bits & flags.bits
5970
(fs & KINDFLAGS) != 0 && (fs & ~KINDFLAGS) != 0
6071
}
6172

62-
def isOneOf(flags: FlagSet, butNot: FlagSet): Boolean = isOneOf(flags) && !isOneOf(butNot)
73+
def (x: FlagSet) isOneOf(flags: FlagSet, butNot: FlagSet): Boolean = x.isOneOf(flags) && !x.isOneOf(butNot)
6374

64-
/** Does this flag set have all of the flags in given flag conjunction?
65-
* Pre: The intersection of the typeflags of both sets must be non-empty.
75+
/** Does a given flag set have all of the flags of another flag set?
76+
* Pre: The intersection of the term/type flags of both sets must be non-empty.
6677
*/
67-
def isAllOf(flags: FlagSet): Boolean = {
68-
val fs = bits & flags.bits
78+
def (x: FlagSet) isAllOf(flags: FlagSet): Boolean = {
79+
val fs = x.bits & flags.bits
6980
((fs & KINDFLAGS) != 0 || flags.bits == 0) &&
7081
(fs >>> TYPESHIFT) == (flags.bits >>> TYPESHIFT)
7182
}
7283

73-
/** Does this flag set have all of the flags in given flag conjunction?
84+
/** Does a given flag set have all of the flags in another flag set
7485
* and at the same time contain none of the flags in the `butNot` set?
75-
* Pre: The intersection of the typeflags of both sets must be non-empty.
86+
* Pre: The intersection of the term/type flags of both sets must be non-empty.
7687
*/
77-
def isAllOf(flags: FlagSet, butNot: FlagSet): Boolean = isAllOf(flags) && !isOneOf(butNot)
88+
def (x: FlagSet) isAllOf(flags: FlagSet, butNot: FlagSet): Boolean = x.isAllOf(flags) && !x.isOneOf(butNot)
7889

79-
def isEmpty: Boolean = (bits & ~KINDFLAGS) == 0
90+
def (x: FlagSet) isEmpty: Boolean = (x.bits & ~KINDFLAGS) == 0
8091

81-
/** Is this flag set a subset of that one? */
82-
def <= (that: FlagSet): Boolean = (bits & that.bits) == bits
92+
/** Is a given flag set a subset of another flag set? */
93+
def (x: FlagSet) <= (that: FlagSet): Boolean = (x.bits & that.bits) == x.bits
8394

84-
/** Does this flag set apply to terms? */
85-
def isTermFlags: Boolean = (bits & TERMS) != 0
95+
/** Does the given flag set apply to terms? */
96+
def (x: FlagSet) isTermFlags: Boolean = (x.bits & TERMS) != 0
8697

87-
/** Does this flag set apply to terms? */
88-
def isTypeFlags: Boolean = (bits & TYPES) != 0
98+
/** Does the given flag set apply to terms? */
99+
def (x: FlagSet) isTypeFlags: Boolean = (x.bits & TYPES) != 0
89100

90-
/** This flag set with all flags transposed to be type flags */
91-
def toTypeFlags: FlagSet = if (bits == 0) this else FlagSet(bits & ~KINDFLAGS | TYPES)
101+
/** The given flag set with all flags transposed to be type flags */
102+
def (x: FlagSet) toTypeFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TYPES)
92103

93-
/** This flag set with all flags transposed to be term flags */
94-
def toTermFlags: FlagSet = if (bits == 0) this else FlagSet(bits & ~KINDFLAGS | TERMS)
104+
/** The given flag set with all flags transposed to be term flags */
105+
def (x: FlagSet) toTermFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TERMS)
95106

96-
/** This flag set with all flags transposed to be common flags */
97-
def toCommonFlags: FlagSet = if (bits == 0) this else FlagSet(bits | KINDFLAGS)
107+
/** The given flag set with all flags transposed to be common flags */
108+
def (x: FlagSet) toCommonFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits | KINDFLAGS)
98109

99-
/** The number of non-kind flags in this set */
100-
def numFlags: Int = java.lang.Long.bitCount(bits & ~KINDFLAGS)
110+
/** The number of non-kind flags in the given flag set */
111+
def (x: FlagSet) numFlags: Int = java.lang.Long.bitCount(x.bits & ~KINDFLAGS)
101112

102-
/** The lowest non-kind bit set in this flagset */
103-
def firstBit: Int = java.lang.Long.numberOfTrailingZeros(bits & ~KINDFLAGS)
113+
/** The lowest non-kind bit set in the given flag set */
114+
def (x: FlagSet) firstBit: Int = java.lang.Long.numberOfTrailingZeros(x.bits & ~KINDFLAGS)
104115

105-
/** The list of non-empty names of flags with given index idx that are set in this FlagSet */
106-
private def flagString(idx: Int): List[String] =
107-
if ((bits & (1L << idx)) == 0) Nil
116+
/** The list of non-empty names of flags with given index idx that are set in the given flag set */
117+
private def (x: FlagSet) flagString(idx: Int): List[String] =
118+
if ((x.bits & (1L << idx)) == 0) Nil
108119
else {
109120
def halfString(kind: Int) =
110-
if ((bits & (1L << kind)) != 0) flagName(idx)(kind) else ""
121+
if ((x.bits & (1L << kind)) != 0) flagName(idx)(kind) else ""
111122
val termFS = halfString(TERMindex)
112123
val typeFS = halfString(TYPEindex)
113124
val strs = termFS :: (if (termFS == typeFS) Nil else typeFS :: Nil)
114125
strs filter (_.nonEmpty)
115126
}
116127

117-
/** The list of non-empty names of flags that are set in this FlagSet */
118-
def flagStrings(privateWithin: String): Seq[String] = {
119-
var rawStrings = (2 to MaxFlag).flatMap(flagString)
120-
if (!privateWithin.isEmpty && !this.is(Protected))
128+
/** The list of non-empty names of flags that are set in teh given flag set */
129+
def (x: FlagSet) flagStrings(privateWithin: String): Seq[String] = {
130+
var rawStrings = (2 to MaxFlag).flatMap(x.flagString(_)) // !!!
131+
if (!privateWithin.isEmpty && !x.is(Protected))
121132
rawStrings = rawStrings :+ "private"
122-
val scopeStr = if (this.is(Local)) "this" else privateWithin
133+
val scopeStr = if (x.is(Local)) "this" else privateWithin
123134
if (scopeStr != "")
124135
rawStrings.filter(_ != "<local>").map {
125136
case "private" => s"private[$scopeStr]"
@@ -129,8 +140,8 @@ object Flags {
129140
else rawStrings
130141
}
131142

132-
/** The string representation of this flag set */
133-
def flagsString: String = flagStrings("").mkString(" ")
143+
/** The string representation of the given flag set */
144+
def (x: FlagSet) flagsString: String = x.flagStrings("").mkString(" ")
134145
}
135146

136147
def termFlagSet(x: Long) = FlagSet(TERMS | x)
@@ -148,7 +159,7 @@ object Flags {
148159

149160
private val flagName = Array.fill(64, 2)("")
150161

151-
private def isDefinedAsFlag(idx: Int) = flagName(idx) exists (_.nonEmpty)
162+
private def isDefinedAsFlag(idx: Int) = flagName(idx).exists(_.nonEmpty)
152163

153164
/** The flag set containing all defined flags of either kind whose bits
154165
* lie in the given range
@@ -565,11 +576,11 @@ object Flags {
565576
/** An inline method or inline argument proxy */
566577
final val InlineOrProxy: FlagSet = Inline | InlineProxy
567578

568-
final val ImplicitOrImplied = Implicit | Implied
569-
final val ImplicitOrImpliedOrGiven = Implicit | Implied | Given
570-
final val ImplicitOrGiven = Implicit | Given
579+
final val ImplicitOrImplied: FlagSet = Implicit | Implied
580+
final val ImplicitOrImpliedOrGiven: FlagSet = Implicit | Implied | Given
581+
final val ImplicitOrGiven: FlagSet = Implicit | Given
571582

572-
final val ImpliedOrGiven = Implied | Given
583+
final val ImpliedOrGiven: FlagSet = Implied | Given
573584

574585
final val ImplicitOrImpliedOrGivenTerm = ImplicitOrImpliedOrGiven.toTermFlags
575586

@@ -598,7 +609,7 @@ object Flags {
598609
final val InlineParam: FlagSet = Inline | Param
599610

600611
/** An extension method */
601-
final val ExtensionMethod = Extension | Method
612+
final val ExtensionMethod: FlagSet = Extension | Method
602613

603614
/** An implied method */
604615
final val SyntheticImpliedMethod: FlagSet = Synthetic | Implied | Method

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

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -187,34 +187,46 @@ object SymDenotations {
187187
if (isCurrent(fs)) myFlags else flags
188188

189189
/** Has this denotation one of the flags in `fs` set? */
190-
final def is(fs: FlagSet)(implicit ctx: Context): Boolean =
191-
(if (isCurrent(fs)) myFlags else flags).is(fs)
190+
final def is(fs: FlagSet)(implicit ctx: Context): Boolean = {
191+
val toTest = if (isCurrent(fs)) myFlags else flags // TODO: combine these two lines once 0.17 is released and #6706 is in
192+
toTest.is(fs)
193+
}
192194

193195
/** Has this denotation one of the flags in `fs` set? */
194-
final def isOneOf(fs: FlagSet)(implicit ctx: Context): Boolean =
195-
(if (isCurrent(fs)) myFlags else flags).isOneOf(fs)
196+
final def isOneOf(fs: FlagSet)(implicit ctx: Context): Boolean = {
197+
val toTest = if (isCurrent(fs)) myFlags else flags // TODO: combine these two lines once 0.17 is released and #6706 is in
198+
toTest.isOneOf(fs)
199+
}
196200

197201
/** Has this denotation one of the flags in `fs` set, whereas none of the flags
198202
* in `butNot` are set?
199203
*/
200-
final def is(fs: FlagSet, butNot: FlagSet)(implicit ctx: Context): Boolean =
201-
(if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags).is(fs, butNot)
204+
final def is(fs: FlagSet, butNot: FlagSet)(implicit ctx: Context): Boolean = {
205+
val toTest = if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags // TODO: combine these two lines once 0.17 is released and #6706 is in
206+
toTest.is(fs, butNot)
207+
}
202208

203209
/** Has this denotation one of the flags in `fs` set, whereas none of the flags
204210
* in `butNot` are set?
205211
*/
206-
final def isOneOf(fs: FlagSet, butNot: FlagSet)(implicit ctx: Context): Boolean =
207-
(if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags).isOneOf(fs, butNot)
212+
final def isOneOf(fs: FlagSet, butNot: FlagSet)(implicit ctx: Context): Boolean = {
213+
val toTest = if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags // TODO: combine these two lines once 0.17 is released and #6706 is in
214+
toTest.isOneOf(fs, butNot)
215+
}
208216

209217
/** Has this denotation all of the flags in `fs` set? */
210-
final def isAllOf(fs: FlagSet)(implicit ctx: Context): Boolean =
211-
(if (isCurrent(fs)) myFlags else flags).isAllOf(fs)
218+
final def isAllOf(fs: FlagSet)(implicit ctx: Context): Boolean = {
219+
val toTest = if (isCurrent(fs)) myFlags else flags // TODO: combine these two lines once 0.17 is released and #6706 is in
220+
toTest.isAllOf(fs)
221+
}
212222

213223
/** Has this denotation all of the flags in `fs` set, whereas none of the flags
214224
* in `butNot` are set?
215225
*/
216-
final def isAllOf(fs: FlagSet, butNot: FlagSet)(implicit ctx: Context): Boolean =
217-
(if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags).isAllOf(fs, butNot)
226+
final def isAllOf(fs: FlagSet, butNot: FlagSet)(implicit ctx: Context): Boolean = {
227+
val toTest = if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags // TODO: combine these two lines once 0.17 is released and #6706 is in
228+
toTest.isAllOf(fs, butNot)
229+
}
218230

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

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,11 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
7070
override protected def recursionLimitExceeded(): Unit = {}
7171

7272
protected def PrintableFlags(isType: Boolean): FlagSet = {
73-
if (isType) TypeSourceModifierFlags | Module | Local
74-
else TermSourceModifierFlags | Module | Local
75-
}.toCommonFlags
73+
val fs =
74+
if (isType) TypeSourceModifierFlags | Module | Local // DOTTY problem: cannot merge these two statements
75+
else TermSourceModifierFlags | Module | Local
76+
fs.toCommonFlags
77+
}
7678

7779
override def nameString(name: Name): String =
7880
if (ctx.settings.YdebugNames.value) name.debugString else NameTransformer.decodeIllegalChars(name.toString)

0 commit comments

Comments
 (0)