From 45d61774eb255416c96e983cdb87960ad6415b74 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sat, 8 Jun 2013 12:04:27 -0700 Subject: Eliminate needless Options. Many of our core types have dedicated sentinels which serve perfectly to communicate "no value", even more perfectly than None. Saving a billion allocations is gravy. --- .../scala/tools/nsc/backend/jvm/GenASM.scala | 8 ++--- .../scala/tools/nsc/symtab/SymbolLoaders.scala | 4 +-- .../nsc/symtab/classfile/ClassfileParser.scala | 15 ++++---- .../scala/tools/nsc/typechecker/Typers.scala | 25 +++++++------- .../scala/reflect/internal/BaseTypeSeqs.scala | 9 +++-- .../reflect/internal/ExistentialsAndSkolems.scala | 6 ++-- src/reflect/scala/reflect/internal/Symbols.scala | 3 ++ src/reflect/scala/reflect/internal/TreeGen.scala | 22 ++++++------ src/reflect/scala/reflect/internal/Types.scala | 40 +++++++++++----------- .../scala/reflect/internal/tpe/GlbLubs.scala | 4 +-- 10 files changed, 69 insertions(+), 67 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 7edcc944e1..19a6e11986 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -1270,9 +1270,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { private def getSuperInterfaces(c: IClass): Array[String] = { // Additional interface parents based on annotations and other cues - def newParentForAttr(attr: Symbol): Option[Symbol] = attr match { - case RemoteAttr => Some(RemoteInterfaceClass) - case _ => None + def newParentForAttr(ann: AnnotationInfo): Symbol = ann.symbol match { + case RemoteAttr => RemoteInterfaceClass + case _ => NoSymbol } /* Drop redundant interfaces (ones which are implemented by some other parent) from the immediate parents. @@ -1295,7 +1295,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { val ps = c.symbol.info.parents val superInterfaces0: List[Symbol] = if(ps.isEmpty) Nil else c.symbol.mixinClasses - val superInterfaces = (superInterfaces0 ++ c.symbol.annotations.flatMap(ann => newParentForAttr(ann.symbol))).distinct + val superInterfaces = existingSymbols(superInterfaces0 ++ c.symbol.annotations.map(newParentForAttr)).distinct if(superInterfaces.isEmpty) EMPTY_STRING_ARRAY else mkArray(minimizeInterfaces(superInterfaces) map javaName) diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index 250feb69bf..fd85bbb169 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -244,9 +244,9 @@ abstract class SymbolLoaders { } class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader with FlagAssigningCompleter { - private object classfileParser extends ClassfileParser { + private object classfileParser extends { val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global - } + } with ClassfileParser protected def description = "class file "+ classfile.toString diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index fb927d15d3..fa7279f6ef 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -39,7 +39,7 @@ abstract class ClassfileParser { protected var isScala: Boolean = _ // does class file describe a scala class? protected var isScalaAnnot: Boolean = _ // does class file describe a scala class with its pickled info in an annotation? protected var isScalaRaw: Boolean = _ // this class file is a scala class with no pickled info - protected var busy: Option[Symbol] = None // lock to detect recursive reads + protected var busy: Symbol = _ // lock to detect recursive reads protected var currentClass: Name = _ // JVM name of the current class protected var classTParams = Map[Name,Symbol]() protected var srcfile0 : Option[AbstractFile] = None @@ -90,16 +90,15 @@ abstract class ClassfileParser { case e: RuntimeException => handleError(e) } @inline private def pushBusy[T](sym: Symbol)(body: => T): T = { - busy match { - case Some(`sym`) => throw new IOException(s"unsatisfiable cyclic dependency in '$sym'") - case Some(sym1) => throw new IOException(s"illegal class file dependency between '$sym' and '$sym1'") - case _ => () - } + if (busy eq sym) + throw new IOException(s"unsatisfiable cyclic dependency in '$sym'") + else if ((busy ne null) && (busy ne NoSymbol)) + throw new IOException(s"illegal class file dependency between '$sym' and '$busy'") - busy = Some(sym) + busy = sym try body catch parseErrorHandler - finally busy = None + finally busy = NoSymbol } @inline private def raiseLoaderLevel[T](body: => T): T = { loaders.parentsLevel += 1 diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index ec6b78f2de..ff4e76efcd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3185,7 +3185,7 @@ trait Typers extends Adaptations with Tags { * to that. This is the last thing which is tried (after * default arguments) */ - def tryTupleApply: Option[Tree] = ( + def tryTupleApply: Tree = ( if (eligibleForTupleConversion(paramTypes, argslen) && !phase.erasedTypes) { val tupleArgs = List(atPos(tree.pos.makeTransparent)(gen.mkTuple(args))) // expected one argument, but got 0 or >1 ==> try applying to tuple @@ -3194,14 +3194,15 @@ trait Typers extends Adaptations with Tags { silent(_.doTypedApply(tree, fun, tupleArgs, mode, pt)) map { t => // Depending on user options, may warn or error here if // a Unit or tuple was inserted. - Some(t) filter (tupledTree => + val keepTree = ( !mode.typingExprNotFun - || tupledTree.symbol == null - || checkValidAdaptation(tupledTree, args) + || t.symbol == null + || checkValidAdaptation(t, args) ) - } orElse { _ => context.undetparams = savedUndetparams ; None } - } - else None + if (keepTree) t else EmptyTree + } orElse { _ => context.undetparams = savedUndetparams ; EmptyTree } + } + else EmptyTree ) /* Treats an application which uses named or default arguments. @@ -3214,7 +3215,7 @@ trait Typers extends Adaptations with Tags { def checkNotMacro() = { if (treeInfo.isMacroApplication(fun)) - tryTupleApply getOrElse duplErrorTree(NamedAndDefaultArgumentsNotSupportedForMacros(tree, fun)) + tryTupleApply orElse duplErrorTree(NamedAndDefaultArgumentsNotSupportedForMacros(tree, fun)) } if (mt.isErroneous) duplErrTree @@ -3222,7 +3223,7 @@ trait Typers extends Adaptations with Tags { // #2064 duplErrorTree(WrongNumberOfArgsError(tree, fun)) } else if (lencmp > 0) { - tryTupleApply getOrElse duplErrorTree(TooManyArgsNamesDefaultsError(tree, fun)) + tryTupleApply orElse duplErrorTree(TooManyArgsNamesDefaultsError(tree, fun)) } else if (lencmp == 0) { // we don't need defaults. names were used, so this application is transformed // into a block (@see transformNamedApplication in NamesDefaults) @@ -3275,7 +3276,7 @@ trait Typers extends Adaptations with Tags { if (!(context.diagnostic contains note)) context.diagnostic = note :: context.diagnostic doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt) } else { - tryTupleApply getOrElse duplErrorTree(NotEnoughArgsError(tree, fun, missing)) + tryTupleApply orElse duplErrorTree(NotEnoughArgsError(tree, fun, missing)) } } } @@ -3311,7 +3312,7 @@ trait Typers extends Adaptations with Tags { // instantiate dependent method types, must preserve singleton types where possible (stableTypeFor) -- example use case: // val foo = "foo"; def precise(x: String)(y: x.type): x.type = {...}; val bar : foo.type = precise(foo)(foo) // precise(foo) : foo.type => foo.type - val restpe = mt.resultType(args1 map (arg => gen.stableTypeFor(arg) getOrElse arg.tpe)) + val restpe = mt.resultType(args1 map (arg => gen stableTypeFor arg orElse arg.tpe)) def ifPatternSkipFormals(tp: Type) = tp match { case MethodType(_, rtp) if (mode.inPatternMode) => rtp case _ => tp @@ -3729,7 +3730,7 @@ trait Typers extends Adaptations with Tags { /** Compute an existential type from raw hidden symbols `syms` and type `tp` */ - def packSymbols(hidden: List[Symbol], tp: Type): Type = global.packSymbols(hidden, tp, Some(context0.owner)) + def packSymbols(hidden: List[Symbol], tp: Type): Type = global.packSymbols(hidden, tp, context0.owner) def isReferencedFrom(ctx: Context, sym: Symbol): Boolean = ( ctx.owner.isTerm && diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala index 368e1cde30..e3498a95a6 100644 --- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala +++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala @@ -66,15 +66,14 @@ trait BaseTypeSeqs { pending += i try { mergePrefixAndArgs(variants, Variance.Contravariant, lubDepth(variants)) match { - case Some(tp0) => + case NoType => typeError("no common type instance of base types "+(variants mkString ", and ")+" exists.") + case tp0 => pending(i) = false elems(i) = tp0 tp0 - case None => - typeError( - "no common type instance of base types "+(variants mkString ", and ")+" exists.") } - } catch { + } + catch { case CyclicInheritance => typeError( "computing the common type instance of base types "+(variants mkString ", and ")+" leads to a cycle.") diff --git a/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala index 6251849182..073f124630 100644 --- a/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala +++ b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala @@ -77,14 +77,14 @@ trait ExistentialsAndSkolems { * also replaced, except for term symbols of an Ident tree, where * only the type of the Ident is changed. */ - final def existentialTransform[T](rawSyms: List[Symbol], tp: Type, rawOwner: Option[Symbol] = None)(creator: (List[Symbol], Type) => T): T = { + final def existentialTransform[T](rawSyms: List[Symbol], tp: Type, rawOwner: Symbol = NoSymbol)(creator: (List[Symbol], Type) => T): T = { val allBounds = existentialBoundsExcludingHidden(rawSyms) val typeParams: List[Symbol] = rawSyms map { sym => val name = sym.name match { case x: TypeName => x case x => tpnme.singletonName(x) } - def rawOwner0 = rawOwner.getOrElse(abort(s"no owner provided for existential transform over raw parameter: $sym")) + def rawOwner0 = rawOwner orElse abort(s"no owner provided for existential transform over raw parameter: $sym") val bound = allBounds(sym) val sowner = if (isRawParameter(sym)) rawOwner0 else sym.owner val quantified = sowner.newExistential(name, sym.pos) @@ -106,7 +106,7 @@ trait ExistentialsAndSkolems { * @param hidden The original type * @param rawOwner The owner for Java raw types. */ - final def packSymbols(hidden: List[Symbol], tp: Type, rawOwner: Option[Symbol] = None): Type = + final def packSymbols(hidden: List[Symbol], tp: Type, rawOwner: Symbol = NoSymbol): Type = if (hidden.isEmpty) tp else existentialTransform(hidden, tp, rawOwner)(existentialAbstraction) } diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index f3cea1fd00..2da9fa1cca 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -3413,6 +3413,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def mapParamss[T](sym: Symbol)(f: Symbol => T): List[List[T]] = mmap(sym.info.paramss)(f) + def existingSymbols(syms: List[Symbol]): List[Symbol] = + syms filter (s => (s ne null) && (s ne NoSymbol)) + /** Return closest enclosing method, unless shadowed by an enclosing class. */ // TODO Move back to ExplicitOuter when the other call site is removed. // no use of closures here in the interest of speed. diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index 6abf344adb..b75fd72526 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -137,20 +137,20 @@ abstract class TreeGen extends macros.TreeBuilder { /** Replaces tree type with a stable type if possible */ def stabilize(tree: Tree): Tree = stableTypeFor(tree) match { - case Some(tp) => tree setType tp - case _ => tree + case NoType => tree + case tp => tree setType tp } /** Computes stable type for a tree if possible */ - def stableTypeFor(tree: Tree): Option[Type] = - if (treeInfo.admitsTypeSelection(tree)) - tree match { - case This(_) => Some(ThisType(tree.symbol)) - case Ident(_) => Some(singleType(tree.symbol.owner.thisType, tree.symbol)) - case Select(qual, _) => Some(singleType(qual.tpe, tree.symbol)) - case _ => None - } - else None + def stableTypeFor(tree: Tree): Type = ( + if (!treeInfo.admitsTypeSelection(tree)) NoType + else tree match { + case This(_) => ThisType(tree.symbol) + case Ident(_) => singleType(tree.symbol.owner.thisType, tree.symbol) + case Select(qual, _) => singleType(qual.tpe, tree.symbol) + case _ => NoType + } + ) /** Builds a reference with stable type to given symbol */ def mkAttributedStableRef(pre: Type, sym: Symbol): Tree = diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index d942c71619..967146a130 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -4380,12 +4380,11 @@ trait Types /** Compute lub (if `variance == Covariant`) or glb (if `variance == Contravariant`) of given list * of types `tps`. All types in `tps` are typerefs or singletypes * with the same symbol. - * Return `Some(x)` if the computation succeeds with result `x`. - * Return `None` if the computation fails. + * Return `x` if the computation succeeds with result `x`. + * Return `NoType` if the computation fails. */ - def mergePrefixAndArgs(tps: List[Type], variance: Variance, depth: Int): Option[Type] = tps match { - case List(tp) => - Some(tp) + def mergePrefixAndArgs(tps: List[Type], variance: Variance, depth: Int): Type = tps match { + case tp :: Nil => tp case TypeRef(_, sym, _) :: rest => val pres = tps map (_.prefix) // prefix normalizes automatically val pre = if (variance.isPositive) lub(pres, depth) else glb(pres, depth) @@ -4397,12 +4396,13 @@ trait Types // if argss contain one value type and some other type, the lub is Object // if argss contain several reference types, the lub is an array over lub of argtypes if (argss exists typeListIsEmpty) { - None // something is wrong: an array without a type arg. - } else { + NoType // something is wrong: an array without a type arg. + } + else { val args = argss map (_.head) - if (args.tail forall (_ =:= args.head)) Some(typeRef(pre, sym, List(args.head))) - else if (args exists (arg => isPrimitiveValueClass(arg.typeSymbol))) Some(ObjectTpe) - else Some(typeRef(pre, sym, List(lub(args)))) + if (args.tail forall (_ =:= args.head)) typeRef(pre, sym, List(args.head)) + else if (args exists (arg => isPrimitiveValueClass(arg.typeSymbol))) ObjectTpe + else typeRef(pre, sym, List(lub(args))) } } else transposeSafe(argss) match { @@ -4411,7 +4411,7 @@ trait Types // catching just in case (shouldn't happen, but also doesn't cost us) // [JZ] It happens: see SI-5683. debuglog(s"transposed irregular matrix!? tps=$tps argss=$argss") - None + NoType case Some(argsst) => val args = map2(sym.typeParams, argsst) { (tparam, as0) => val as = as0.distinct @@ -4442,22 +4442,22 @@ trait Types } } } - if (args contains NoType) None - else Some(existentialAbstraction(capturedParams.toList, typeRef(pre, sym, args))) + if (args contains NoType) NoType + else existentialAbstraction(capturedParams.toList, typeRef(pre, sym, args)) } } catch { - case ex: MalformedType => None + case ex: MalformedType => NoType } case SingleType(_, sym) :: rest => val pres = tps map (_.prefix) val pre = if (variance.isPositive) lub(pres, depth) else glb(pres, depth) - try { - Some(singleType(pre, sym)) - } catch { - case ex: MalformedType => None - } + try singleType(pre, sym) + catch { case ex: MalformedType => NoType } case ExistentialType(tparams, quantified) :: rest => - mergePrefixAndArgs(quantified :: rest, variance, depth) map (existentialAbstraction(tparams, _)) + mergePrefixAndArgs(quantified :: rest, variance, depth) match { + case NoType => NoType + case tpe => existentialAbstraction(tparams, tpe) + } case _ => abort(s"mergePrefixAndArgs($tps, $variance, $depth): unsupported tps") } diff --git a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala index 0a7a2a127c..1d3c6b0f23 100644 --- a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala +++ b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala @@ -125,8 +125,8 @@ private[internal] trait GlbLubs { } val tails = tsBts map (_.tail) mergePrefixAndArgs(elimSub(ts1, depth) map elimHigherOrderTypeParam, Covariant, depth) match { - case Some(tp) => loop(tp :: pretypes, tails) - case _ => loop(pretypes, tails) + case NoType => loop(pretypes, tails) + case tp => loop(tp :: pretypes, tails) } } else { -- cgit v1.2.3