diff options
Diffstat (limited to 'src')
17 files changed, 89 insertions, 85 deletions
diff --git a/src/compiler/scala/reflect/macros/util/Helpers.scala b/src/compiler/scala/reflect/macros/util/Helpers.scala index f12582a3a1..f40c6bb7e6 100644 --- a/src/compiler/scala/reflect/macros/util/Helpers.scala +++ b/src/compiler/scala/reflect/macros/util/Helpers.scala @@ -23,25 +23,27 @@ trait Helpers { * or to streamline creation of the list of macro arguments. */ def transformTypeTagEvidenceParams(macroImplRef: Tree, transform: (Symbol, Symbol) => Symbol): List[List[Symbol]] = { + val MacroContextUniverse = definitions.MacroContextUniverse val treeInfo.MacroImplReference(isBundle, _, macroImpl, _) = macroImplRef val paramss = macroImpl.paramss - if (paramss.isEmpty || paramss.last.isEmpty) return paramss // no implicit parameters in the signature => nothing to do - val rc = - if (isBundle) macroImpl.owner.tpe.member(nme.c) - else { - def cparam = paramss.head.head - if (paramss.head.isEmpty || !(cparam.tpe <:< MacroContextClass.tpe)) return paramss // no context parameter in the signature => nothing to do - cparam - } + val ContextParam = paramss match { + case Nil | _ :+ Nil => NoSymbol // no implicit parameters in the signature => nothing to do + case _ if isBundle => macroImpl.owner.tpe member nme.c + case (cparam :: _) :: _ if cparam.tpe <:< MacroContextClass.tpe => cparam + case _ => NoSymbol // no context parameter in the signature => nothing to do + } def transformTag(param: Symbol): Symbol = param.tpe.dealias match { - case TypeRef(SingleType(SingleType(_, ac), universe), WeakTypeTagClass, targ :: Nil) - if ac == rc && universe == MacroContextUniverse => - transform(param, targ.typeSymbol) - case _ => - param + case TypeRef(SingleType(SingleType(_, ContextParam), MacroContextUniverse), WeakTypeTagClass, targ :: Nil) => transform(param, targ.typeSymbol) + case _ => param + } + ContextParam match { + case NoSymbol => paramss + case _ => + paramss.last map transformTag filter (_.exists) match { + case Nil => paramss.init + case transformed => paramss.init :+ transformed + } } - val transformed = paramss.last map transformTag filter (_ ne NoSymbol) - if (transformed.isEmpty) paramss.init else paramss.init :+ transformed } /** Increases metalevel of the type, i.e. transforms: diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala index caab299635..9c8e13a1a9 100644 --- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala @@ -282,7 +282,7 @@ abstract class NodePrinters { traverseList("[]", "type parameter")(tparams) vparamss match { case Nil => println("Nil") - case Nil :: Nil => println("List(Nil)") + case ListOfNil => println("List(Nil)") case ps :: Nil => printLine("", "1 parameter list") ps foreach traverse diff --git a/src/compiler/scala/tools/nsc/package.scala b/src/compiler/scala/tools/nsc/package.scala index 761fd79358..817a4a5c88 100644 --- a/src/compiler/scala/tools/nsc/package.scala +++ b/src/compiler/scala/tools/nsc/package.scala @@ -23,5 +23,6 @@ package object nsc { type MissingRequirementError = scala.reflect.internal.MissingRequirementError val MissingRequirementError = scala.reflect.internal.MissingRequirementError - val ListOfNil = List(Nil) + @deprecated("Use scala.reflect.internal.util.ListOfNil", "2.11.0") + lazy val ListOfNil = scala.reflect.internal.util.ListOfNil } diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 540b8f6c6c..b2e071579e 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -276,18 +276,16 @@ abstract class ExplicitOuter extends InfoTransform else outerPath(outerSelect(base), from.outerClass, to) } - override def transform(tree: Tree): Tree = { + def sym = tree.symbol val savedOuterParam = outerParam try { tree match { case Template(_, _, _) => outerParam = NoSymbol - case DefDef(_, _, _, vparamss, _, _) => - if (tree.symbol.isClassConstructor && isInner(tree.symbol.owner)) { - outerParam = vparamss.head.head.symbol - assert(outerParam.name startsWith nme.OUTER, outerParam.name) - } + case DefDef(_, _, _, (param :: _) :: _, _, _) if sym.isClassConstructor && isInner(sym.owner) => + outerParam = param.symbol + assert(outerParam.name startsWith nme.OUTER, outerParam.name) case _ => } super.transform(tree) diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala index 45aa1106f0..f7b194a6ca 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala @@ -292,6 +292,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { trait TreesAndTypesDomain extends PropositionalLogic with CheckableTreeAndTypeAnalysis { type Type = global.Type type Tree = global.Tree + import global.definitions.ConstantNull // resets hash consing -- only supposed to be called by TreeMakersToProps def prepareNewAnalysis(): Unit = { Var.resetUniques(); Const.resetUniques() } @@ -320,7 +321,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { val staticTpCheckable: Type = checkableType(staticTp) private[this] var _mayBeNull = false - def registerNull(): Unit = { ensureCanModify(); if (NullTp <:< staticTpCheckable) _mayBeNull = true } + def registerNull(): Unit = { ensureCanModify(); if (ConstantNull <:< staticTpCheckable) _mayBeNull = true } def mayBeNull: Boolean = _mayBeNull // case None => domain is unknown, @@ -568,7 +569,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { object TypeConst extends TypeConstExtractor { def apply(tp: Type) = { - if (tp =:= NullTp) NullConst + if (tp =:= ConstantNull) NullConst else if (tp.isInstanceOf[SingletonType]) ValueConst.fromType(tp) else Const.unique(tp, new TypeConst(tp)) } @@ -577,7 +578,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { // corresponds to a type test that does not imply any value-equality (well, except for outer checks, which we don't model yet) sealed class TypeConst(val tp: Type) extends Const { - assert(!(tp =:= NullTp)) + assert(!(tp =:= ConstantNull)) /*private[this] val id: Int = */ Const.nextTypeId val wideTp = widenToClass(tp) @@ -598,7 +599,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { } def apply(p: Tree) = { val tp = p.tpe.normalize - if (tp =:= NullTp) NullConst + if (tp =:= ConstantNull) NullConst else { val wideTp = widenToClass(tp) @@ -626,16 +627,14 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { } sealed class ValueConst(val tp: Type, val wideTp: Type, override val toString: String) extends Const { // debug.patmat("VC"+(tp, wideTp, toString)) - assert(!(tp =:= NullTp)) // TODO: assert(!tp.isStable) + assert(!(tp =:= ConstantNull)) // TODO: assert(!tp.isStable) /*private[this] val id: Int = */Const.nextValueId def isValue = true } - - lazy val NullTp = ConstantType(Constant(null)) case object NullConst extends Const { - def tp = NullTp - def wideTp = NullTp + def tp = ConstantNull + def wideTp = ConstantNull def isValue = true override def toString = "null" diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala index 8feb87210e..7eb899d9d7 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala @@ -50,7 +50,7 @@ trait TreeAndTypeAnalysis extends Debugging { case UnitClass => Some(List(UnitTpe)) case BooleanClass => - Some((List(ConstantType(Constant(true)), ConstantType(Constant(false))))) + Some(ConstantTrue :: ConstantFalse :: Nil) // TODO case _ if tp.isTupleType => // recurse into component types case modSym: ModuleClassSymbol => Some(List(tp)) @@ -271,9 +271,9 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT case SubstOnlyTreeMaker(_, _) => True case GuardTreeMaker(guard) => guard.tpe match { - case ConstantType(Constant(true)) => True - case ConstantType(Constant(false)) => False - case _ => handleUnknown(tm) + case ConstantTrue => True + case ConstantFalse => False + case _ => handleUnknown(tm) } case ExtractorTreeMaker(_, _, _) | ProductExtractorTreeMaker(_, _) | diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala index ba78438b66..8a04c67582 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala @@ -402,23 +402,15 @@ trait MatchOptimization extends MatchTreeMaking with MatchAnalysis { private def noGuards(cs: List[CaseDef]): Boolean = !cs.exists(isGuardedCase) // must do this before removing guards from cases and collapsing (SI-6011, SI-6048) - private def unreachableCase(cs: List[CaseDef]): Option[CaseDef] = { - var cases = cs - var unreachable: Option[CaseDef] = None - - while (cases.nonEmpty && unreachable.isEmpty) { - val currCase = cases.head - if (isDefault(currCase) && cases.tail.nonEmpty) // subsumed by the `else if` that follows, but faster - unreachable = Some(cases.tail.head) - else if (!isGuardedCase(currCase) || currCase.guard.tpe =:= ConstantType(Constant(true))) - unreachable = cases.tail.find(caseImplies(currCase)) - else if (currCase.guard.tpe =:= ConstantType(Constant(false))) - unreachable = Some(currCase) - - cases = cases.tail + private def unreachableCase(cases: List[CaseDef]): Option[CaseDef] = { + def loop(cases: List[CaseDef]): Option[CaseDef] = cases match { + case head :: next :: _ if isDefault(head) => Some(next) // subsumed by the next case, but faster + case head :: rest if !isGuardedCase(head) || head.guard.tpe =:= ConstantTrue => rest find caseImplies(head) orElse loop(rest) + case head :: _ if head.guard.tpe =:= ConstantFalse => Some(head) + case _ :: rest => loop(rest) + case _ => None } - - unreachable + loop(cases) } // empty list ==> failure diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala index cf26ec3398..317685682d 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala @@ -288,8 +288,8 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { def irrefutableExtractorType(tp: Type): Boolean = tp.resultType.dealias match { case TypeRef(_, SomeClass, _) => true // probably not useful since this type won't be inferred nor can it be written down (yet) - case ConstantType(Constant(true)) => true - case _ => false + case ConstantTrue => true + case _ => false } def unapply(xtm: ExtractorTreeMaker): Option[(Tree, Symbol)] = xtm match { diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala index 114bcba5df..6267585ea8 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala @@ -9,6 +9,7 @@ package scala.tools.nsc.transform.patmat import scala.collection.mutable import scala.reflect.internal.util.Statistics import scala.language.postfixOps +import scala.reflect.internal.util.Collections._ // naive CNF translation and simple DPLL solver trait Solving extends Logic { @@ -205,9 +206,8 @@ trait Solving extends Logic { // SI-7020 Linked- for deterministic counter examples. val pos = new mutable.LinkedHashSet[Sym]() val neg = new mutable.LinkedHashSet[Sym]() - f.foreach{_.foreach{ lit => - if (lit.pos) pos += lit.sym else neg += lit.sym - }} + mforeach(f)(lit => if (lit.pos) pos += lit.sym else neg += lit.sym) + // appearing in both positive and negative val impures: mutable.LinkedHashSet[Sym] = pos intersect neg // appearing only in either positive/negative positions diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 9ac0b0835a..347426d42a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1183,8 +1183,8 @@ trait Namers extends MethodSynthesis { // value parameters of the base class (whose defaults might be overridden) var baseParamss = (vparamss, overridden.tpe.paramss) match { // match empty and missing parameter list - case (Nil, List(Nil)) => Nil - case (List(Nil), Nil) => ListOfNil + case (Nil, ListOfNil) => Nil + case (ListOfNil, Nil) => ListOfNil case (_, paramss) => paramss } assert( diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index 2584dcb117..de24b88397 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -3,6 +3,7 @@ package reflect package internal import Flags._ +import util._ trait BuildUtils { self: SymbolTable => import definitions.{TupleClass, FunctionClass, ScalaPackage, UnitClass} @@ -364,7 +365,7 @@ trait BuildUtils { self: SymbolTable => def unapply(tree: Tree): Option[(List[Tree], List[Tree], ValDef, List[Tree])] = tree match { case SyntacticApplied(Select(New(SyntacticTypeApplied(ident, targs)), nme.CONSTRUCTOR), argss) => Some((Nil, SyntacticApplied(SyntacticTypeApplied(ident, targs), argss) :: Nil, emptyValDef, Nil)) - case SyntacticBlock(SyntacticClassDef(_, tpnme.ANON_CLASS_NAME, Nil, _, List(Nil), earlyDefs, parents, selfdef, body) :: + case SyntacticBlock(SyntacticClassDef(_, tpnme.ANON_CLASS_NAME, Nil, _, ListOfNil, earlyDefs, parents, selfdef, body) :: Apply(Select(New(Ident(tpnme.ANON_CLASS_NAME)), nme.CONSTRUCTOR), Nil) :: Nil) => Some((earlyDefs, parents, selfdef, body)) case _ => diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index ed1c3f1044..f8af4f155d 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -285,6 +285,10 @@ trait Definitions extends api.StandardDefinitions { lazy val StringTpe = StringClass.tpe lazy val ThrowableTpe = ThrowableClass.tpe + lazy val ConstantTrue = ConstantType(Constant(true)) + lazy val ConstantFalse = ConstantType(Constant(false)) + lazy val ConstantNull = ConstantType(Constant(null)) + // Note: this is not the type alias AnyRef, it's a companion-like // object used by the @specialize annotation. lazy val AnyRefModule = getMemberModule(ScalaPackageClass, nme.AnyRef) diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index 26adf20c52..72e1ee107b 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -3,6 +3,7 @@ package reflect package internal import Flags._ +import util._ abstract class TreeGen extends macros.TreeBuilder { val global: SymbolTable @@ -355,8 +356,9 @@ abstract class TreeGen extends macros.TreeBuilder { if (body forall treeInfo.isInterfaceMember) None else Some( atPos(wrappingPos(superPos, lvdefs)) ( - DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), List(Nil), TypeTree(), Block(lvdefs, Literal(Constant()))))) - } else { + DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, Nil, ListOfNil, TypeTree(), Block(lvdefs, Literal(Constant()))))) + } + else { // convert (implicit ... ) to ()(implicit ... ) if its the only parameter section if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit) vparamss1 = List() :: vparamss1 @@ -416,7 +418,7 @@ abstract class TreeGen extends macros.TreeBuilder { atPos(cpos) { ClassDef( Modifiers(FINAL), x, Nil, - mkTemplate(parents, self, NoMods, List(Nil), stats, cpos.focus)) + mkTemplate(parents, self, NoMods, ListOfNil, stats, cpos.focus)) }), atPos(npos) { New( diff --git a/src/reflect/scala/reflect/internal/TypeDebugging.scala b/src/reflect/scala/reflect/internal/TypeDebugging.scala index fd64d98ca2..b70d3bd970 100644 --- a/src/reflect/scala/reflect/internal/TypeDebugging.scala +++ b/src/reflect/scala/reflect/internal/TypeDebugging.scala @@ -7,7 +7,7 @@ package scala package reflect package internal -import util.shortClassOfInstance +import util._ trait TypeDebugging { self: SymbolTable => @@ -39,17 +39,17 @@ trait TypeDebugging { def skipType(tpe: Type): Boolean = (tpe eq null) || skipSym(tpe.typeSymbolDirect) def skip(t: Tree): Boolean = t match { - case EmptyTree => true - case PackageDef(_, _) => true - case t: RefTree => skipRefTree(t) - case TypeBoundsTree(lo, hi) => skip(lo) && skip(hi) - case Block(Nil, expr) => skip(expr) - case Apply(fn, Nil) => skip(fn) - case Block(stmt :: Nil, expr) => skip(stmt) && skip(expr) - case DefDef(_, nme.CONSTRUCTOR, Nil, Nil :: Nil, _, rhs) => skip(rhs) - case Literal(Constant(())) => true - case tt @ TypeTree() => skipType(tt.tpe) - case _ => skipSym(t.symbol) + case EmptyTree => true + case PackageDef(_, _) => true + case t: RefTree => skipRefTree(t) + case TypeBoundsTree(lo, hi) => skip(lo) && skip(hi) + case Block(Nil, expr) => skip(expr) + case Apply(fn, Nil) => skip(fn) + case Block(stmt :: Nil, expr) => skip(stmt) && skip(expr) + case DefDef(_, nme.CONSTRUCTOR, Nil, ListOfNil, _, rhs) => skip(rhs) + case Literal(Constant(())) => true + case tt @ TypeTree() => skipType(tt.tpe) + case _ => skipSym(t.symbol) } def apply(t: Tree) = skip(t) } diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 3adbbf13fc..dd6917814e 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -2835,9 +2835,6 @@ trait Types // but pattern-matching returned the original constr0 (a bug) // now, pattern-matching returns the most recent constr object TypeVar { - private val ConstantTrue = ConstantType(Constant(true)) - private val ConstantFalse = ConstantType(Constant(false)) - @inline final def trace[T](action: String, msg: => String)(value: T): T = { if (traceTypeVars) { val s = msg match { @@ -3059,13 +3056,13 @@ trait Types // ignore subtyping&equality checks while true -- see findMember // OPT: This could be Either[TypeVar, Boolean], but this encoding was chosen instead to save allocations. - private var _suspended: Type = TypeVar.ConstantFalse + private var _suspended: Type = ConstantFalse private[Types] def suspended: Boolean = (_suspended: @unchecked) match { - case TypeVar.ConstantFalse => false - case TypeVar.ConstantTrue => true - case tv: TypeVar => tv.suspended + case ConstantFalse => false + case ConstantTrue => true + case tv: TypeVar => tv.suspended } - private[Types] def suspended_=(b: Boolean): Unit = _suspended = if (b) TypeVar.ConstantTrue else TypeVar.ConstantFalse + private[Types] def suspended_=(b: Boolean): Unit = _suspended = if (b) ConstantTrue else ConstantFalse // SI-7785 Link the suspended attribute of a TypeVar created in, say, a TypeMap (e.g. AsSeenFrom) to its originator private[Types] def linkSuspended(origin: TypeVar): Unit = _suspended = origin diff --git a/src/reflect/scala/reflect/internal/util/Collections.scala b/src/reflect/scala/reflect/internal/util/Collections.scala index 59af819dad..738baddc08 100644 --- a/src/reflect/scala/reflect/internal/util/Collections.scala +++ b/src/reflect/scala/reflect/internal/util/Collections.scala @@ -34,14 +34,19 @@ trait Collections { xss forall (_ forall p) final def mmap[A, B](xss: List[List[A]])(f: A => B) = xss map (_ map f) - final def mforeach[A](xss: List[List[A]])(f: A => Unit) = - xss foreach (_ foreach f) final def mfind[A](xss: List[List[A]])(p: A => Boolean): Option[A] = { var res: Option[A] = null mforeach(xss)(x => if ((res eq null) && p(x)) res = Some(x)) if (res eq null) None else res } + /** These are all written in terms of List because we're trying to wring all + * the performance we can and List is used almost exclusively in the compiler, + * but people are branching out in their collections so here's an overload. + */ + final def mforeach[A](xss: List[List[A]])(f: A => Unit) = xss foreach (_ foreach f) + final def mforeach[A](xss: Traversable[Traversable[A]])(f: A => Unit) = xss foreach (_ foreach f) + final def map2[A, B, C](xs1: List[A], xs2: List[B])(f: (A, B) => C): List[C] = { val lb = new ListBuffer[C] var ys1 = xs1 diff --git a/src/reflect/scala/reflect/internal/util/package.scala b/src/reflect/scala/reflect/internal/util/package.scala index df63a55090..3618c150ca 100644 --- a/src/reflect/scala/reflect/internal/util/package.scala +++ b/src/reflect/scala/reflect/internal/util/package.scala @@ -7,6 +7,9 @@ import scala.language.existentials // SI-6541 package object util { import StringOps.longestCommonPrefix + // An allocation-avoiding reusable instance of the so-common List(Nil). + val ListOfNil: List[List[Nothing]] = Nil :: Nil + def andFalse(body: Unit): Boolean = false // Shorten a name like Symbols$FooSymbol to FooSymbol. |