diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index c758c3272af5..c3841b8057d7 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -3,7 +3,7 @@ package dotty.tools.backend.jvm import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.ast.Trees import dotty.tools.dotc -import dotty.tools.dotc.core.Flags.{termFlagSet, termFlagConjunction} +import dotty.tools.dotc.core.Flags.{termFlagSet} import dotty.tools.dotc.transform.{Erasure, GenericSignatures} import dotty.tools.dotc.transform.SymUtils._ import java.io.{File => _} @@ -256,12 +256,12 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma case t: TypeApply if (t.fun.symbol == Predef_classOf) => av.visit(name, t.args.head.tpe.classSymbol.denot.info.toTypeKind(bcodeStore)(innerClasesStore).toASMType) case t: tpd.RefTree => - if (t.symbol.denot.owner.is(Flags.JavaEnum)) { + if (t.symbol.denot.owner.isAllOf(Flags.JavaEnumTrait)) { val edesc = innerClasesStore.typeDescriptor(t.tpe.asInstanceOf[bcodeStore.int.Type]) // the class descriptor of the enumeration class. val evalue = t.symbol.name.mangledString // value the actual enumeration value. av.visitEnum(name, edesc, evalue) } else { - // println(i"not an enum: ${t.symbol} / ${t.symbol.denot.owner} / ${t.symbol.denot.owner.isTerm} / ${t.symbol.denot.owner.flags}") + // println(i"not an enum: ${t.symbol} / ${t.symbol.denot.owner} / ${t.symbol.denot.owner.isTerm} / ${t.symbol.denot.owner.flagsString}") assert(toDenot(t.symbol).name.is(DefaultGetterName), s"${toDenot(t.symbol).name.debugString}") // this should be default getter. do not emit. } @@ -477,7 +477,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma // unrelated change. ctx.base.settings.YnoGenericSig.value || sym.is(Flags.Artifact) - || sym.is(Flags.LiftedMethod) + || sym.isAllOf(Flags.LiftedMethod) || sym.is(Flags.Bridge) ) @@ -658,50 +658,49 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def isConstructor: Boolean = toDenot(sym).isConstructor def isExpanded: Boolean = sym.name.is(ExpandedName) def isAnonymousFunction: Boolean = toDenot(sym).isAnonymousFunction - def isMethod: Boolean = sym is Flags.Method - def isPublic: Boolean = sym.flags.is(Flags.EmptyFlags, Flags.Private | Flags.Protected) - def isSynthetic: Boolean = sym is Flags.Synthetic - def isPackageClass: Boolean = sym is Flags.PackageClass - def isModuleClass: Boolean = sym is Flags.ModuleClass - def isModule: Boolean = sym is Flags.Module + def isMethod: Boolean = sym.is(Flags.Method) + def isPublic: Boolean = !sym.flags.isOneOf(Flags.Private | Flags.Protected) + def isSynthetic: Boolean = sym.is(Flags.Synthetic) + def isPackageClass: Boolean = sym.is(Flags.PackageClass) + def isModuleClass: Boolean = sym.is(Flags.ModuleClass) + def isModule: Boolean = sym.is(Flags.Module) def isStrictFP: Boolean = false // todo: implement - def isLabel: Boolean = sym is Flags.Label - def hasPackageFlag: Boolean = sym is Flags.Package - def isInterface: Boolean = (sym is Flags.PureInterface) || (sym is Flags.Trait) + def isLabel: Boolean = sym.is(Flags.Label) + def hasPackageFlag: Boolean = sym.is(Flags.Package) + def isInterface: Boolean = (sym.is(Flags.PureInterface)) || (sym.is(Flags.Trait)) def isGetter: Boolean = toDenot(sym).isGetter def isSetter: Boolean = toDenot(sym).isSetter def isGetClass: Boolean = sym eq defn.Any_getClass - def isJavaDefined: Boolean = sym is Flags.JavaDefined - def isJavaDefaultMethod: Boolean = !((sym is Flags.Deferred) || toDenot(sym).isClassConstructor) - def isDeferred: Boolean = sym is Flags.Deferred - def isPrivate: Boolean = sym is Flags.Private + def isJavaDefined: Boolean = sym.is(Flags.JavaDefined) + def isJavaDefaultMethod: Boolean = !((sym.is(Flags.Deferred)) || toDenot(sym).isClassConstructor) + def isDeferred: Boolean = sym.is(Flags.Deferred) + def isPrivate: Boolean = sym.is(Flags.Private) def getsJavaFinalFlag: Boolean = - isFinal && !toDenot(sym).isClassConstructor && !(sym is Flags.Mutable) && !(sym.enclosingClass is Flags.Trait) + isFinal && !toDenot(sym).isClassConstructor && !(sym.is(Flags.Mutable)) && !(sym.enclosingClass.is(Flags.Trait)) def getsJavaPrivateFlag: Boolean = isPrivate //|| (sym.isPrimaryConstructor && sym.owner.isTopLevelModuleClass) - def isFinal: Boolean = sym is Flags.Final + def isFinal: Boolean = sym.is(Flags.Final) def isStaticMember: Boolean = (sym ne NoSymbol) && - ((sym is Flags.JavaStatic) || toDenot(sym).hasAnnotation(ctx.definitions.ScalaStaticAnnot)) + (sym.is(Flags.JavaStatic) || toDenot(sym).hasAnnotation(ctx.definitions.ScalaStaticAnnot)) // guard against no sumbol cause this code is executed to select which call type(static\dynamic) to use to call array.clone def isBottomClass: Boolean = (sym ne defn.NullClass) && (sym ne defn.NothingClass) - def isBridge: Boolean = sym is Flags.Bridge - def isArtifact: Boolean = sym is Flags.Artifact - def hasEnumFlag: Boolean = sym is Flags.JavaEnum + def isBridge: Boolean = sym.is(Flags.Bridge) + def isArtifact: Boolean = sym.is(Flags.Artifact) + def hasEnumFlag: Boolean = sym.isAllOf(Flags.JavaEnumTrait) def hasAccessBoundary: Boolean = sym.accessBoundary(defn.RootClass) ne defn.RootClass - def isVarargsMethod: Boolean = sym is Flags.JavaVarargs + def isVarargsMethod: Boolean = sym.is(Flags.JavaVarargs) def isDeprecated: Boolean = false - def isMutable: Boolean = sym is Flags.Mutable - def hasAbstractFlag: Boolean = - (sym is Flags.Abstract) || (sym is Flags.JavaInterface) || (sym is Flags.Trait) - def hasModuleFlag: Boolean = sym is Flags.Module - def isSynchronized: Boolean = sym is Flags.Synchronized + def isMutable: Boolean = sym.is(Flags.Mutable) + def hasAbstractFlag: Boolean = sym.isOneOf(Flags.AbstractOrTrait) + def hasModuleFlag: Boolean = sym.is(Flags.Module) + def isSynchronized: Boolean = sym.is(Flags.Synchronized) def isNonBottomSubClass(other: Symbol): Boolean = sym.derivesFrom(other) def hasAnnotation(ann: Symbol): Boolean = toDenot(sym).hasAnnotation(ann) def shouldEmitForwarders: Boolean = - (sym is Flags.Module) && sym.isStatic + (sym.is(Flags.Module)) && sym.isStatic def isJavaEntryPoint: Boolean = CollectEntryPoints.isJavaEntryPoint(sym) def isEnum = sym.is(Flags.Enum) @@ -713,7 +712,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma * for such objects will get a MODULE$ flag and a corresponding static initializer. */ def isStaticModuleClass: Boolean = - (sym is Flags.Module) && { + (sym.is(Flags.Module)) && { // scalac uses atPickling here // this would not work if modules are created after pickling // for example by specialization @@ -736,7 +735,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def superClass: Symbol = { val t = toDenot(sym).asClass.superClass if (t.exists) t - else if (sym is Flags.ModuleClass) { + else if (sym.is(Flags.ModuleClass)) { // workaround #371 println(s"Warning: mocking up superclass for $sym") @@ -749,7 +748,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def linkedClass: Symbol = toDenot(sym)(ctx).linkedClass(ctx) //exitingPickler(sym.linkedClassOfClass) def companionClass: Symbol = toDenot(sym).companionClass def companionModule: Symbol = toDenot(sym).companionModule - def companionSymbol: Symbol = if (sym is Flags.Module) companionClass else companionModule + def companionSymbol: Symbol = if (sym.is(Flags.Module)) companionClass else companionModule def moduleClass: Symbol = toDenot(sym).moduleClass def enclosingClassSym: Symbol = { if (this.isClass) { @@ -859,7 +858,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma implicit def typeHelper(tp: Type): TypeHelper = new TypeHelper { def member(string: Name): Symbol = tp.member(string.toTermName).symbol - def isFinalType: Boolean = tp.typeSymbol is Flags.Final //in scalac checks for type parameters. Why? Aren't they gone by backend? + def isFinalType: Boolean = tp.typeSymbol.is(Flags.Final) //in scalac checks for type parameters. Why? Aren't they gone by backend? def underlying: Type = tp match { case t: TypeProxy => t.underlying @@ -881,7 +880,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def =:=(other: Type): Boolean = tp =:= other def membersBasedOnFlags(excludedFlags: Flags, requiredFlags: Flags): List[Symbol] = - tp.membersBasedOnFlags(termFlagConjunction(requiredFlags), termFlagSet(excludedFlags)).map(_.symbol).toList + tp.membersBasedOnFlags(termFlagSet(requiredFlags), termFlagSet(excludedFlags)).map(_.symbol).toList def resultType: Type = tp.resultType diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index 7dccc47d304a..ace82a9bbc80 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -447,7 +447,7 @@ class JSCodeGen()(implicit ctx: Context) { "genClassFields called with a ClassDef other than the current one") // Term members that are neither methods nor modules are fields - classSym.info.decls.filter(f => !f.is(Method | Module) && f.isTerm).map({ f => + classSym.info.decls.filter(f => !f.isOneOf(Method | Module) && f.isTerm).map({ f => implicit val pos = f.span val name = @@ -540,7 +540,7 @@ class JSCodeGen()(implicit ctx: Context) { implicit pos: SourcePosition): Option[js.Tree] = { val ctors = if (sym.is(Abstract)) Nil - else sym.info.member(nme.CONSTRUCTOR).alternatives.map(_.symbol).filter(m => !m.is(Private | Protected)) + else sym.info.member(nme.CONSTRUCTOR).alternatives.map(_.symbol).filter(m => !m.isOneOf(Private | Protected)) if (ctors.isEmpty) { None diff --git a/compiler/src/dotty/tools/backend/sjs/JUnitBootstrappers.scala b/compiler/src/dotty/tools/backend/sjs/JUnitBootstrappers.scala index 7c6ced8b19d2..d1a3139a3067 100644 --- a/compiler/src/dotty/tools/backend/sjs/JUnitBootstrappers.scala +++ b/compiler/src/dotty/tools/backend/sjs/JUnitBootstrappers.scala @@ -128,7 +128,7 @@ class JUnitBootstrappers extends MiniPhase { def isTestClass(sym: Symbol): Boolean = { sym.isClass && - !sym.is(ModuleClass | Abstract | Trait) && + !sym.isOneOf(ModuleClass | Abstract | Trait) && hasTests(sym.asClass) } diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 3b710ec34f5f..b507c2ed14fb 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -90,10 +90,10 @@ object desugar { * in apply/unapply methods. */ override def ensureCompletions(implicit ctx: Context): Unit = - if (!(ctx.owner is Package)) + if (!ctx.owner.is(Package)) if (ctx.owner.isClass) { ctx.owner.ensureCompleted() - if (ctx.owner is ModuleClass) + if (ctx.owner.is(ModuleClass)) ctx.owner.linkedClass.ensureCompleted() } else ensureCompletions(ctx.outer) @@ -159,7 +159,7 @@ object desugar { val vdef @ ValDef(name, tpt, rhs) = transformQuotedPatternName(vdef0) val mods = vdef.mods val setterNeeded = - (mods is Mutable) && ctx.owner.isClass && (!(mods is PrivateLocal) || (ctx.owner is Trait)) + mods.is(Mutable) && ctx.owner.isClass && (!mods.isAllOf(PrivateLocal) || ctx.owner.is(Trait)) if (setterNeeded) { // TODO: copy of vdef as getter needed? // val getter = ValDef(mods, name, tpt, rhs) withPos vdef.pos? @@ -174,7 +174,7 @@ object desugar { vparamss = (setterParam :: Nil) :: Nil, tpt = TypeTree(defn.UnitType), rhs = setterRhs - ).withMods((mods | Accessor) &~ (CaseAccessor | ImplicitOrGiven | Lazy)) + ).withMods((mods | Accessor) &~ (CaseAccessor | GivenOrImplicit | Lazy)) Thicket(vdef, setter) } else vdef @@ -182,7 +182,7 @@ object desugar { def makeImplicitParameters(tpts: List[Tree], implicitFlag: FlagSet, forPrimaryConstructor: Boolean = false)(implicit ctx: Context): List[ValDef] = for (tpt <- tpts) yield { - val paramFlags: FlagSet = if (forPrimaryConstructor) PrivateLocalParamAccessor else Param + val paramFlags: FlagSet = if (forPrimaryConstructor) LocalParamAccessor else Param val epname = EvidenceParamName.fresh() ValDef(epname, tpt, EmptyTree).withFlags(paramFlags | implicitFlag) } @@ -323,7 +323,7 @@ object desugar { meth case evidenceParams => val vparamss1 = meth.vparamss.reverse match { - case (vparams @ (vparam :: _)) :: rvparamss if vparam.mods is ImplicitOrGiven => + case (vparams @ (vparam :: _)) :: rvparamss if vparam.mods.isOneOf(GivenOrImplicit) => ((evidenceParams ++ vparams) :: rvparamss).reverse case _ => meth.vparamss :+ evidenceParams @@ -334,7 +334,7 @@ object desugar { /** The implicit evidence parameters of `meth`, as generated by `desugar.defDef` */ private def evidenceParams(meth: DefDef)(implicit ctx: Context): List[ValDef] = meth.vparamss.reverse match { - case (vparams @ (vparam :: _)) :: _ if vparam.mods is ImplicitOrGiven => + case (vparams @ (vparam :: _)) :: _ if vparam.mods.isOneOf(GivenOrImplicit) => vparams.dropWhile(!_.name.is(EvidenceParamName)) case _ => Nil @@ -345,7 +345,7 @@ object desugar { private def toDefParam(tparam: TypeDef): TypeDef = tparam.withMods(tparam.rawMods & EmptyFlags | Param) private def toDefParam(vparam: ValDef): ValDef = - vparam.withMods(vparam.rawMods & (ImplicitOrGiven | Erased) | Param) + vparam.withMods(vparam.rawMods & (GivenOrImplicit | Erased) | Param) /** The expansion of a class definition. See inline comments for what is involved */ def classDef(cdef: TypeDef)(implicit ctx: Context): Tree = { @@ -413,7 +413,7 @@ object desugar { if (isCaseClass && originalTparams.isEmpty) ctx.error(CaseClassMissingParamList(cdef), namePos) ListOfNil - } else if (isCaseClass && originalVparamss.head.exists(_.mods.is(ImplicitOrGiven))) { + } else if (isCaseClass && originalVparamss.head.exists(_.mods.isOneOf(GivenOrImplicit))) { ctx.error("Case classes should have a non-implicit parameter list", namePos) ListOfNil } @@ -444,7 +444,7 @@ object desugar { if (enumCases.isEmpty) ctx.error("Enumerations must constain at least one case", namePos) val enumCompanionRef = new TermRefTree() - val enumImport = Import(importImplied = false, enumCompanionRef, enumCases.flatMap(caseIds)) + val enumImport = Import(importDelegate = false, enumCompanionRef, enumCases.flatMap(caseIds)) (enumImport :: enumStats, enumCases, enumCompanionRef) } else (stats, Nil, EmptyTree) @@ -508,7 +508,7 @@ object desugar { // new C[Ts](paramss) lazy val creatorExpr = { val vparamss = constrVparamss match { - case (vparam :: _) :: _ if vparam.mods.is(ImplicitOrGiven) => // add a leading () to match class parameters + case (vparam :: _) :: _ if vparam.mods.isOneOf(GivenOrImplicit) => // add a leading () to match class parameters Nil :: constrVparamss case _ => constrVparamss @@ -658,7 +658,7 @@ object desugar { def widenedCreatorExpr = (creatorExpr /: widenDefs)((rhs, meth) => Apply(Ident(meth.name), rhs :: Nil)) val applyMeths = - if (mods is Abstract) Nil + if (mods.is(Abstract)) Nil else { val copiedFlagsMask = DefaultParameterized | (copiedAccessFlags & Private) val appMods = { @@ -703,9 +703,9 @@ object desugar { // synthetic implicit C[Ts](p11: T11, ..., p1N: T1N) ... (pM1: TM1, ..., pMN: TMN): C[Ts] = // new C[Ts](p11, ..., p1N) ... (pM1, ..., pMN) = val implicitWrappers = - if (!mods.is(ImplicitOrImplied)) + if (!mods.isOneOf(DelegateOrImplicit)) Nil - else if (ctx.owner is Package) { + else if (ctx.owner.is(Package)) { ctx.error(TopLevelImplicitClass(cdef), cdef.sourcePos) Nil } @@ -717,7 +717,7 @@ object desugar { ctx.error(ImplicitCaseClass(cdef), cdef.sourcePos) Nil } - else if (arity != 1 && !mods.is(Implied)) { + else if (arity != 1 && !mods.is(Delegate)) { ctx.error(ImplicitClassPrimaryConstructorArity(), cdef.sourcePos) Nil } @@ -731,7 +731,7 @@ object desugar { // implicit wrapper is typechecked in same scope as constructor, so // we can reuse the constructor parameters; no derived params are needed. DefDef(className.toTermName, constrTparams, defParamss, classTypeRef, creatorExpr) - .withMods(companionMods | mods.flags.toTermFlags & ImplicitOrImplied | Synthetic | Final) + .withMods(companionMods | mods.flags.toTermFlags & DelegateOrImplicit | Synthetic | Final) .withSpan(cdef.span) :: Nil } @@ -792,7 +792,7 @@ object desugar { if (mods.is(Final) && !mods.is(Synthetic)) ctx.warning(em"${hl("final")} modifier is redundant for objects", flagSourcePos(Final)) - if (mods is Package) + if (mods.is(Package)) PackageDef(Ident(moduleName), cpy.ModuleDef(mdef)(nme.PACKAGE, impl).withMods(mods &~ Package) :: Nil) else if (isEnumCase) { typeParamIsReferenced(enumClass.typeParams, Nil, Nil, impl.parents) @@ -982,7 +982,7 @@ object desugar { val restDefs = for (((named, tpt), n) <- vars.zipWithIndex if named.name != nme.WILDCARD) yield - if (mods is Lazy) derivedDefDef(original, named, tpt, selector(n), mods &~ Lazy) + if (mods.is(Lazy)) derivedDefDef(original, named, tpt, selector(n), mods &~ Lazy) else derivedValDef(original, named, tpt, selector(n), mods) flatTree(firstDef :: restDefs) } @@ -1016,9 +1016,9 @@ object desugar { case tree: MemberDef => var tested: MemberDef = tree def fail(msg: String) = ctx.error(msg, tree.sourcePos) - def checkApplicable(flag: FlagSet, test: MemberDefTest): Unit = + def checkApplicable(flag: Flag, test: MemberDefTest): Unit = if (tested.mods.is(flag) && !test.applyOrElse(tree, (md: MemberDef) => false)) { - fail(i"modifier `$flag` is not allowed for this definition") + fail(i"modifier `${flag.flagsString}` is not allowed for this definition") tested = tested.withMods(tested.mods.withoutFlags(flag)) } checkApplicable(Opaque, legalOpaque) @@ -1109,8 +1109,8 @@ object desugar { def needsObject(stat: Tree) = stat match { case _: ValDef | _: PatDef | _: DefDef | _: Export => true case stat: ModuleDef => - stat.mods.is(ImplicitOrImplied) || opaqueNames.contains(stat.name.stripModuleClassSuffix.toTypeName) - case stat: TypeDef => !stat.isClassDef || stat.mods.is(ImplicitOrImplied) + stat.mods.isOneOf(DelegateOrImplicit) || opaqueNames.contains(stat.name.stripModuleClassSuffix.toTypeName) + case stat: TypeDef => !stat.isClassDef || stat.mods.isOneOf(DelegateOrImplicit) case _ => false } val (nestedStats, topStats) = pdef.stats.partition(needsObject) diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index b11ac626f767..3d8495a5ea86 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -296,7 +296,7 @@ trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped] */ def lacksDefinition(mdef: MemberDef)(implicit ctx: Context): Boolean = mdef match { case mdef: ValOrDefDef => - mdef.unforcedRhs == EmptyTree && !mdef.name.isConstructorName && !mdef.mods.is(TermParamOrAccessor) + mdef.unforcedRhs == EmptyTree && !mdef.name.isConstructorName && !mdef.mods.isOneOf(TermParamOrAccessor) case mdef: TypeDef => def isBounds(rhs: Tree): Boolean = rhs match { case _: TypeBoundsTree => true @@ -534,7 +534,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => */ def isVariableOrGetter(tree: Tree)(implicit ctx: Context): Boolean = { def sym = tree.symbol - def isVar = sym is Mutable + def isVar = sym.is(Mutable) def isGetter = mayBeVarGetter(sym) && sym.owner.info.member(sym.name.asTermName.setterName).exists @@ -661,7 +661,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => private def isSimpleThrowable(tp: Type)(implicit ctx: Context): Boolean = tp match { case tp @ TypeRef(pre, _) => (pre == NoPrefix || pre.widen.typeSymbol.isStatic) && - (tp.symbol derivesFrom defn.ThrowableClass) && !(tp.symbol is Trait) + (tp.symbol derivesFrom defn.ThrowableClass) && !tp.symbol.is(Trait) case _ => false } @@ -719,7 +719,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => else Nil case vdef: ValDef => val sym = vdef.symbol - assert(sym is Module) + assert(sym.is(Module)) if (cls == sym.companionClass || cls == sym.moduleClass) vdef :: Nil else Nil case tree => @@ -872,7 +872,7 @@ object TreeInfo { /** The expression has no side effects */ val Pure: PurityLevel = new PurityLevel(3) - /** Running the expression a second time has no side effects. Implied by `Pure`. */ + /** Running the expression a second time has no side effects. Delegate by `Pure`. */ val Idempotent: PurityLevel = new PurityLevel(1) val Impure: PurityLevel = new PurityLevel(0) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index ecbd63bc35f4..73e9707f230d 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -410,7 +410,7 @@ object Trees { // Denotation of a This tree is always the underlying class; needs correction for modules. override def denot(implicit ctx: Context): Denotation = { typeOpt match { - case tpe @ TermRef(pre, _) if tpe.symbol is Module => + case tpe @ TermRef(pre, _) if tpe.symbol.is(Module) => tpe.symbol.moduleClass.denot.asSeenFrom(pre) case _ => super.denot @@ -750,7 +750,7 @@ object Trees { def unforced: LazyTree = preRhs protected def force(x: AnyRef): Unit = preRhs = x - override def disableOverlapChecks = rawMods.is(Flags.Implied) + override def disableOverlapChecks = rawMods.is(Delegate) // disable order checks for implicit aliases since their given clause follows // their for clause, but the two appear swapped in the DefDef. } @@ -801,7 +801,7 @@ object Trees { * where a selector is either an untyped `Ident`, `name` or * an untyped thicket consisting of `name` and `rename`. */ - case class Import[-T >: Untyped] private[ast] (importImplied: Boolean, expr: Tree[T], selectors: List[Tree[Untyped]])(implicit @constructorOnly src: SourceFile) + case class Import[-T >: Untyped] private[ast] (importDelegate: Boolean, expr: Tree[T], selectors: List[Tree[Untyped]])(implicit @constructorOnly src: SourceFile) extends DenotingTree[T] { type ThisTree[-T >: Untyped] = Import[T] } @@ -1200,9 +1200,9 @@ object Trees { case tree: Template if (constr eq tree.constr) && (parents eq tree.parents) && (derived eq tree.derived) && (self eq tree.self) && (body eq tree.unforcedBody) => tree case tree => finalize(tree, untpd.Template(constr, parents, derived, self, body)(sourceFile(tree))) } - def Import(tree: Tree)(importImplied: Boolean, expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = tree match { - case tree: Import if (importImplied == tree.importImplied) && (expr eq tree.expr) && (selectors eq tree.selectors) => tree - case _ => finalize(tree, untpd.Import(importImplied, expr, selectors)(sourceFile(tree))) + def Import(tree: Tree)(importDelegate: Boolean, expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = tree match { + case tree: Import if (importDelegate == tree.importDelegate) && (expr eq tree.expr) && (selectors eq tree.selectors) => tree + case _ => finalize(tree, untpd.Import(importDelegate, expr, selectors)(sourceFile(tree))) } def PackageDef(tree: Tree)(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef = tree match { case tree: PackageDef if (pid eq tree.pid) && (stats eq tree.stats) => tree @@ -1343,8 +1343,8 @@ object Trees { cpy.TypeDef(tree)(name, transform(rhs)) case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty => cpy.Template(tree)(transformSub(constr), transform(tree.parents), Nil, transformSub(self), transformStats(tree.body)) - case Import(importImplied, expr, selectors) => - cpy.Import(tree)(importImplied, transform(expr), selectors) + case Import(importDelegate, expr, selectors) => + cpy.Import(tree)(importDelegate, transform(expr), selectors) case PackageDef(pid, stats) => cpy.PackageDef(tree)(transformSub(pid), transformStats(stats)(localCtx)) case Annotated(arg, annot) => diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 7b70bf2591a0..277f1dda299d 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -268,7 +268,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def ClassDef(cls: ClassSymbol, constr: DefDef, body: List[Tree], superArgs: List[Tree] = Nil)(implicit ctx: Context): TypeDef = { val firstParent :: otherParents = cls.info.parents val superRef = - if (cls is Trait) TypeTree(firstParent) + if (cls.is(Trait)) TypeTree(firstParent) else { def isApplicable(ctpe: Type): Boolean = ctpe match { case ctpe: PolyType => @@ -289,7 +289,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { if (cls.classInfo.selfInfo ne NoType) ValDef(ctx.newSelfSym(cls)) else EmptyValDef def isOwnTypeParam(stat: Tree) = - (stat.symbol is TypeParam) && stat.symbol.owner == cls + stat.symbol.is(TypeParam) && stat.symbol.owner == cls val bodyTypeParams = body filter isOwnTypeParam map (_.symbol) val newTypeParams = for (tparam <- cls.typeParams if !(bodyTypeParams contains tparam)) @@ -333,8 +333,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { Block(cdef :: Nil, New(cls.typeRef, Nil)) } - def Import(importImplied: Boolean, expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = - ta.assignType(untpd.Import(importImplied, expr, selectors), ctx.newImportSymbol(ctx.owner, expr)) + def Import(importDelegate: Boolean, expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = + ta.assignType(untpd.Import(importDelegate, expr, selectors), ctx.newImportSymbol(ctx.owner, expr)) def PackageDef(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef = ta.assignType(untpd.PackageDef(pid, stats), pid) @@ -964,7 +964,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { */ def becomes(rhs: Tree)(implicit ctx: Context): Tree = { val sym = tree.symbol - if (sym is Method) { + if (sym.is(Method)) { val setter = sym.setter.orElse { assert(sym.name.isSetterName && sym.info.firstParamTypes.nonEmpty) sym @@ -1002,7 +1002,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { * Returns true if the symbol is a val or def generated by eta-expansion/inline */ override protected def skipLocal(sym: Symbol): Boolean = - sym.is(InlineProxy) || sym.is(Synthetic) + sym.isOneOf(InlineProxy | Synthetic) } mapToUnderlying.transform(tree) } diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 9c1a798b3d4f..580c82998db9 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -167,7 +167,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case class Inline()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Inline) - case class Implied()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Implied) + case class Delegate()(implicit @constructorOnly src: SourceFile) extends Mod(Flags.Delegate) } /** Modifiers and annotations for definitions @@ -183,9 +183,11 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { annotations: List[Tree] = Nil, mods: List[Mod] = Nil) { - def is(fs: FlagSet): Boolean = flags is fs - def is(fc: FlagConjunction): Boolean = flags is fc - def is(fc: FlagSet, butNot: FlagSet): Boolean = flags.is(fc, butNot = butNot) + def is(flag: Flag): Boolean = flags.is(flag) + def is(flag: Flag, butNot: FlagSet): Boolean = flags.is(flag, butNot = butNot) + def isOneOf(fs: FlagSet): Boolean = flags.isOneOf(fs) + def isOneOf(fs: FlagSet, butNot: FlagSet): Boolean = flags.isOneOf(fs, butNot = butNot) + def isAllOf(fc: FlagSet): Boolean = flags.isAllOf(fc) def | (fs: FlagSet): Modifiers = withFlags(flags | fs) def & (fs: FlagSet): Modifiers = withFlags(flags & fs) @@ -199,8 +201,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { else copy(flags = flags) def withoutFlags(flags: FlagSet): Modifiers = - if (this.is(flags)) - Modifiers(this.flags &~ flags, this.privateWithin, this.annotations, this.mods.filterNot(_.flags.is(flags))) + if (this.isOneOf(flags)) + Modifiers(this.flags &~ flags, this.privateWithin, this.annotations, this.mods.filterNot(_.flags.isOneOf(flags))) else this def withAddedMod(mod: Mod): Modifiers = @@ -215,7 +217,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { else { if (ms.nonEmpty) for (m <- ms) - assert(flags.is(m.flags) || + assert(flags.isAllOf(m.flags) || m.isInstanceOf[Mod.Private] && !privateWithin.isEmpty, s"unaccounted modifier: $m in $this when adding $ms") copy(mods = ms) @@ -343,7 +345,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def Template(constr: DefDef, parents: List[Tree], derived: List[Tree], self: ValDef, body: LazyTreeList)(implicit src: SourceFile): Template = if (derived.isEmpty) new Template(constr, parents, self, body) else new DerivingTemplate(constr, parents ++ derived, self, body, derived.length) - def Import(importImplied: Boolean, expr: Tree, selectors: List[Tree])(implicit src: SourceFile): Import = new Import(importImplied, expr, selectors) + def Import(importDelegate: Boolean, expr: Tree, selectors: List[Tree])(implicit src: SourceFile): Import = new Import(importDelegate, expr, selectors) def PackageDef(pid: RefTree, stats: List[Tree])(implicit src: SourceFile): PackageDef = new PackageDef(pid, stats) def Annotated(arg: Tree, annot: Tree)(implicit src: SourceFile): Annotated = new Annotated(arg, annot) diff --git a/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala b/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala index cbcf3c703f1d..2005a2add3b2 100644 --- a/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala +++ b/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala @@ -39,7 +39,7 @@ class JavaPlatform extends Platform { /** Is the SAMType `cls` also a SAM under the rules of the JVM? */ def isSam(cls: ClassSymbol)(implicit ctx: Context): Boolean = - cls.is(NoInitsTrait) && + cls.isAllOf(NoInitsTrait) && cls.superClass == defn.ObjectClass && cls.directlyInheritedTraits.forall(_.is(NoInits)) && !ExplicitOuter.needsOuterIfReferenced(cls) && diff --git a/compiler/src/dotty/tools/dotc/core/CheckRealizable.scala b/compiler/src/dotty/tools/dotc/core/CheckRealizable.scala index e4849bdf1c25..0823fbbd2746 100644 --- a/compiler/src/dotty/tools/dotc/core/CheckRealizable.scala +++ b/compiler/src/dotty/tools/dotc/core/CheckRealizable.scala @@ -47,7 +47,7 @@ object CheckRealizable { def boundsRealizability(tp: Type)(implicit ctx: Context): Realizability = new CheckRealizable().boundsRealizability(tp) - private val LateInitialized = Lazy | Erased + private val LateInitializedFlags = Lazy | Erased } /** Compute realizability status. @@ -70,7 +70,7 @@ class CheckRealizable(implicit ctx: Context) { /** Is symbol's definitition a lazy or erased val? * (note we exclude modules here, because their realizability is ensured separately) */ - private def isLateInitialized(sym: Symbol) = sym.is(LateInitialized, butNot = Module) + private def isLateInitialized(sym: Symbol) = sym.isOneOf(LateInitializedFlags, butNot = Module) /** The realizability status of given type `tp`*/ def realizability(tp: Type): Realizability = tp.dealias match { @@ -183,7 +183,7 @@ class CheckRealizable(implicit ctx: Context) { private def memberRealizability(tp: Type) = { def checkField(sofar: Realizability, fld: SingleDenotation): Realizability = sofar andAlso { - if (checkedFields.contains(fld.symbol) || fld.symbol.is(Private | Mutable | LateInitialized)) + if (checkedFields.contains(fld.symbol) || fld.symbol.isOneOf(Private | Mutable | LateInitializedFlags)) // if field is private it cannot be part of a visible path // if field is mutable it cannot be part of a path // if field is lazy or erased it does not need to be initialized when the owning object is diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index f19539ed5ad6..d261b025942b 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -13,7 +13,7 @@ import Scopes._ import Uniques._ import ast.Trees._ import ast.untpd -import Flags.ImplicitOrImpliedOrGiven +import Flags.DelegateOrGivenOrImplicit import util.{FreshNameCreator, NoSource, SimpleIdentityMap, SourceFile} import typer.{Implicits, ImportInfo, Inliner, NamerContextOps, SearchHistory, SearchRoot, TypeAssigner, Typer} import Implicits.ContextualImplicits @@ -214,7 +214,7 @@ object Contexts { implicitsCache = { val implicitRefs: List[ImplicitRef] = if (isClassDefContext) - try owner.thisType.implicitMembers(ImplicitOrImpliedOrGiven) + try owner.thisType.implicitMembers(DelegateOrGivenOrImplicit) catch { case ex: CyclicReference => Nil } @@ -404,7 +404,7 @@ object Contexts { case _ => None } ctx.fresh.setImportInfo( - new ImportInfo(implicit ctx => sym, imp.selectors, impNameOpt, imp.importImplied)) + new ImportInfo(implicit ctx => sym, imp.selectors, impNameOpt, imp.importDelegate)) } /** Does current phase use an erased types interpretation? */ diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 07c1fb8d565a..6d345a1550cc 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -520,10 +520,10 @@ class Definitions { @threadUnsafe lazy val LongType: TypeRef = valueTypeRef("scala.Long", java.lang.Long.TYPE, LongEnc, nme.specializedTypeNames.Long) def LongClass(implicit ctx: Context): ClassSymbol = LongType.symbol.asClass @threadUnsafe lazy val Long_XOR_Long: Symbol = LongType.member(nme.XOR).requiredSymbol("method", nme.XOR, LongType.denot)( - x => (x is Method) && (x.info.firstParamTypes.head isRef defn.LongClass) + x => x.is(Method) && (x.info.firstParamTypes.head isRef defn.LongClass) ) @threadUnsafe lazy val Long_LSR_Int: Symbol = LongType.member(nme.LSR).requiredSymbol("method", nme.LSR, LongType.denot)( - x => (x is Method) && (x.info.firstParamTypes.head isRef defn.IntClass) + x => x.is(Method) && (x.info.firstParamTypes.head isRef defn.IntClass) ) @threadUnsafe lazy val Long_plusR: TermRef = LongClass.requiredMethodRef(nme.PLUS, List(LongType)) def Long_+ : Symbol = Long_plusR.symbol diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index b041a69e171c..331d593a2644 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -113,7 +113,7 @@ object Denotations { /** Keep only those denotations in this group that have all of the flags in `required`, * but none of the flags in `excluded`. */ - def filterWithFlags(required: FlagConjunction, excluded: FlagSet)(implicit ctx: Context): PreDenotation + def filterWithFlags(required: FlagSet, excluded: FlagSet)(implicit ctx: Context): PreDenotation private[this] var cachedPrefix: Type = _ private[this] var cachedAsSeenFrom: AsSeenFromResult = _ @@ -260,7 +260,7 @@ object Denotations { * flags and no `excluded` flag, and produce a denotation that contains the type of the member * as seen from given prefix `pre`. */ - def findMember(name: Name, pre: Type, required: FlagConjunction, excluded: FlagSet)(implicit ctx: Context): Denotation = + def findMember(name: Name, pre: Type, required: FlagSet, excluded: FlagSet)(implicit ctx: Context): Denotation = info.findMember(name, pre, required, excluded) /** If this denotation is overloaded, filter with given predicate. @@ -305,7 +305,7 @@ object Denotations { def requiredMethod(pname: PreName)(implicit ctx: Context): TermSymbol = { val name = pname.toTermName - info.member(name).requiredSymbol("method", name, this)(_ is Method).asTerm + info.member(name).requiredSymbol("method", name, this)(_.is(Method)).asTerm } def requiredMethodRef(name: PreName)(implicit ctx: Context): TermRef = requiredMethod(name).termRef @@ -313,7 +313,7 @@ object Denotations { def requiredMethod(pname: PreName, argTypes: List[Type])(implicit ctx: Context): TermSymbol = { val name = pname.toTermName info.member(name).requiredSymbol(i"method", name, this, argTypes) { x => - (x is Method) && { + x.is(Method) && { x.info.paramInfoss match { case paramInfos :: Nil => paramInfos.corresponds(argTypes)(_ =:= _) case _ => false @@ -1108,7 +1108,7 @@ object Denotations { if (p(this)) this else NoDenotation final def filterDisjoint(denots: PreDenotation)(implicit ctx: Context): SingleDenotation = if (denots.exists && denots.matches(this)) NoDenotation else this - def filterWithFlags(required: FlagConjunction, excluded: FlagSet)(implicit ctx: Context): SingleDenotation = + def filterWithFlags(required: FlagSet, excluded: FlagSet)(implicit ctx: Context): SingleDenotation = if (required.isEmpty && excluded.isEmpty || compatibleWith(required, excluded)) this else NoDenotation type AsSeenFromResult = SingleDenotation @@ -1147,12 +1147,12 @@ object Denotations { /** Does this denotation have all the `required` flags but none of the `excluded` flags? */ - private def compatibleWith(required: FlagConjunction, excluded: FlagSet)(implicit ctx: Context): Boolean = { + private def compatibleWith(required: FlagSet, excluded: FlagSet)(implicit ctx: Context): Boolean = { val symd: SymDenotation = this match { case symd: SymDenotation => symd case _ => symbol.denot } - symd.is(required) && !symd.is(excluded) + symd.isAllOf(required) && !symd.isOneOf(excluded) } } @@ -1237,7 +1237,7 @@ object Denotations { derivedUnion(denot1 filterWithPredicate p, denot2 filterWithPredicate p) def filterDisjoint(denot: PreDenotation)(implicit ctx: Context): PreDenotation = derivedUnion(denot1 filterDisjoint denot, denot2 filterDisjoint denot) - def filterWithFlags(required: FlagConjunction, excluded: FlagSet)(implicit ctx: Context): PreDenotation = + def filterWithFlags(required: FlagSet, excluded: FlagSet)(implicit ctx: Context): PreDenotation = derivedUnion(denot1.filterWithFlags(required, excluded), denot2.filterWithFlags(required, excluded)) protected def derivedUnion(denot1: PreDenotation, denot2: PreDenotation) = if ((denot1 eq this.denot1) && (denot2 eq this.denot2)) this @@ -1370,7 +1370,7 @@ object Denotations { * enter it. */ def missingHook(owner: Symbol, name: Name)(implicit ctx: Context): Symbol = - if ((owner is Package) && name.isTermName) + if (owner.is(Package) && name.isTermName) ctx.newCompletePackageSymbol(owner, name.asTermName).entered else NoSymbol diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index a9fff5f11c94..464807e98a35 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -5,113 +5,146 @@ import language.implicitConversions object Flags { - /** A FlagSet represents a set of flags. Flags are encoded as follows: - * The first two bits indicate whether a flagset applies to terms, - * to types, or to both. Bits 2..63 are available for properties - * and can be doubly used for terms and types. - */ - case class FlagSet(val bits: Long) extends AnyVal { + object opaques { + + /** A FlagSet represents a set of flags. Flags are encoded as follows: + * The first two bits indicate whether a flag set applies to terms, + * to types, or to both. Bits 2..63 are available for properties + * and can be doubly used for terms and types. + */ + opaque type FlagSet = Long + def FlagSet(bits: Long): FlagSet = bits + def toBits(fs: FlagSet): Long = fs + + /** A flag set consisting of a single flag */ + opaque type Flag <: FlagSet = Long + private[Flags] def Flag(bits: Long): Flag = bits + } + type FlagSet = opaques.FlagSet + def FlagSet(bits: Long): FlagSet = opaques.FlagSet(bits) + // DOTTY TODO: replace previous 2 lines with + // export opaques.FlagSet + // once 0.17 is released and #6721 is in the bootstrap - /** The union of this flag set and the given flag set + type Flag = opaques.Flag + + delegate FlagOps { + + def (x: FlagSet) bits: Long = opaques.toBits(x) + + /** The union of the given flag sets. * Combining two FlagSets with `|` will give a FlagSet * that has the intersection of the applicability to terms/types * of the two flag sets. It is checked that the intersection is not empty. */ - def | (that: FlagSet): FlagSet = - if (bits == 0) that - else if (that.bits == 0) this + def (x: FlagSet) | (y: FlagSet): FlagSet = + if (x.bits == 0) y + else if (y.bits == 0) x else { - val tbits = bits & that.bits & KINDFLAGS + val tbits = x.bits & y.bits & KINDFLAGS if (tbits == 0) - assert(false, s"illegal flagset combination: $this and $that") - FlagSet(tbits | ((this.bits | that.bits) & ~KINDFLAGS)) + assert(false, s"illegal flagset combination: $x and $y") + FlagSet(tbits | ((x.bits | y.bits) & ~KINDFLAGS)) } - /** The intersection of this flag set and the given flag set */ - def & (that: FlagSet): FlagSet = FlagSet(bits & that.bits) + /** The intersection of the given flag sets */ + def (x: FlagSet) & (y: FlagSet): FlagSet = FlagSet(x.bits & y.bits) + + /** The intersection of a flag set with the complement of another flag set */ + def (x: FlagSet) &~ (y: FlagSet): FlagSet = { + val tbits = x.bits & KINDFLAGS + if ((tbits & y.bits) == 0) x + else FlagSet(tbits | ((x.bits & ~y.bits) & ~KINDFLAGS)) + } + + def (x: FlagSet) ^ (y: FlagSet) = + FlagSet((x.bits | y.bits) & KINDFLAGS | (x.bits ^ y.bits) & ~KINDFLAGS) - /** The intersection of this flag set with the complement of the given flag set */ - def &~ (that: FlagSet): FlagSet = { - val tbits = bits & KINDFLAGS - if ((tbits & that.bits) == 0) this - else FlagSet(tbits | ((this.bits & ~that.bits) & ~KINDFLAGS)) + /** Does the given flag set contain the given flag? + * This means that both the kind flags and the carrier bits have non-empty intersection. + */ + def (x: FlagSet) is (flag: Flag): Boolean = { + val fs = x.bits & flag.bits + (fs & KINDFLAGS) != 0 && (fs & ~KINDFLAGS) != 0 } - def ^ (that: FlagSet) = - FlagSet((bits | that.bits) & KINDFLAGS | (bits ^ that.bits) & ~KINDFLAGS) + /** Does the given flag set contain the given flag + * and at the same time contain none of the flags in the `butNot` set? + */ + def (x: FlagSet) is (flag: Flag, butNot: FlagSet): Boolean = x.is(flag) && !x.isOneOf(butNot) - /** Does this flag set have a non-empty intersection with the given flag set? + /** Does the given flag set have a non-empty intersection with another flag set? * This means that both the kind flags and the carrier bits have non-empty intersection. */ - def is(flags: FlagSet): Boolean = { - val fs = bits & flags.bits + def (x: FlagSet) isOneOf (flags: FlagSet): Boolean = { + val fs = x.bits & flags.bits (fs & KINDFLAGS) != 0 && (fs & ~KINDFLAGS) != 0 } - /** Does this flag set have a non-empty intersection with the given flag set, + /** Does the given flag set have a non-empty intersection with another flag set, * and at the same time contain none of the flags in the `butNot` set? */ - def is(flags: FlagSet, butNot: FlagSet): Boolean = is(flags) && !is(butNot) + def (x: FlagSet) isOneOf (flags: FlagSet, butNot: FlagSet): Boolean = x.isOneOf(flags) && !x.isOneOf(butNot) - /** Does this flag set have all of the flags in given flag conjunction? - * Pre: The intersection of the typeflags of both sets must be non-empty. + /** Does a given flag set have all of the flags of another flag set? + * Pre: The intersection of the term/type flags of both sets must be non-empty. */ - def is(flags: FlagConjunction): Boolean = { - val fs = bits & flags.bits + def (x: FlagSet) isAllOf (flags: FlagSet): Boolean = { + val fs = x.bits & flags.bits ((fs & KINDFLAGS) != 0 || flags.bits == 0) && (fs >>> TYPESHIFT) == (flags.bits >>> TYPESHIFT) } - /** Does this flag set have all of the flags in given flag conjunction? + /** Does a given flag set have all of the flags in another flag set * and at the same time contain none of the flags in the `butNot` set? - * Pre: The intersection of the typeflags of both sets must be non-empty. + * Pre: The intersection of the term/type flags of both sets must be non-empty. */ - def is(flags: FlagConjunction, butNot: FlagSet): Boolean = is(flags) && !is(butNot) + def (x: FlagSet) isAllOf (flags: FlagSet, butNot: FlagSet): Boolean = x.isAllOf(flags) && !x.isOneOf(butNot) - def isEmpty: Boolean = (bits & ~KINDFLAGS) == 0 + def (x: FlagSet) isEmpty: Boolean = (x.bits & ~KINDFLAGS) == 0 - /** Is this flag set a subset of that one? */ - def <= (that: FlagSet): Boolean = (bits & that.bits) == bits + /** Is a given flag set a subset of another flag set? */ + def (x: FlagSet) <= (y: FlagSet): Boolean = (x.bits & y.bits) == x.bits - /** Does this flag set apply to terms? */ - def isTermFlags: Boolean = (bits & TERMS) != 0 + /** Does the given flag set apply to terms? */ + def (x: FlagSet) isTermFlags: Boolean = (x.bits & TERMS) != 0 - /** Does this flag set apply to terms? */ - def isTypeFlags: Boolean = (bits & TYPES) != 0 + /** Does the given flag set apply to terms? */ + def (x: FlagSet) isTypeFlags: Boolean = (x.bits & TYPES) != 0 - /** This flag set with all flags transposed to be type flags */ - def toTypeFlags: FlagSet = if (bits == 0) this else FlagSet(bits & ~KINDFLAGS | TYPES) + /** The given flag set with all flags transposed to be type flags */ + def (x: FlagSet) toTypeFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TYPES) - /** This flag set with all flags transposed to be term flags */ - def toTermFlags: FlagSet = if (bits == 0) this else FlagSet(bits & ~KINDFLAGS | TERMS) + /** The given flag set with all flags transposed to be term flags */ + def (x: FlagSet) toTermFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits & ~KINDFLAGS | TERMS) - /** This flag set with all flags transposed to be common flags */ - def toCommonFlags: FlagSet = if (bits == 0) this else FlagSet(bits | KINDFLAGS) + /** The given flag set with all flags transposed to be common flags */ + def (x: FlagSet) toCommonFlags: FlagSet = if (x.bits == 0) x else FlagSet(x.bits | KINDFLAGS) - /** The number of non-kind flags in this set */ - def numFlags: Int = java.lang.Long.bitCount(bits & ~KINDFLAGS) + /** The number of non-kind flags in the given flag set */ + def (x: FlagSet) numFlags: Int = java.lang.Long.bitCount(x.bits & ~KINDFLAGS) - /** The lowest non-kind bit set in this flagset */ - def firstBit: Int = java.lang.Long.numberOfTrailingZeros(bits & ~KINDFLAGS) + /** The lowest non-kind bit set in the given flag set */ + def (x: FlagSet) firstBit: Int = java.lang.Long.numberOfTrailingZeros(x.bits & ~KINDFLAGS) - /** The list of non-empty names of flags with given index idx that are set in this FlagSet */ - private def flagString(idx: Int): List[String] = - if ((bits & (1L << idx)) == 0) Nil + /** The list of non-empty names of flags with given index idx that are set in the given flag set */ + private def (x: FlagSet) flagString(idx: Int): List[String] = + if ((x.bits & (1L << idx)) == 0) Nil else { def halfString(kind: Int) = - if ((bits & (1L << kind)) != 0) flagName(idx)(kind) else "" + if ((x.bits & (1L << kind)) != 0) flagName(idx)(kind) else "" val termFS = halfString(TERMindex) val typeFS = halfString(TYPEindex) val strs = termFS :: (if (termFS == typeFS) Nil else typeFS :: Nil) strs filter (_.nonEmpty) } - /** The list of non-empty names of flags that are set in this FlagSet */ - def flagStrings(privateWithin: String): Seq[String] = { - var rawStrings = (2 to MaxFlag).flatMap(flagString) - if (!privateWithin.isEmpty && !this.is(Protected)) + /** The list of non-empty names of flags that are set in teh given flag set */ + def (x: FlagSet) flagStrings(privateWithin: String): Seq[String] = { + var rawStrings = (2 to MaxFlag).flatMap(x.flagString(_)) // DOTTY problem: cannot drop with (_) + if (!privateWithin.isEmpty && !x.is(Protected)) rawStrings = rawStrings :+ "private" - val scopeStr = if (this.is(Local)) "this" else privateWithin + val scopeStr = if (x.is(Local)) "this" else privateWithin if (scopeStr != "") rawStrings.filter(_ != "").map { case "private" => s"private[$scopeStr]" @@ -121,37 +154,26 @@ object Flags { else rawStrings } - /** The string representation of this flag set */ - override def toString: String = flagStrings("").mkString(" ") + /** The string representation of the given flag set */ + def (x: FlagSet) flagsString: String = x.flagStrings("").mkString(" ") } def termFlagSet(x: Long) = FlagSet(TERMS | x) - /** A class representing flag sets that should be tested - * conjunctively. I.e. for a flag conjunction `fc`, - * `x is fc` tests whether `x` contains all flags in `fc`. - */ - case class FlagConjunction(bits: Long) { - override def toString: String = FlagSet(bits).toString - def | (fs: FlagSet): FlagConjunction = FlagConjunction((FlagSet(bits) | fs).bits) - } + private inline val TYPESHIFT = 2 + private inline val TERMindex = 0 + private inline val TYPEindex = 1 + private inline val TERMS = 1 << TERMindex + private inline val TYPES = 1 << TYPEindex + private inline val KINDFLAGS = TERMS | TYPES - def termFlagConjunction(x: Long) = FlagConjunction(TERMS | x) - - private final val TYPESHIFT = 2 - private final val TERMindex = 0 - private final val TYPEindex = 1 - private final val TERMS = 1 << TERMindex - private final val TYPES = 1 << TYPEindex - private final val KINDFLAGS = TERMS | TYPES - - private final val FirstFlag = 2 - private final val FirstNotPickledFlag = 48 - private final val MaxFlag = 63 + private inline val FirstFlag = 2 + private inline val FirstNotPickledFlag = 48 + private inline val MaxFlag = 63 private val flagName = Array.fill(64, 2)("") - private def isDefinedAsFlag(idx: Int) = flagName(idx) exists (_.nonEmpty) + private def isDefinedAsFlag(idx: Int) = flagName(idx).exists(_.nonEmpty) /** The flag set containing all defined flags of either kind whose bits * lie in the given range @@ -160,28 +182,6 @@ object Flags { FlagSet((KINDFLAGS.toLong /: (start until end)) ((bits, idx) => if (isDefinedAsFlag(idx)) bits | (1L << idx) else bits)) - /** The flag with given index between 2 and 63 which applies to terms. - * Installs given name as the name of the flag. */ - private def termFlag(index: Int, name: String): FlagSet = { - flagName(index)(TERMindex) = name - FlagSet(TERMS | (1L << index)) - } - - /** The flag with given index between 2 and 63 which applies to types. - * Installs given name as the name of the flag. */ - private def typeFlag(index: Int, name: String): FlagSet = { - flagName(index)(TYPEindex) = name - FlagSet(TYPES | (1L << index)) - } - - /** The flag with given index between 2 and 63 which applies to both terms and types - * Installs given name as the name of the flag. */ - private def commonFlag(index: Int, name: String): FlagSet = { - flagName(index)(TERMindex) = name - flagName(index)(TYPEindex) = name - FlagSet(TERMS | TYPES | (1L << index)) - } - /** The union of all flags in given flag set */ def union(flagss: FlagSet*): FlagSet = { var flag = EmptyFlags @@ -190,550 +190,395 @@ object Flags { flag } - def allOf(flags: FlagSet) = FlagConjunction(flags.bits) - - /** The conjunction of all flags in given flag set */ - def allOf(flags1: FlagSet, flags2: FlagSet): FlagConjunction = { - assert(flags1.numFlags == 1 && flags2.numFlags == 1, "Flags.allOf doesn't support flag " + (if (flags1.numFlags != 1) flags1 else flags2)) - FlagConjunction((flags1 | flags2).bits) - } - - /** The conjunction of all flags in given flag set */ - def allOf(flags1: FlagSet, flags2: FlagSet, flags3: FlagSet, flagss: FlagSet*): FlagConjunction = { - val flags0 = allOf(flags1, flags2) | flags3 - assert(flags3.numFlags == 1 && flagss.forall(_.numFlags == 1), "Flags.allOf doesn't support flag " + (if (flags3.numFlags != 1) flags3 else flagss.find(_.numFlags != 1))) - FlagConjunction((flags0 | union(flagss: _*)).bits) - } - def commonFlags(flagss: FlagSet*): FlagSet = union(flagss.map(_.toCommonFlags): _*) /** The empty flag set */ - final val EmptyFlags: FlagSet = FlagSet(0) - - final val EmptyFlagConjunction = FlagConjunction(0) + val EmptyFlags: FlagSet = FlagSet(0) /** The undefined flag set */ - final val UndefinedFlags: FlagSet = FlagSet(~KINDFLAGS) + val UndefinedFlags: FlagSet = FlagSet(~KINDFLAGS) - // Available flags: + /** Three flags with given index between 2 and 63. + * The first applies to both terms and types. the second is a term flag, and + * the third is a type flag. Installs given name(s) as the name(s) of the flags. + * @param name The name to be used for the term flag + * @param typeName The name to be used for the type flag, if it is different from `name`. + */ + private def newFlags(index: Int, name: String, typeName: String = ""): (Flag, Flag, Flag) = { + flagName(index)(TERMindex) = name + flagName(index)(TYPEindex) = if (typeName.isEmpty) name else typeName + val bits = 1L << index + (opaques.Flag(KINDFLAGS | bits), opaques.Flag(TERMS | bits), opaques.Flag(TYPES | bits)) + } + + // ----------------- Available flags ----------------------------------------------------- /** Labeled with `private` modifier */ - final val Private: FlagSet = commonFlag(2, "private") - final val PrivateTerm: FlagSet = Private.toTermFlags - final val PrivateType: FlagSet = Private.toTypeFlags + val (Private @ _, PrivateTerm @ _, PrivateType @ _) = newFlags(2, "private") /** Labeled with `protected` modifier */ - final val Protected: FlagSet = commonFlag(3, "protected") + val (Protected @ _, _, _) = newFlags(3, "protected") /** Labeled with `override` modifier */ - final val Override: FlagSet = commonFlag(4, "override") + val (Override @ _, _, _) = newFlags(4, "override") /** A declared, but not defined member */ - final val Deferred: FlagSet = commonFlag(5, "") - final val DeferredTerm: FlagSet = Deferred.toTermFlags - final val DeferredType: FlagSet = Deferred.toTypeFlags + val (Deferred @ _, DeferredTerm @ _, DeferredType @ _) = newFlags(5, "") /** Labeled with `final` modifier */ - final val Final: FlagSet = commonFlag(6, "final") + val (Final @ _, _, _) = newFlags(6, "final") - /** A method symbol. */ - final val Method: FlagSet = termFlag(7, "") - final val HigherKinded: FlagSet = typeFlag(7, "") + /** A method symbol */ + val (_, Method @ _, HigherKinded @ _) = newFlags(7, "", "") // TODO drop HigherKinded /** A (term or type) parameter to a class or method */ - final val Param: FlagSet = commonFlag(8, "") - final val TermParam: FlagSet = Param.toTermFlags - final val TypeParam: FlagSet = Param.toTypeFlags + val (Param @ _, TermParam @ _, TypeParam @ _) = newFlags(8, "") /** Labeled with `implicit` modifier (implicit value) */ - final val Implicit: FlagSet = commonFlag(9, "implicit") - final val ImplicitTerm: FlagSet = Implicit.toTermFlags - - /** Labeled with `lazy` (a lazy val). */ - final val Lazy: FlagSet = termFlag(10, "lazy") - - /** A trait */ - final val Trait: FlagSet = typeFlag(10, "") + val (Implicit @ _, ImplicitTerm @ _, _) = newFlags(9, "implicit") - final val LazyOrTrait: FlagSet = Lazy.toCommonFlags + /** Labeled with `lazy` (a lazy val) / a trait */ + val (LazyOrTrait @ _, Lazy @ _, Trait @ _) = newFlags(10, "lazy", "") /** A value or variable accessor (getter or setter) */ - final val Accessor: FlagSet = termFlag(11, "") - - /** Labeled with `sealed` modifier (sealed class) */ - final val Sealed: FlagSet = typeFlag(11, "sealed") - - final val AccessorOrSealed: FlagSet = Accessor.toCommonFlags + val (AccessorOrSealed @ _, Accessor @ _, Sealed @ _) = newFlags(11, "", "sealed") /** A mutable var */ - final val Mutable: FlagSet = termFlag(12, "mutable") - - /** An opaque type or a class containing one */ - final val Opaque: FlagSet = typeFlag(12, "opaque") - - final val MutableOrOpaque: FlagSet = Mutable.toCommonFlags + val (_, Mutable @ _, _) = newFlags(12, "mutable") /** Symbol is local to current class (i.e. private[this] or protected[this] * pre: Private or Protected are also set */ - final val Local: FlagSet = commonFlag(13, "") + val (Local @ _, _, _) = newFlags(13, "") /** A field generated for a primary constructor parameter (no matter if it's a 'val' or not), * or an accessor of such a field. */ - final val ParamAccessor: FlagSet = termFlag(14, "") + val (_, ParamAccessor @ _, _) = newFlags(14, "") /** A value or class implementing a module */ - final val Module: FlagSet = commonFlag(15, "module") - final val ModuleVal: FlagSet = Module.toTermFlags - final val ModuleClass: FlagSet = Module.toTypeFlags + val (Module @ _, ModuleVal @ _, ModuleClass @ _) = newFlags(15, "module") /** A value or class representing a package */ - final val Package: FlagSet = commonFlag(16, "") - final val PackageVal: FlagSet = Package.toTermFlags - final val PackageClass: FlagSet = Package.toTypeFlags + val (Package @ _, PackageVal @ _, PackageClass @ _) = newFlags(16, "") /** A case class or its companion object * Note: Case is also used to indicate that a symbol is bound by a pattern. */ - final val Case: FlagSet = commonFlag(17, "case") - final val CaseClass: FlagSet = Case.toTypeFlags - final val CaseVal: FlagSet = Case.toTermFlags + val (Case @ _, CaseVal @ _, CaseClass @ _) = newFlags(17, "case") /** A compiler-generated symbol, which is visible for type-checking * (compare with artifact) */ - final val Synthetic: FlagSet = commonFlag(18, "") + val (Synthetic @ _, _, _) = newFlags(18, "") /** Labelled with `inline` modifier */ - final val Inline: FlagSet = commonFlag(19, "inline") + val (Inline @ _, _, _) = newFlags(19, "inline") - /** A covariant type variable / an outer accessor */ - final val CovariantOrOuter: FlagSet = commonFlag(20, "") - final val Covariant: FlagSet = typeFlag(20, "") - final val OuterAccessor: FlagSet = termFlag(20, "") + /** An outer accessor / a covariant type variable */ + val (OuterOrCovariant @ _, OuterAccessor @ _, Covariant @ _) = newFlags(20, "", "") - /** A contravariant type variable / the label of a labeled block */ - final val ContravariantOrLabel: FlagSet = commonFlag(21, "") - final val Contravariant: FlagSet = typeFlag(21, "") - final val Label: FlagSet = termFlag(21, "