diff options
author | Paul Phillips <paulp@improving.org> | 2013-01-09 12:18:50 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-01-09 12:28:57 -0800 |
commit | 198d5229967367493960a6b4e0f9c382d7122a25 (patch) | |
tree | 98dd0c2cfe624baae0534b0d9926292b2cff4e18 /src | |
parent | 816bcdf382ea0469f6c5eadcff44901921ba6075 (diff) | |
download | scala-198d5229967367493960a6b4e0f9c382d7122a25.tar.gz scala-198d5229967367493960a6b4e0f9c382d7122a25.tar.bz2 scala-198d5229967367493960a6b4e0f9c382d7122a25.zip |
Made "mode" into a value class.
This is an obvious place to apply value class goodness and
collect some safety/sanity in typing modes. It does show off
a challenge in introducing value classes without disruption:
there's no way to deprecate the old signature of 'typed',
'adapt', etc. because they erase the same.
class Bippy(val x: Int) extends AnyVal
class A {
@deprecated("Use a bippy") def f(x: Int): Int = 5
def f(x: Bippy): Int = x.x
}
./a.scala:5: error: double definition:
method f:(x: Bippy)Int and
method f:(x: Int)Int at line 4
have same type after erasure: (x: Int)Int
An Int => Mode implicit handles most uses, but nothing can
be done to avoid breaking anything which e.g. extends Typer
and overrides typed.
Diffstat (limited to 'src')
15 files changed, 204 insertions, 183 deletions
diff --git a/src/compiler/scala/reflect/macros/runtime/Typers.scala b/src/compiler/scala/reflect/macros/runtime/Typers.scala index f9add91b9a..7e268247dd 100644 --- a/src/compiler/scala/reflect/macros/runtime/Typers.scala +++ b/src/compiler/scala/reflect/macros/runtime/Typers.scala @@ -1,6 +1,8 @@ package scala.reflect.macros package runtime +import scala.reflect.internal.Mode + trait Typers { self: Context => @@ -22,7 +24,7 @@ trait Typers { // typechecking uses silent anyways (e.g. in typedSelect), so you'll only waste your time // I'd advise fixing the root cause: finding why the context is not set to report errors // (also see reflect.runtime.ToolBoxes.typeCheckExpr for a workaround that might work for you) - wrapper(callsiteTyper.silent(_.typed(tree, universe.analyzer.EXPRmode, pt)) match { + wrapper(callsiteTyper.silent(_.typed(tree, Mode.EXPRmode, pt)) match { case universe.analyzer.SilentResultValue(result) => macroLogVerbose(result) result @@ -62,4 +64,4 @@ trait Typers { def resetAllAttrs(tree: Tree): Tree = universe.resetAllAttrs(tree) def resetLocalAttrs(tree: Tree): Tree = universe.resetLocalAttrs(tree) -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala index 5d2cc51c97..5d5d7d483c 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala @@ -170,7 +170,7 @@ trait ModelFactoryImplicitSupport { val newContext = context.makeImplicit(context.ambiguousErrors) newContext.macrosEnabled = false val newTyper = global.analyzer.newTyper(newContext) - newTyper.silent(_.typed(appliedTree, global.analyzer.EXPRmode, WildcardType), false) match { + newTyper.silent(_.typed(appliedTree, EXPRmode, WildcardType), false) match { case global.analyzer.SilentResultValue(t: Tree) => t case global.analyzer.SilentTypeError(err) => diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala b/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala index 16b22869e7..0eabd84234 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala @@ -24,7 +24,7 @@ trait ReplGlobal extends Global { val global: ReplGlobal.this.type = ReplGlobal.this } with Analyzer { override def newTyper(context: Context): Typer = new Typer(context) { - override def typed(tree: Tree, mode: Int, pt: Type): Tree = { + override def typed(tree: Tree, mode: Mode, pt: Type): Tree = { val res = super.typed(tree, mode, pt) tree match { case Ident(name) if !tree.symbol.hasPackageFlag && !name.toString.startsWith("$") => diff --git a/src/compiler/scala/tools/nsc/package.scala b/src/compiler/scala/tools/nsc/package.scala index 00a9f3b39c..5e8d4f7885 100644 --- a/src/compiler/scala/tools/nsc/package.scala +++ b/src/compiler/scala/tools/nsc/package.scala @@ -6,6 +6,15 @@ package scala.tools package object nsc { + type Mode = scala.reflect.internal.Mode + val Mode = scala.reflect.internal.Mode + + def EXPRmode = Mode.EXPRmode + def BYVALmode = Mode.BYVALmode + def POLYmode = Mode.POLYmode + def TAPPmode = Mode.TAPPmode + def FUNmode = Mode.FUNmode + type Phase = scala.reflect.internal.Phase val NoPhase = scala.reflect.internal.NoPhase diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 13d3bb23cb..e3b5efde1f 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -10,6 +10,7 @@ import scala.reflect.internal.ClassfileConstants._ import scala.collection.{ mutable, immutable } import symtab._ import Flags._ +import scala.reflect.internal.Mode._ abstract class Erasure extends AddInterfaces with scala.reflect.internal.transform.Erasure @@ -801,12 +802,12 @@ abstract class Erasure extends AddInterfaces /** A replacement for the standard typer's adapt method. */ - override protected def adapt(tree: Tree, mode: Int, pt: Type, original: Tree = EmptyTree): Tree = + override protected def adapt(tree: Tree, mode: Mode, pt: Type, original: Tree = EmptyTree): Tree = adaptToType(tree, pt) /** A replacement for the standard typer's `typed1` method. */ - override def typed1(tree: Tree, mode: Int, pt: Type): Tree = { + override def typed1(tree: Tree, mode: Mode, pt: Type): Tree = { val tree1 = try { tree match { case InjectDerivedValue(arg) => diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index 1c48eeed70..ab65e18093 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -197,7 +197,7 @@ abstract class Duplicators extends Analyzer { * their symbols are recreated ad-hoc and their types are fixed inline, instead of letting the * namer/typer handle them, or Idents that refer to them. */ - override def typed(tree: Tree, mode: Int, pt: Type): Tree = { + override def typed(tree: Tree, mode: Mode, pt: Type): Tree = { debuglog("typing " + tree + ": " + tree.tpe + ", " + tree.getClass) val origtreesym = tree.symbol if (tree.hasSymbolField && tree.symbol != NoSymbol diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 768d739b4b..64d76d6a83 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -676,7 +676,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { * the expandee with an error marker set if the expansion has been cancelled due malformed arguments or implementation * the expandee with an error marker set if there has been an error */ - def macroExpand(typer: Typer, expandee: Tree, mode: Int = EXPRmode, pt: Type = WildcardType): Tree = { + def macroExpand(typer: Typer, expandee: Tree, mode: Mode = EXPRmode, pt: Type = WildcardType): Tree = { val start = if (Statistics.canEnable) Statistics.startTimer(macroExpandNanos) else null if (Statistics.canEnable) Statistics.incCounter(macroExpandCount) try { diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index dfc1196f2e..f5884e5c34 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -104,7 +104,7 @@ trait NamesDefaults { self: Analyzer => * @return the transformed application (a Block) together with the NamedApplyInfo. * if isNamedApplyBlock(tree), returns the existing context.namedApplyBlockInfo */ - def transformNamedApplication(typer: Typer, mode: Int, pt: Type) + def transformNamedApplication(typer: Typer, mode: Mode, pt: Type) (tree: Tree, argPos: Int => Int): Tree = { import typer._ import typer.infer._ diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index 260bd87fdf..1c1e9c10fb 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -189,7 +189,7 @@ abstract class TreeCheckers extends Analyzer { if (t.symbol == NoSymbol) errorFn(t.pos, "no symbol: " + treestr(t)) - override def typed(tree: Tree, mode: Int, pt: Type): Tree = returning(tree) { + override def typed(tree: Tree, mode: Mode, pt: Type): Tree = returning(tree) { case EmptyTree | TypeTree() => () case _ if tree.tpe != null => tpeOfTree.getOrElseUpdate(tree, try tree.tpe finally tree.clearType()) diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index 3bb6ae53dc..07d7bd07a6 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -552,7 +552,7 @@ trait TypeDiagnostics { } // The checkDead call from typedArg is more selective. - def inMode(mode: Int, tree: Tree): Tree = { + def inMode(mode: Mode, tree: Tree): Tree = { val modeOK = (mode & (EXPRmode | BYVALmode | POLYmode)) == (EXPRmode | BYVALmode) if (modeOK) apply(tree) else tree diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index b853f687a7..368d9f545b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -16,6 +16,7 @@ import scala.collection.mutable import scala.reflect.internal.util.{ BatchSourceFile, Statistics, shortClassOfInstance } import mutable.ListBuffer import symtab.Flags._ +import Mode._ // Suggestion check whether we can do without priming scopes with symbols of outer scopes, // like the IDE does. @@ -24,7 +25,7 @@ import symtab.Flags._ * @author Martin Odersky * @version 1.0 */ -trait Typers extends Modes with Adaptations with Tags { +trait Typers extends Adaptations with Tags { self: Analyzer => import global._ @@ -32,7 +33,7 @@ trait Typers extends Modes with Adaptations with Tags { import TypersStats._ import patmat.DefaultOverrideMatchAttachment - final def forArgMode(fun: Tree, mode: Int) = + final def forArgMode(fun: Tree, mode: Mode) = if (treeInfo.isSelfOrSuperConstrCall(fun)) mode | SCCmode else mode @@ -525,11 +526,11 @@ trait Typers extends Modes with Adaptations with Tags { /** Does the context of tree `tree` require a stable type? */ - private def isStableContext(tree: Tree, mode: Int, pt: Type) = - isNarrowable(tree.tpe) && ((mode & (EXPRmode | LHSmode)) == EXPRmode) && + private def isStableContext(tree: Tree, mode: Mode, pt: Type) = + isNarrowable(tree.tpe) && mode.inExprMode && mode.inNone(LHSmode) && (xtypes || (pt.isStable || - (mode & QUALmode) != 0 && !tree.symbol.isConstant || + mode.inAll(QUALmode) && !tree.symbol.isConstant || pt.typeSymbol.isAbstractType && pt.bounds.lo.isStable && !(tree.tpe <:< pt)) || pt.typeSymbol.isRefinementClass && !(tree.tpe <:< pt)) @@ -583,15 +584,15 @@ trait Typers extends Modes with Adaptations with Tags { * 3. Turn tree type into stable type if possible and required by context. * 4. Give getClass calls a more precise type based on the type of the target of the call. */ - private def stabilize(tree: Tree, pre: Type, mode: Int, pt: Type): Tree = { - if (tree.symbol.isOverloaded && !inFunMode(mode)) + private def stabilize(tree: Tree, pre: Type, mode: Mode, pt: Type): Tree = { + if (tree.symbol.isOverloaded && !mode.inFunMode) inferExprAlternative(tree, pt) val sym = tree.symbol def fail() = NotAValueError(tree, sym) if (tree.isErrorTyped) tree - else if (inPatternNotFunMode(mode) && tree.isTerm) { // (1) + else if (mode.inPatternNotFunMode && tree.isTerm) { // (1) if (sym.isValue) { val tree1 = checkStable(tree) // A module reference in a pattern has type Foo.type, not "object Foo" @@ -625,7 +626,7 @@ trait Typers extends Modes with Adaptations with Tags { case _ => !phase.erasedTypes } - def stabilizeFun(tree: Tree, mode: Int, pt: Type): Tree = { + def stabilizeFun(tree: Tree, mode: Mode, pt: Type): Tree = { val sym = tree.symbol val pre = tree match { case Select(qual, _) => qual.tpe @@ -785,7 +786,7 @@ trait Typers extends Modes with Adaptations with Tags { * (14) When in mode EXPRmode, apply a view * If all this fails, error */ - protected def adapt(tree: Tree, mode: Int, pt: Type, original: Tree = EmptyTree): Tree = { + protected def adapt(tree: Tree, mode: Mode, pt: Type, original: Tree = EmptyTree): Tree = { def adaptToImplicitMethod(mt: MethodType): Tree = { if (context.undetparams.nonEmpty) { // (9) -- should revisit dropped condition `(mode & POLYmode) == 0` @@ -854,13 +855,13 @@ trait Typers extends Modes with Adaptations with Tags { } def adaptType(): Tree = { - if (inFunMode(mode)) { + if (mode.inFunMode) { // todo. the commented line below makes sense for typechecking, say, TypeApply(Ident(`some abstract type symbol`), List(...)) // because otherwise Ident will have its tpe set to a TypeRef, not to a PolyType, and `typedTypeApply` will fail // but this needs additional investigation, because it crashes t5228, gadts1 and maybe something else // tree setType tree.tpe.normalize tree - } else if (tree.hasSymbolField && !tree.symbol.typeParams.isEmpty && !inHKMode(mode) && + } else if (tree.hasSymbolField && !tree.symbol.typeParams.isEmpty && !mode.inHKMode && !(tree.symbol.isJavaDefined && context.unit.isJava)) { // (7) // @M When not typing a higher-kinded type ((mode & HKmode) == 0) // or raw type (tree.symbol.isJavaDefined && context.unit.isJava), types must be of kind *, @@ -869,7 +870,7 @@ trait Typers extends Modes with Adaptations with Tags { MissingTypeParametersError(tree) } else if ( // (7.1) @M: check kind-arity // @M: removed check for tree.hasSymbolField and replace tree.symbol by tree.tpe.symbol (TypeTree's must also be checked here, and they don't directly have a symbol) - (inHKMode(mode)) && + mode.inHKMode && // @M: don't check tree.tpe.symbol.typeParams. check tree.tpe.typeParams!!! // (e.g., m[Int] --> tree.tpe.symbol.typeParams.length == 1, tree.tpe.typeParams.length == 0!) !sameLength(tree.tpe.typeParams, pt.typeParams) && @@ -991,7 +992,7 @@ trait Typers extends Modes with Adaptations with Tags { } def insertApply(): Tree = { - assert(!inHKMode(mode), modeString(mode)) //@M + assert(!mode.inHKMode, mode) //@M val adapted = adaptToName(tree, nme.apply) def stabilize0(pre: Type): Tree = stabilize(adapted, pre, EXPRmode | QUALmode, WildcardType) // TODO reconcile the overlap between Typers#stablize and TreeGen.stabilize @@ -1019,26 +1020,26 @@ trait Typers extends Modes with Adaptations with Tags { tree.tpe match { case atp @ AnnotatedType(_, _, _) if canAdaptAnnotations(tree, mode, pt) => // (-1) adaptAnnotations(tree, mode, pt) - case ct @ ConstantType(value) if inNoModes(mode, TYPEmode | FUNmode) && (ct <:< pt) && !forScaladoc && !forInteractive => // (0) + case ct @ ConstantType(value) if mode.inNone(TYPEmode | FUNmode) && (ct <:< pt) && !forScaladoc && !forInteractive => // (0) val sym = tree.symbol if (sym != null && sym.isDeprecated) { val msg = sym.toString + sym.locationString + " is deprecated: " + sym.deprecationMessage.getOrElse("") unit.deprecationWarning(tree.pos, msg) } treeCopy.Literal(tree, value) - case OverloadedType(pre, alts) if !inFunMode(mode) => // (1) + case OverloadedType(pre, alts) if !mode.inFunMode => // (1) inferExprAlternative(tree, pt) adapt(tree, mode, pt, original) case NullaryMethodType(restpe) => // (2) adapt(tree setType restpe, mode, pt, original) - case TypeRef(_, ByNameParamClass, List(arg)) if ((mode & EXPRmode) != 0) => // (2) + case TypeRef(_, ByNameParamClass, List(arg)) if mode.inExprMode => // (2) adapt(tree setType arg, mode, pt, original) case tr @ TypeRef(_, sym, _) if sym.isAliasType && tr.dealias.isInstanceOf[ExistentialType] && ((mode & (EXPRmode | LHSmode)) == EXPRmode) => adapt(tree setType tr.dealias.skolemizeExistential(context.owner, tree), mode, pt, original) case et @ ExistentialType(_, _) if ((mode & (EXPRmode | LHSmode)) == EXPRmode) => adapt(tree setType et.skolemizeExistential(context.owner, tree), mode, pt, original) - case PolyType(tparams, restpe) if inNoModes(mode, TAPPmode | PATTERNmode | HKmode) => // (3) + case PolyType(tparams, restpe) if mode.inNone(TAPPmode | PATTERNmode | HKmode) => // (3) // assert((mode & HKmode) == 0) //@M a PolyType in HKmode represents an anonymous type function, // we're in HKmode since a higher-kinded type is expected --> hence, don't implicitly apply it to type params! // ticket #2197 triggered turning the assert into a guard @@ -1057,18 +1058,18 @@ trait Typers extends Modes with Adaptations with Tags { adaptToImplicitMethod(mt) case mt: MethodType if (((mode & (EXPRmode | FUNmode | LHSmode)) == EXPRmode) && - (context.undetparams.isEmpty || inPolyMode(mode))) && !(tree.symbol != null && tree.symbol.isTermMacro) => + (context.undetparams.isEmpty || mode.inPolyMode)) && !(tree.symbol != null && tree.symbol.isTermMacro) => instantiateToMethodType(mt) case _ => - def shouldInsertApply(tree: Tree) = inAllModes(mode, EXPRmode | FUNmode) && (tree.tpe match { + def shouldInsertApply(tree: Tree) = mode.inAll(EXPRmode | FUNmode) && (tree.tpe match { case _: MethodType | _: OverloadedType | _: PolyType => false case _ => applyPossible }) def applyPossible = { def applyMeth = member(adaptToName(tree, nme.apply), nme.apply) dyna.acceptsApplyDynamic(tree.tpe) || ( - if ((mode & TAPPmode) != 0) + if (mode.inAll(TAPPmode)) tree.tpe.typeParams.isEmpty && applyMeth.filter(!_.tpe.typeParams.isEmpty) != NoSymbol else applyMeth.filter(_.tpe.paramSectionCount > 0) != NoSymbol @@ -1077,17 +1078,17 @@ trait Typers extends Modes with Adaptations with Tags { if (tree.isType) adaptType() else if ( - inExprModeButNot(mode, FUNmode) && !tree.isDef && // typechecking application + mode.inExprModeButNot(FUNmode) && !tree.isDef && // typechecking application tree.symbol != null && tree.symbol.isTermMacro && // of a macro !tree.attachments.get[SuppressMacroExpansionAttachment.type].isDefined) macroExpand(this, tree, mode, pt) - else if (inAllModes(mode, PATTERNmode | FUNmode)) + else if (mode.inAll(PATTERNmode | FUNmode)) adaptConstrPattern() else if (shouldInsertApply(tree)) insertApply() - else if (!context.undetparams.isEmpty && !inPolyMode(mode)) { // (9) - assert(!inHKMode(mode), modeString(mode)) //@M - if (inExprModeButNot(mode, FUNmode) && pt.typeSymbol == UnitClass) + else if (!context.undetparams.isEmpty && !mode.inPolyMode) { // (9) + assert(!mode.inHKMode, mode) //@M + if (mode.inExprModeButNot(FUNmode) && pt.typeSymbol == UnitClass) instantiateExpectingUnit(tree, mode) else instantiate(tree, mode, pt) @@ -1095,7 +1096,7 @@ trait Typers extends Modes with Adaptations with Tags { tree } else { def fallBack: Tree = { - if (inPatternMode(mode)) { + if (mode.inPatternMode) { if ((tree.symbol ne null) && tree.symbol.isModule) inferModulePattern(tree, pt) if (isPopulated(tree.tpe, approximateAbstracts(pt))) @@ -1104,7 +1105,7 @@ trait Typers extends Modes with Adaptations with Tags { val tree1 = constfold(tree, pt) // (10) (11) if (tree1.tpe <:< pt) adapt(tree1, mode, pt, original) else { - if (inExprModeButNot(mode, FUNmode)) { + if (mode.inExprModeButNot(FUNmode)) { pt.dealias match { case TypeRef(_, sym, _) => // note: was if (pt.typeSymbol == UnitClass) but this leads to a potentially @@ -1212,7 +1213,7 @@ trait Typers extends Modes with Adaptations with Tags { } } - def instantiate(tree: Tree, mode: Int, pt: Type): Tree = { + def instantiate(tree: Tree, mode: Mode, pt: Type): Tree = { inferExprInstance(tree, context.extractUndetparams(), pt) adapt(tree, mode, pt) } @@ -1220,7 +1221,7 @@ trait Typers extends Modes with Adaptations with Tags { * with expected type Unit, but if that fails, try again with pt = WildcardType * and discard the expression. */ - def instantiateExpectingUnit(tree: Tree, mode: Int): Tree = { + def instantiateExpectingUnit(tree: Tree, mode: Mode): Tree = { val savedUndetparams = context.undetparams silent(_.instantiate(tree, mode, UnitClass.tpe)) orElse { _ => context.undetparams = savedUndetparams @@ -1294,7 +1295,7 @@ trait Typers extends Modes with Adaptations with Tags { * a method `name`. If that's ambiguous try taking arguments into * account using `adaptToArguments`. */ - def adaptToMemberWithArgs(tree: Tree, qual: Tree, name: Name, mode: Int, reportAmbiguous: Boolean, saveErrors: Boolean): Tree = { + def adaptToMemberWithArgs(tree: Tree, qual: Tree, name: Name, mode: Mode, reportAmbiguous: Boolean, saveErrors: Boolean): Tree = { def onError(reportError: => Tree): Tree = context.tree match { case Apply(tree1, args) if (tree1 eq tree) && args.nonEmpty => ( silent (_.typedArgs(args, mode)) @@ -2296,7 +2297,7 @@ trait Typers extends Modes with Adaptations with Tags { } } - def typedBlock(block: Block, mode: Int, pt: Type): Block = { + def typedBlock(block: Block, mode: Mode, pt: Type): Block = { val syntheticPrivates = new ListBuffer[Symbol] try { namer.enterSyms(block.stats) @@ -2358,7 +2359,7 @@ trait Typers extends Modes with Adaptations with Tags { case _ => stat::Nil }) val stats2 = typedStats(stats1, context.owner) - val expr1 = typed(block.expr, mode & ~(FUNmode | QUALmode), pt) + val expr1 = typed(block.expr, mode &~ (FUNmode | QUALmode), pt) treeCopy.Block(block, stats2, expr1) .setType(if (treeInfo.isExprSafeToInline(block)) expr1.tpe else expr1.tpe.deconst) } finally { @@ -2429,13 +2430,13 @@ trait Typers extends Modes with Adaptations with Tags { newTyper(context.makeNewScope(cdef, context.owner)).typedCase(cdef, pattp, pt) } - def adaptCase(cdef: CaseDef, mode: Int, tpe: Type): CaseDef = deriveCaseDef(cdef)(adapt(_, mode, tpe)) + def adaptCase(cdef: CaseDef, mode: Mode, tpe: Type): CaseDef = deriveCaseDef(cdef)(adapt(_, mode, tpe)) def ptOrLub(tps: List[Type], pt: Type ) = if (isFullyDefined(pt)) (pt, false) else weakLub(tps map (_.deconst)) def ptOrLubPacked(trees: List[Tree], pt: Type) = if (isFullyDefined(pt)) (pt, false) else weakLub(trees map (c => packedType(c, context.owner).deconst)) // takes untyped sub-trees of a match and type checks them - def typedMatch(selector: Tree, cases: List[CaseDef], mode: Int, pt: Type, tree: Tree = EmptyTree): Match = { + def typedMatch(selector: Tree, cases: List[CaseDef], mode: Mode, pt: Type, tree: Tree = EmptyTree): Match = { val selector1 = checkDead(typed(selector, EXPRmode | BYVALmode, WildcardType)) val selectorTp = packCaptured(selector1.tpe.widen).skolemizeExistential(context.owner, selector) val casesTyped = typedCases(cases, selectorTp, pt) @@ -2448,7 +2449,7 @@ trait Typers extends Modes with Adaptations with Tags { } // match has been typed -- virtualize it during type checking so the full context is available - def virtualizedMatch(match_ : Match, mode: Int, pt: Type) = { + def virtualizedMatch(match_ : Match, mode: Mode, pt: Type) = { import patmat.{ vpmName, PureMatchTranslator } // TODO: add fallback __match sentinel to predef @@ -2466,7 +2467,7 @@ trait Typers extends Modes with Adaptations with Tags { // Match(EmptyTree, cases) ==> new PartialFunction { def apply<OrElse>(params) = `translateMatch('`(param1,...,paramN)` match { cases }')` } // for fresh params, the selector of the match we'll translated simply gathers those in a tuple // NOTE: restricted to PartialFunction -- leave Function trees if the expected type does not demand a partial function - class MatchFunTyper(tree: Tree, cases: List[CaseDef], mode: Int, pt0: Type) { + class MatchFunTyper(tree: Tree, cases: List[CaseDef], mode: Mode, pt0: Type) { // TODO: remove FunctionN support -- this is currently designed so that it can emit FunctionN and PartialFunction subclasses // however, we should leave Function nodes until Uncurry so phases after typer can still detect normal Function trees // we need to synthesize PartialFunction impls, though, to avoid nastiness in Uncurry in transforming&duplicating generated pattern matcher trees @@ -2616,7 +2617,7 @@ trait Typers extends Modes with Adaptations with Tags { } // Function(params, Match(sel, cases)) ==> new <Partial>Function { def apply<OrElse>(params) = `translateMatch('sel match { cases }')` } - class MatchFunTyperBetaReduced(fun: Function, sel: Tree, cases: List[CaseDef], mode: Int, pt: Type) extends MatchFunTyper(fun, cases, mode, pt) { + class MatchFunTyperBetaReduced(fun: Function, sel: Tree, cases: List[CaseDef], mode: Mode, pt: Type) extends MatchFunTyper(fun, cases, mode, pt) { override def deriveFormals = fun.vparams map { p => if(p.tpt.tpe == null) typedType(p.tpt).tpe else p.tpt.tpe } @@ -2629,7 +2630,7 @@ trait Typers extends Modes with Adaptations with Tags { override def mkSel(params: List[Symbol]) = sel.duplicate } - private def typedFunction(fun: Function, mode: Int, pt: Type): Tree = { + private def typedFunction(fun: Function, mode: Mode, pt: Type): Tree = { val numVparams = fun.vparams.length if (numVparams > definitions.MaxFunctionArity) return MaxFunctionArityError(fun) @@ -2654,7 +2655,7 @@ trait Typers extends Modes with Adaptations with Tags { else { fun match { case etaExpansion(vparams, fn, args) => - silent(_.typed(fn, forFunMode(mode), pt)) filter (_ => context.undetparams.isEmpty) map { fn1 => + silent(_.typed(fn, mode.forFunMode, pt)) filter (_ => context.undetparams.isEmpty) map { fn1 => // if context,undetparams is not empty, the function was polymorphic, // so we need the missing arguments to infer its type. See #871 //println("typing eta "+fun+":"+fn1.tpe+"/"+context.undetparams) @@ -2859,14 +2860,14 @@ trait Typers extends Modes with Adaptations with Tags { } } - def typedArg(arg: Tree, mode: Int, newmode: Int, pt: Type): Tree = { - val typedMode = onlyStickyModes(mode) | newmode - val t = withCondConstrTyper((mode & SCCmode) != 0)(_.typed(arg, typedMode, pt)) + def typedArg(arg: Tree, mode: Mode, newmode: Mode, pt: Type): Tree = { + val typedMode = mode.onlySticky | newmode + val t = withCondConstrTyper((mode & SCCmode) != NOmode)(_.typed(arg, typedMode, pt)) checkDead.inMode(typedMode, t) } - def typedArgs(args: List[Tree], mode: Int) = - args mapConserve (arg => typedArg(arg, mode, 0, WildcardType)) + def typedArgs(args: List[Tree], mode: Mode) = + args mapConserve (arg => typedArg(arg, mode, NOmode, WildcardType)) /** Type trees in `args0` against corresponding expected type in `adapted0`. * @@ -2876,8 +2877,8 @@ trait Typers extends Modes with Adaptations with Tags { * * (docs reverse-engineered -- AM) */ - def typedArgs(args0: List[Tree], mode: Int, formals0: List[Type], adapted0: List[Type]): List[Tree] = { - val sticky = onlyStickyModes(mode) + def typedArgs(args0: List[Tree], mode: Mode, formals0: List[Type], adapted0: List[Type]): List[Tree] = { + val sticky = mode.onlySticky def loop(args: List[Tree], formals: List[Type], adapted: List[Type]): List[Tree] = { if (args.isEmpty || adapted.isEmpty) Nil else { @@ -2885,7 +2886,7 @@ trait Typers extends Modes with Adaptations with Tags { val isVarArgs = formals.isEmpty || formals.tail.isEmpty && isRepeatedParamType(formals.head) val typedMode = sticky | ( if (isVarArgs) STARmode | BYVALmode - else if (isByNameParamType(formals.head)) 0 + else if (isByNameParamType(formals.head)) NOmode else BYVALmode ) var tree = typedArg(args.head, mode, typedMode, adapted.head) @@ -2937,7 +2938,7 @@ trait Typers extends Modes with Adaptations with Tags { } } - def doTypedApply(tree: Tree, fun0: Tree, args: List[Tree], mode: Int, pt: Type): Tree = { + def doTypedApply(tree: Tree, fun0: Tree, args: List[Tree], mode: Mode, pt: Type): Tree = { // TODO_NMT: check the assumption that args nonEmpty def duplErrTree = setError(treeCopy.Apply(tree, fun0, args)) def duplErrorTree(err: AbsTypeError) = { issue(err); duplErrTree } @@ -2979,7 +2980,7 @@ trait Typers extends Modes with Adaptations with Tags { if (sym1 != NoSymbol) sym = sym1 } if (sym == NoSymbol) fun - else adapt(fun setSymbol sym setType pre.memberType(sym), forFunMode(mode), WildcardType) + else adapt(fun setSymbol sym setType pre.memberType(sym), mode.forFunMode, WildcardType) } else fun } @@ -3012,7 +3013,7 @@ trait Typers extends Modes with Adaptations with Tags { setError(tree) else { inferMethodAlternative(fun, undetparams, argtpes.toList, pt) - doTypedApply(tree, adapt(fun, forFunMode(mode), WildcardType), args1, mode, pt) + doTypedApply(tree, adapt(fun, mode.forFunMode, WildcardType), args1, mode, pt) } } handleOverloaded @@ -3037,7 +3038,7 @@ trait Typers extends Modes with Adaptations with Tags { // Depending on user options, may warn or error here if // a Unit or tuple was inserted. Some(t) filter (tupledTree => - !inExprModeButNot(mode, FUNmode) + !mode.inExprModeButNot(FUNmode) || tupledTree.symbol == null || checkValidAdaptation(tupledTree, args) ) @@ -3060,7 +3061,7 @@ trait Typers extends Modes with Adaptations with Tags { } if (mt.isErroneous) duplErrTree - else if (inPatternMode(mode)) { + else if (mode.inPatternMode) { // #2064 duplErrorTree(WrongNumberOfArgsError(tree, fun)) } else if (lencmp > 0) { @@ -3157,7 +3158,7 @@ trait Typers extends Modes with Adaptations with Tags { // precise(foo) : foo.type => foo.type val restpe = mt.resultType(args1 map (arg => gen.stableTypeFor(arg) getOrElse arg.tpe)) def ifPatternSkipFormals(tp: Type) = tp match { - case MethodType(_, rtp) if (inPatternMode(mode)) => rtp + case MethodType(_, rtp) if (mode.inPatternMode) => rtp case _ => tp } @@ -3181,7 +3182,7 @@ trait Typers extends Modes with Adaptations with Tags { doTypedApply(tree, fun, args, mode, pt) } else { def handlePolymorphicCall = { - assert(!inPatternMode(mode), modeString(mode)) // this case cannot arise for patterns + assert(!mode.inPatternMode, mode) // this case cannot arise for patterns val lenientTargs = protoTypeArgs(tparams, formals, mt.resultApprox, pt) val strictTargs = map2(lenientTargs, tparams)((targ, tparam) => if (targ == WildcardType) tparam.tpeHK else targ) @@ -3222,7 +3223,7 @@ trait Typers extends Modes with Adaptations with Tags { if (!tree.isErrorTyped) setError(tree) else tree // @H change to setError(treeCopy.Apply(tree, fun, args)) - case otpe if inPatternMode(mode) && unapplyMember(otpe).exists => + case otpe if mode.inPatternMode && unapplyMember(otpe).exists => doTypedUnapply(tree, fun0, fun, args, mode, pt) case _ => @@ -3230,7 +3231,7 @@ trait Typers extends Modes with Adaptations with Tags { } } - def doTypedUnapply(tree: Tree, fun0: Tree, fun: Tree, args: List[Tree], mode: Int, pt: Type): Tree = { + def doTypedUnapply(tree: Tree, fun0: Tree, fun: Tree, args: List[Tree], mode: Mode, pt: Type): Tree = { def duplErrTree = setError(treeCopy.Apply(tree, fun0, args)) def duplErrorTree(err: AbsTypeError) = { issue(err); duplErrTree } @@ -3354,7 +3355,7 @@ trait Typers extends Modes with Adaptations with Tags { * * @param annClass the expected annotation class */ - def typedAnnotation(ann: Tree, mode: Int = EXPRmode, selfsym: Symbol = NoSymbol, annClass: Symbol = AnnotationClass, requireJava: Boolean = false): AnnotationInfo = { + def typedAnnotation(ann: Tree, mode: Mode = EXPRmode, selfsym: Symbol = NoSymbol, annClass: Symbol = AnnotationClass, requireJava: Boolean = false): AnnotationInfo = { var hasError: Boolean = false val pending = ListBuffer[AbsTypeError]() @@ -3399,7 +3400,7 @@ trait Typers extends Modes with Adaptations with Tags { // use of Array.apply[T: ClassTag](xs: T*): Array[T] // and Array.apply(x: Int, xs: Int*): Array[Int] (and similar) case Apply(fun, args) => - val typedFun = typed(fun, forFunMode(mode), WildcardType) + val typedFun = typed(fun, mode.forFunMode, WildcardType) if (typedFun.symbol.owner == ArrayModule.moduleClass && typedFun.symbol.name == nme.apply) pt match { case TypeRef(_, ArrayClass, targ :: _) => @@ -3443,7 +3444,7 @@ trait Typers extends Modes with Adaptations with Tags { val res = if (fun.isErroneous) ErroneousAnnotation else { - val typedFun @ Select(New(tpt), _) = typed(fun, forFunMode(mode), WildcardType) + val typedFun @ Select(New(tpt), _) = typed(fun, mode.forFunMode, WildcardType) val annType = tpt.tpe if (typedFun.isErroneous) ErroneousAnnotation @@ -3733,7 +3734,7 @@ trait Typers extends Modes with Adaptations with Tags { if (!checkClassType(tpt) && noGen) tpt else atPos(tree.pos)(gen.mkClassOf(tpt.tpe)) - protected def typedExistentialTypeTree(tree: ExistentialTypeTree, mode: Int): Tree = { + protected def typedExistentialTypeTree(tree: ExistentialTypeTree, mode: Mode): Tree = { for (wc <- tree.whereClauses) if (wc.symbol == NoSymbol) { namer.enterSym(wc); wc.symbol setFlag EXISTENTIAL } else context.scope enter wc.symbol @@ -3748,7 +3749,7 @@ trait Typers extends Modes with Adaptations with Tags { } // lifted out of typed1 because it's needed in typedImplicit0 - protected def typedTypeApply(tree: Tree, mode: Int, fun: Tree, args: List[Tree]): Tree = fun.tpe match { + protected def typedTypeApply(tree: Tree, mode: Mode, fun: Tree, args: List[Tree]): Tree = fun.tpe match { case OverloadedType(pre, alts) => inferPolyAlternatives(fun, args map (_.tpe)) val tparams = fun.symbol.typeParams //@M TODO: fun.symbol.info.typeParams ? (as in typedAppliedTypeTree) @@ -3837,7 +3838,7 @@ trait Typers extends Modes with Adaptations with Tags { // else false } - def typedNamedApply(orig: Tree, fun: Tree, args: List[Tree], mode: Int, pt: Type): Tree = { + def typedNamedApply(orig: Tree, fun: Tree, args: List[Tree], mode: Mode, pt: Type): Tree = { def argToBinding(arg: Tree): Tree = arg match { case AssignOrNamedArg(Ident(name), rhs) => gen.mkTuple(List(CODE.LIT(name.toString), rhs)) case _ => gen.mkTuple(List(CODE.LIT(""), arg)) @@ -3922,10 +3923,10 @@ trait Typers extends Modes with Adaptations with Tags { println(s) } - def typed1(tree: Tree, mode: Int, pt: Type): Tree = { - def isPatternMode = inPatternMode(mode) - def inPatternConstructor = inAllModes(mode, PATTERNmode | FUNmode) - def isQualifierMode = (mode & QUALmode) != 0 + def typed1(tree: Tree, mode: Mode, pt: Type): Tree = { + def isPatternMode = mode.inPatternMode + def inPatternConstructor = mode.inAll(PATTERNmode | FUNmode) + def isQualifierMode = mode.inAll(QUALmode) // Lookup in the given class using the root mirror. def lookupInOwner(owner: Symbol, name: Name): Symbol = @@ -3947,7 +3948,7 @@ trait Typers extends Modes with Adaptations with Tags { val ann = atd.annot val arg1 = typed(atd.arg, mode, pt) /** mode for typing the annotation itself */ - val annotMode = mode & ~TYPEmode | EXPRmode + val annotMode = (mode &~ TYPEmode) | EXPRmode def resultingTypeTree(tpe: Type) = { // we need symbol-ful originals for reification @@ -4049,7 +4050,7 @@ trait Typers extends Modes with Adaptations with Tags { else context.owner.newValue(name, tree.pos) if (name != nme.WILDCARD) { - if ((mode & ALTmode) != 0) VariableInPatternAlternativeError(tree) + if (mode.inAll(ALTmode)) VariableInPatternAlternativeError(tree) namer.enterInScope(sym) } @@ -4276,7 +4277,7 @@ trait Typers extends Modes with Adaptations with Tags { UnderscoreEtaError(expr1) } - def tryTypedArgs(args: List[Tree], mode: Int): Option[List[Tree]] = { + def tryTypedArgs(args: List[Tree], mode: Mode): Option[List[Tree]] = { val c = context.makeSilent(false) c.retyping = true try { @@ -4356,7 +4357,7 @@ trait Typers extends Modes with Adaptations with Tags { val stableApplication = (fun.symbol ne null) && fun.symbol.isMethod && fun.symbol.isStable if (stableApplication && isPatternMode) { // treat stable function applications f() as expressions. - typed1(tree, mode & ~PATTERNmode | EXPRmode, pt) + typed1(tree, (mode &~ PATTERNmode) | EXPRmode, pt) } else { val funpt = if (isPatternMode) pt else WildcardType val appStart = if (Statistics.canEnable) Statistics.startTimer(failedApplyNanos) else null @@ -4379,9 +4380,9 @@ trait Typers extends Modes with Adaptations with Tags { reportError } } - silent(_.typed(fun, forFunMode(mode), funpt), - if ((mode & EXPRmode) != 0) false else context.ambiguousErrors, - if ((mode & EXPRmode) != 0) tree else context.tree) match { + silent(_.typed(fun, mode.forFunMode, funpt), + if (mode.inExprMode) false else context.ambiguousErrors, + if (mode.inExprMode) tree else context.tree) match { case SilentResultValue(fun1) => val fun2 = if (stableApplication) stabilizeFun(fun1, mode, pt) else fun1 if (Statistics.canEnable) Statistics.incCounter(typedApplyCount) @@ -4521,7 +4522,7 @@ trait Typers extends Modes with Adaptations with Tags { val owntype = ( if (!mix.isEmpty) findMixinSuper(clazz.tpe) - else if ((mode & SUPERCONSTRmode) != 0) clazz.info.firstParent + else if (mode.inAll(SUPERCONSTRmode)) clazz.info.firstParent else intersectionType(clazz.info.parents) ) treeCopy.Super(tree, qual1, mix) setType SuperType(clazz.thisType, owntype) @@ -4565,7 +4566,7 @@ trait Typers extends Modes with Adaptations with Tags { // symbol not found? --> try to convert implicitly to a type that does have the required // member. Added `| PATTERNmode` to allow enrichment in patterns (so we can add e.g., an // xml member to StringContext, which in turn has an unapply[Seq] method) - if (name != nme.CONSTRUCTOR && inExprModeOr(mode, PATTERNmode)) { + if (name != nme.CONSTRUCTOR && mode.inExprModeOr(PATTERNmode)) { val qual1 = adaptToMemberWithArgs(tree, qual, name, mode, true, true) if ((qual1 ne qual) && !qual1.isErrorTyped) return typed(treeCopy.Select(tree, qual1, name), mode, pt) @@ -4738,7 +4739,7 @@ trait Typers extends Modes with Adaptations with Tags { setError(tree) } // ignore current variable scope in patterns to enforce linearity - val startContext = if (inNoModes(mode, PATTERNmode | TYPEPATmode)) context else context.outer + val startContext = if (mode.inNone(PATTERNmode | TYPEPATmode)) context else context.outer val nameLookup = tree.symbol match { case NoSymbol => startContext.lookupSymbol(name, qualifies) case sym => LookupSucceeded(EmptyTree, sym) @@ -4774,8 +4775,8 @@ trait Typers extends Modes with Adaptations with Tags { def typedIdentOrWildcard(tree: Ident) = { val name = tree.name if (Statistics.canEnable) Statistics.incCounter(typedIdentCount) - if ((name == nme.WILDCARD && (mode & (PATTERNmode | FUNmode)) == PATTERNmode) || - (name == tpnme.WILDCARD && (mode & TYPEmode) != 0)) + if ((name == nme.WILDCARD && mode.inPatternNotFunMode) || + (name == tpnme.WILDCARD && mode.inAll(TYPEmode))) tree setType makeFullyDefined(pt) else typedIdent(tree, name) @@ -4898,7 +4899,7 @@ trait Typers extends Modes with Adaptations with Tags { } def typedStar(tree: Star) = { - if ((mode & STARmode) == 0 && !isPastTyper) + if (mode.inNone(STARmode) && !isPastTyper) StarPatternWithVarargParametersError(tree) treeCopy.Star(tree, typed(tree.elem, mode, pt)) setType makeFullyDefined(pt) } @@ -4958,7 +4959,7 @@ trait Typers extends Modes with Adaptations with Tags { } case Ident(tpnme.WILDCARD_STAR) => - val exprTyped = typed(expr, onlyStickyModes(mode), WildcardType) + val exprTyped = typed(expr, mode.onlySticky, WildcardType) def subArrayType(pt: Type) = if (isPrimitiveValueClass(pt.typeSymbol) || !isFullyDefined(pt)) arrayType(pt) else { @@ -4967,8 +4968,8 @@ trait Typers extends Modes with Adaptations with Tags { } val (exprAdapted, baseClass) = exprTyped.tpe.typeSymbol match { - case ArrayClass => (adapt(exprTyped, onlyStickyModes(mode), subArrayType(pt)), ArrayClass) - case _ => (adapt(exprTyped, onlyStickyModes(mode), seqType(pt)), SeqClass) + case ArrayClass => (adapt(exprTyped, mode.onlySticky, subArrayType(pt)), ArrayClass) + case _ => (adapt(exprTyped, mode.onlySticky, seqType(pt)), SeqClass) } exprAdapted.tpe.baseType(baseClass) match { case TypeRef(_, _, List(elemtp)) => @@ -4979,7 +4980,7 @@ trait Typers extends Modes with Adaptations with Tags { case _ => val tptTyped = typedType(tpt, mode) - val exprTyped = typed(expr, onlyStickyModes(mode), tptTyped.tpe.deconst) + val exprTyped = typed(expr, mode.onlySticky, tptTyped.tpe.deconst) val treeTyped = treeCopy.Typed(tree, exprTyped, tptTyped) if (isPatternMode) { @@ -5011,7 +5012,7 @@ trait Typers extends Modes with Adaptations with Tags { //val undets = context.undetparams // @M: fun is typed in TAPPmode because it is being applied to its actual type parameters - val fun1 = typed(fun, forFunMode(mode) | TAPPmode, WildcardType) + val fun1 = typed(fun, mode.forFunMode | TAPPmode, WildcardType) val tparams = fun1.symbol.typeParams //@M TODO: val undets_fun = context.undetparams ? @@ -5164,7 +5165,7 @@ trait Typers extends Modes with Adaptations with Tags { } } - def typed(tree: Tree, mode: Int, pt: Type): Tree = { + def typed(tree: Tree, mode: Mode, pt: Type): Tree = { lastTreeToTyper = tree indentTyping() @@ -5184,7 +5185,7 @@ trait Typers extends Modes with Adaptations with Tags { "undetparams" -> context.undetparams, "implicitsEnabled" -> context.implicitsEnabled, "enrichmentEnabled" -> context.enrichmentEnabled, - "mode" -> modeString(mode), + "mode" -> mode, "silent" -> context.bufferErrors, "context.owner" -> context.owner ) @@ -5247,7 +5248,7 @@ trait Typers extends Modes with Adaptations with Tags { ret } - def typedPos(pos: Position, mode: Int, pt: Type)(tree: Tree) = typed(atPos(pos)(tree), mode, pt) + def typedPos(pos: Position, mode: Mode, pt: Type)(tree: Tree) = typed(atPos(pos)(tree), mode, pt) def typedPos(pos: Position)(tree: Tree) = typed(atPos(pos)(tree)) // TODO: see if this formulation would impose any penalty, since // it makes for a lot less casting. @@ -5261,13 +5262,13 @@ trait Typers extends Modes with Adaptations with Tags { /** Types qualifier `tree` of a select node. * E.g. is tree occurs in a context like `tree.m`. */ - def typedQualifier(tree: Tree, mode: Int, pt: Type): Tree = + def typedQualifier(tree: Tree, mode: Mode, pt: Type): Tree = typed(tree, EXPRmode | QUALmode | POLYmode | mode & TYPEPATmode, pt) // TR: don't set BYVALmode, since qualifier might end up as by-name param to an implicit /** Types qualifier `tree` of a select node. * E.g. is tree occurs in a context like `tree.m`. */ - def typedQualifier(tree: Tree, mode: Int): Tree = + def typedQualifier(tree: Tree, mode: Mode): Tree = typedQualifier(tree, mode, WildcardType) def typedQualifier(tree: Tree): Tree = typedQualifier(tree, NOmode, WildcardType) @@ -5300,23 +5301,23 @@ trait Typers extends Modes with Adaptations with Tags { } /** Types a (fully parameterized) type tree */ - def typedType(tree: Tree, mode: Int): Tree = - typed(tree, forTypeMode(mode), WildcardType) + def typedType(tree: Tree, mode: Mode): Tree = + typed(tree, mode.forTypeMode, WildcardType) /** Types a (fully parameterized) type tree */ def typedType(tree: Tree): Tree = typedType(tree, NOmode) /** Types a higher-kinded type tree -- pt denotes the expected kind*/ - def typedHigherKindedType(tree: Tree, mode: Int, pt: Type): Tree = + def typedHigherKindedType(tree: Tree, mode: Mode, pt: Type): Tree = if (pt.typeParams.isEmpty) typedType(tree, mode) // kind is known and it's * else typed(tree, HKmode, pt) - def typedHigherKindedType(tree: Tree, mode: Int): Tree = + def typedHigherKindedType(tree: Tree, mode: Mode): Tree = typed(tree, HKmode, WildcardType) /** Types a type constructor tree used in a new or supertype */ - def typedTypeConstructor(tree: Tree, mode: Int): Tree = { - val result = typed(tree, forTypeMode(mode) | FUNmode, WildcardType) + def typedTypeConstructor(tree: Tree, mode: Mode): Tree = { + val result = typed(tree, mode.forTypeMode | FUNmode, WildcardType) // get rid of type aliases for the following check (#1241) result.tpe.dealias match { @@ -5373,7 +5374,7 @@ trait Typers extends Modes with Adaptations with Tags { case None => op } - def transformedOrTyped(tree: Tree, mode: Int, pt: Type): Tree = transformed.get(tree) match { + def transformedOrTyped(tree: Tree, mode: Mode, pt: Type): Tree = transformed.get(tree) match { case Some(tree1) => transformed -= tree; tree1 case None => typed(tree, mode, pt) } diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 834f5436dc..7b065e7cf6 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -1,6 +1,7 @@ package scala.tools package reflect +import scala.tools.nsc.EXPRmode import scala.tools.nsc.reporters._ import scala.tools.nsc.CompilerCommand import scala.tools.nsc.io.VirtualDirectory @@ -163,7 +164,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => transformDuringTyper(expr, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled)( (currentTyper, expr) => { trace("typing (implicit views = %s, macros = %s): ".format(!withImplicitViewsDisabled, !withMacrosDisabled))(showAttributed(expr, true, true, settings.Yshowsymkinds.value)) - currentTyper.silent(_.typed(expr, analyzer.EXPRmode, pt)) match { + currentTyper.silent(_.typed(expr, EXPRmode, pt)) match { case analyzer.SilentResultValue(result) => trace("success: ")(showAttributed(result, true, true, settings.Yshowsymkinds.value)) result diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala index cf5b1fa2c4..600b51f376 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala @@ -2,11 +2,10 @@ package scala.tools.selectivecps -import scala.tools.nsc.Global -import scala.tools.nsc.typechecker.Modes +import scala.tools.nsc.{ Global, Mode } import scala.tools.nsc.MissingRequirementError -abstract class CPSAnnotationChecker extends CPSUtils with Modes { +abstract class CPSAnnotationChecker extends CPSUtils { val global: Global import global._ import definitions._ @@ -117,14 +116,14 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { bounds } - override def canAdaptAnnotations(tree: Tree, mode: Int, pt: Type): Boolean = { + override def canAdaptAnnotations(tree: Tree, mode: Mode, pt: Type): Boolean = { if (!cpsEnabled) return false - vprintln("can adapt annotations? " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt) + vprintln("can adapt annotations? " + tree + " / " + tree.tpe + " / " + mode + " / " + pt) val annots1 = cpsParamAnnotation(tree.tpe) val annots2 = cpsParamAnnotation(pt) - if ((mode & global.analyzer.PATTERNmode) != 0) { + if (mode.inPatternMode) { //println("can adapt pattern annotations? " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt) if (!annots1.isEmpty) { return true @@ -133,7 +132,7 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { /* // not precise enough -- still relying on addAnnotations to remove things from ValDef symbols - if ((mode & global.analyzer.TYPEmode) != 0 && (mode & global.analyzer.BYVALmode) != 0) { + if ((mode & TYPEmode) != 0 && (mode & BYVALmode) != 0) { if (!annots1.isEmpty) { return true } @@ -142,16 +141,16 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { /* this interferes with overloading resolution - if ((mode & global.analyzer.BYVALmode) != 0 && tree.tpe <:< pt) { + if ((mode & BYVALmode) != 0 && tree.tpe <:< pt) { vprintln("already compatible, can't adapt further") return false } */ - if ((mode & global.analyzer.EXPRmode) != 0) { + if (mode.inExprMode) { if ((annots1 corresponds annots2)(_.atp <:< _.atp)) { vprintln("already same, can't adapt further") false - } else if (annots1.isEmpty && !annots2.isEmpty && ((mode & global.analyzer.BYVALmode) == 0)) { + } else if (annots1.isEmpty && !annots2.isEmpty && !mode.inByValMode) { //println("can adapt annotations? " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt) if (!hasPlusMarker(tree.tpe)) { // val base = tree.tpe <:< removeAllCPSAnnotations(pt) @@ -164,10 +163,10 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { true //} } else false - } else if (!hasPlusMarker(tree.tpe) && annots1.isEmpty && !annots2.isEmpty && ((mode & global.analyzer.RETmode) != 0)) { + } else if (!hasPlusMarker(tree.tpe) && annots1.isEmpty && !annots2.isEmpty && mode.inRetMode) { vprintln("checking enclosing method's result type without annotations") tree.tpe <:< pt.withoutAnnotations - } else if (!hasMinusMarker(tree.tpe) && !annots1.isEmpty && ((mode & global.analyzer.BYVALmode) != 0)) { + } else if (!hasMinusMarker(tree.tpe) && !annots1.isEmpty && mode.inByValMode) { val optCpsTypes: Option[(Type, Type)] = cpsParamTypes(tree.tpe) val optExpectedCpsTypes: Option[(Type, Type)] = cpsParamTypes(pt) if (optCpsTypes.isEmpty || optExpectedCpsTypes.isEmpty) { @@ -183,21 +182,21 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { } else false } - override def adaptAnnotations(tree: Tree, mode: Int, pt: Type): Tree = { + override def adaptAnnotations(tree: Tree, mode: Mode, pt: Type): Tree = { if (!cpsEnabled) return tree - vprintln("adapt annotations " + tree + " / " + tree.tpe + " / " + modeString(mode) + " / " + pt) + vprintln("adapt annotations " + tree + " / " + tree.tpe + " / " + mode + " / " + pt) - val patMode = (mode & global.analyzer.PATTERNmode) != 0 - val exprMode = (mode & global.analyzer.EXPRmode) != 0 - val byValMode = (mode & global.analyzer.BYVALmode) != 0 - val retMode = (mode & global.analyzer.RETmode) != 0 + val patMode = mode.inPatternMode + val exprMode = mode.inExprMode + val byValMode = mode.inByValMode + val retMode = mode.inRetMode val annotsTree = cpsParamAnnotation(tree.tpe) val annotsExpected = cpsParamAnnotation(pt) // not sure I rephrased this comment correctly: - // replacing `patMode` in the condition below by `patMode || ((mode & global.analyzer.TYPEmode) != 0 && (mode & global.analyzer.BYVALmode))` + // replacing `patMode` in the condition below by `patMode || ((mode & TYPEmode) != 0 && (mode & BYVALmode))` // doesn't work correctly -- still relying on addAnnotations to remove things from ValDef symbols if (patMode && !annotsTree.isEmpty) tree modifyType removeAllCPSAnnotations else if (exprMode && !byValMode && !hasPlusMarker(tree.tpe) && annotsTree.isEmpty && annotsExpected.nonEmpty) { // shiftUnit diff --git a/src/reflect/scala/reflect/internal/AnnotationCheckers.scala b/src/reflect/scala/reflect/internal/AnnotationCheckers.scala index 5318d3e540..13346d9151 100644 --- a/src/reflect/scala/reflect/internal/AnnotationCheckers.scala +++ b/src/reflect/scala/reflect/internal/AnnotationCheckers.scala @@ -39,14 +39,14 @@ trait AnnotationCheckers { /** Decide whether this annotation checker can adapt a tree * that has an annotated type to the given type tp, taking * into account the given mode (see method adapt in trait Typers).*/ - def canAdaptAnnotations(tree: Tree, mode: Int, pt: Type): Boolean = false + def canAdaptAnnotations(tree: Tree, mode: Mode, pt: Type): Boolean = false /** Adapt a tree that has an annotated type to the given type tp, * taking into account the given mode (see method adapt in trait Typers). * An implementation cannot rely on canAdaptAnnotations being called * before. If the implementing class cannot do the adaptiong, it * should return the tree unchanged.*/ - def adaptAnnotations(tree: Tree, mode: Int, pt: Type): Tree = tree + def adaptAnnotations(tree: Tree, mode: Mode, pt: Type): Tree = tree /** Adapt the type of a return expression. The decision of an annotation checker * whether the type should be adapted is based on the type of the expression @@ -113,7 +113,7 @@ trait AnnotationCheckers { /** Find out whether any annotation checker can adapt a tree * to a given type. Called by Typers.adapt. */ - def canAdaptAnnotations(tree: Tree, mode: Int, pt: Type): Boolean = { + def canAdaptAnnotations(tree: Tree, mode: Mode, pt: Type): Boolean = { annotationCheckers.exists(_.canAdaptAnnotations(tree, mode, pt)) } @@ -121,7 +121,7 @@ trait AnnotationCheckers { * to a given type (called by Typers.adapt). Annotation checkers * that cannot do the adaption should pass the tree through * unchanged. */ - def adaptAnnotations(tree: Tree, mode: Int, pt: Type): Tree = { + def adaptAnnotations(tree: Tree, mode: Mode, pt: Type): Tree = { annotationCheckers.foldLeft(tree)((tree, checker) => checker.adaptAnnotations(tree, mode, pt)) } @@ -129,7 +129,7 @@ trait AnnotationCheckers { /** Let a registered annotation checker adapt the type of a return expression. * Annotation checkers that cannot do the adaptation should simply return * the `default` argument. - * + * * Note that the result is undefined if more than one annotation checker * returns an adapted type which is not a subtype of `default`. */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Modes.scala b/src/reflect/scala/reflect/internal/Mode.scala index e1ee3c482a..850e3b5669 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Modes.scala +++ b/src/reflect/scala/reflect/internal/Mode.scala @@ -3,75 +3,76 @@ * @author Martin Odersky */ -package scala.tools.nsc -package typechecker +package scala.reflect +package internal + +object Mode { + private implicit def liftIntBitsToMode(bits: Int): Mode = apply(bits) + def apply(bits: Int): Mode = new Mode(bits) -/** Mode constants. - */ -trait Modes { /** NOmode, EXPRmode and PATTERNmode are mutually exclusive. */ - final val NOmode = 0x000 - final val EXPRmode = 0x001 - final val PATTERNmode = 0x002 + final val NOmode: Mode = 0x000 + final val EXPRmode: Mode = 0x001 + final val PATTERNmode: Mode = 0x002 /** TYPEmode needs a comment. <-- XXX. */ - final val TYPEmode = 0x004 + final val TYPEmode: Mode = 0x004 /** SCCmode is orthogonal to above. When set we are * in the this or super constructor call of a constructor. */ - final val SCCmode = 0x008 + final val SCCmode: Mode = 0x008 /** FUNmode is orthogonal to above. * When set we are looking for a method or constructor. */ - final val FUNmode = 0x010 + final val FUNmode: Mode = 0x010 /** POLYmode is orthogonal to above. * When set expression types can be polymorphic. */ - final val POLYmode = 0x020 + final val POLYmode: Mode = 0x020 /** QUALmode is orthogonal to above. When set * expressions may be packages and Java statics modules. */ - final val QUALmode = 0x040 + final val QUALmode: Mode = 0x040 /** TAPPmode is set for the function/type constructor * part of a type application. When set we do not decompose PolyTypes. */ - final val TAPPmode = 0x080 + final val TAPPmode: Mode = 0x080 /** SUPERCONSTRmode is set for the super * in a superclass constructor call super.<init>. */ - final val SUPERCONSTRmode = 0x100 + final val SUPERCONSTRmode: Mode = 0x100 /** SNDTRYmode indicates that an application is typed for the 2nd time. * In that case functions may no longer be coerced with implicit views. */ - final val SNDTRYmode = 0x200 + final val SNDTRYmode: Mode = 0x200 /** LHSmode is set for the left-hand side of an assignment. */ - final val LHSmode = 0x400 + final val LHSmode: Mode = 0x400 /** STARmode is set when star patterns are allowed. * (This was formerly called REGPATmode.) */ - final val STARmode = 0x1000 + final val STARmode: Mode = 0x1000 /** ALTmode is set when we are under a pattern alternative. */ - final val ALTmode = 0x2000 + final val ALTmode: Mode = 0x2000 /** HKmode is set when we are typing a higher-kinded type. * adapt should then check kind-arity based on the prototypical type's * kind arity. Type arguments should not be inferred. */ - final val HKmode = 0x4000 // @M: could also use POLYmode | TAPPmode + final val HKmode: Mode = 0x4000 // @M: could also use POLYmode | TAPPmode /** BYVALmode is set when we are typing an expression * that occurs in a by-value position. An expression e1 is in by-value @@ -80,39 +81,17 @@ trait Modes { * arguments or the conditional of an if-then-else clause. * This mode has been added to support continuations. */ - final val BYVALmode = 0x8000 + final val BYVALmode: Mode = 0x8000 /** TYPEPATmode is set when we are typing a type in a pattern. */ - final val TYPEPATmode = 0x10000 + final val TYPEPATmode: Mode = 0x10000 /** RETmode is set when we are typing a return expression. */ - final val RETmode = 0x20000 - - final private val StickyModes = EXPRmode | PATTERNmode | TYPEmode | ALTmode - - final def onlyStickyModes(mode: Int) = - mode & StickyModes - - final def forFunMode(mode: Int) = - mode & (StickyModes | SCCmode) | FUNmode | POLYmode | BYVALmode - - final def forTypeMode(mode: Int) = - if (inAnyMode(mode, PATTERNmode | TYPEPATmode)) TYPEmode | TYPEPATmode - else TYPEmode + final val RETmode: Mode = 0x20000 - final def inAllModes(mode: Int, required: Int) = (mode & required) == required - final def inAnyMode(mode: Int, required: Int) = (mode & required) != 0 - final def inNoModes(mode: Int, prohibited: Int) = (mode & prohibited) == 0 - final def inHKMode(mode: Int) = (mode & HKmode) != 0 - final def inFunMode(mode: Int) = (mode & FUNmode) != 0 - final def inPolyMode(mode: Int) = (mode & POLYmode) != 0 - final def inPatternMode(mode: Int) = (mode & PATTERNmode) != 0 - final def inPatternNotFunMode(mode: Int) = inPatternMode(mode) && !inFunMode(mode) - final def inExprModeOr(mode: Int, others: Int) = (mode & (EXPRmode | others)) != 0 - final def inExprModeButNot(mode: Int, prohibited: Int) = - (mode & (EXPRmode | prohibited)) == EXPRmode + final private val StickyModes: Mode = EXPRmode | PATTERNmode | TYPEmode | ALTmode /** Translates a mask of mode flags into something readable. */ @@ -134,8 +113,37 @@ trait Modes { (1 << 14) -> "HKmode", (1 << 15) -> "BYVALmode", (1 << 16) -> "TYPEPATmode" - ) - def modeString(mode: Int): String = - if (mode == 0) "NOmode" - else (modeNameMap filterKeys (bit => inAllModes(mode, bit))).values mkString " " + ).map({ case (k, v) => Mode(k) -> v }) +} +import Mode._ + +final class Mode private (val bits: Int) extends AnyVal { + def &(other: Mode): Mode = new Mode(bits & other.bits) + def |(other: Mode): Mode = new Mode(bits | other.bits) + def &~(other: Mode): Mode = new Mode(bits & ~(other.bits)) + + def onlySticky = this & Mode.StickyModes + def forFunMode = this & (Mode.StickyModes | SCCmode) | FUNmode | POLYmode | BYVALmode + def forTypeMode = + if (inAny(PATTERNmode | TYPEPATmode)) TYPEmode | TYPEPATmode + else TYPEmode + + def inAll(required: Mode) = (this & required) == required + def inAny(required: Mode) = (this & required) !=NOmode + def inNone(prohibited: Mode) = (this & prohibited) == NOmode + def inHKMode = inAll(HKmode) + def inFunMode = inAll(FUNmode) + def inPolyMode = inAll(POLYmode) + def inPatternMode = inAll(PATTERNmode) + def inExprMode = inAll(EXPRmode) + def inByValMode = inAll(BYVALmode) + def inRetMode = inAll(RETmode) + + def inPatternNotFunMode = inPatternMode && !inFunMode + def inExprModeOr(others: Mode) = inAny(EXPRmode | others) + def inExprModeButNot(prohibited: Mode) = inAll(EXPRmode) && inNone(prohibited) + + override def toString = + if (bits == 0) "NOmode" + else (modeNameMap filterKeys inAll).values.toList.sorted mkString " " } |