diff options
Diffstat (limited to 'src')
53 files changed, 938 insertions, 2176 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala index e635c5e87d..6e39fc9aa1 100755 --- a/src/compiler/scala/tools/nsc/ast/DocComments.scala +++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala @@ -56,6 +56,11 @@ trait DocComments { self: Global => else sym.owner.ancestors map (sym overriddenSymbol _) filter (_ != NoSymbol) } + def fillDocComment(sym: Symbol, comment: DocComment) { + docComments(sym) = comment + comment.defineVariables(sym) + } + /** The raw doc comment of symbol `sym`, minus usecase and define sections, augmented by * missing sections of an inherited doc comment. * If a symbol does not have a doc comment but some overridden version of it does, diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 0abbe44b02..9b16327ffc 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -2143,8 +2143,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { val start = st.pop() seen ::= LocVarEntry(lv, start, end) case _ => - // TODO SI-6049 - getCurrentCUnit().warning(iPos, "Visited SCOPE_EXIT before visiting corresponding SCOPE_ENTER. SI-6049") + // TODO SI-6049 track down the cause for these. + debugwarn(s"$iPos: Visited SCOPE_EXIT before visiting corresponding SCOPE_ENTER. SI-6191") } } diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala index 73738ebd21..af82957a2e 100644 --- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala +++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala @@ -164,17 +164,22 @@ trait CompilerControl { self: Global => /** Sets sync var `response` to doc comment information for a given symbol. * - * @param sym The symbol whose doc comment should be retrieved (might come from a classfile) - * @param site The place where sym is observed. - * @param source The source file that's supposed to contain the definition - * @param response A response that will be set to the following: - * If `source` contains a definition of a given symbol that has a doc comment, - * the (expanded, raw, position) triplet for a comment, otherwise ("", "", NoPosition). - * Note: This operation does not automatically load `source`. If `source` - * is unloaded, it stays that way. + * @param sym The symbol whose doc comment should be retrieved (might come from a classfile) + * @param source The source file that's supposed to contain the definition + * @param site The symbol where 'sym' is observed + * @param fragments All symbols that can contribute to the generated documentation + * together with their source files. + * @param response A response that will be set to the following: + * If `source` contains a definition of a given symbol that has a doc comment, + * the (expanded, raw, position) triplet for a comment, otherwise ("", "", NoPosition). + * Note: This operation does not automatically load sources that are not yet loaded. */ - def askDocComment(sym: Symbol, site: Symbol, source: SourceFile, response: Response[(String, String, Position)]) = - postWorkItem(new AskDocCommentItem(sym, site, source, response)) + def askDocComment(sym: Symbol, source: SourceFile, site: Symbol, fragments: List[(Symbol,SourceFile)], response: Response[(String, String, Position)]): Unit = + postWorkItem(new AskDocCommentItem(sym, source, site, fragments, response)) + + @deprecated("Use method that accepts fragments", "2.10.2") + def askDocComment(sym: Symbol, site: Symbol, source: SourceFile, response: Response[(String, String, Position)]): Unit = + askDocComment(sym, source, site, (sym,source)::Nil, response) /** Sets sync var `response` to list of members that are visible * as members of the tree enclosing `pos`, possibly reachable by an implicit. @@ -390,9 +395,9 @@ trait CompilerControl { self: Global => response raise new MissingResponse } - case class AskDocCommentItem(val sym: Symbol, val site: Symbol, val source: SourceFile, response: Response[(String, String, Position)]) extends WorkItem { - def apply() = self.getDocComment(sym, site, source, response) - override def toString = "doc comment "+sym+" in "+source + case class AskDocCommentItem(val sym: Symbol, val source: SourceFile, val site: Symbol, val fragments: List[(Symbol,SourceFile)], response: Response[(String, String, Position)]) extends WorkItem { + def apply() = self.getDocComment(sym, source, site, fragments, response) + override def toString = "doc comment "+sym+" in "+source+" with fragments:"+fragments.mkString("(", ",", ")") def raiseMissing() = response raise new MissingResponse diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index 4c2c3e35f8..1f2245abb5 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -704,8 +704,8 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") * If we do just removeUnit, some problems with default parameters can ensue. * Calls to this method could probably be replaced by removeUnit once default parameters are handled more robustly. */ - private def afterRunRemoveUnitOf(source: SourceFile) { - toBeRemovedAfterRun += source.file + private def afterRunRemoveUnitsOf(sources: List[SourceFile]) { + toBeRemovedAfterRun ++= sources map (_.file) } /** A fully attributed tree located at position `pos` */ @@ -713,7 +713,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") case None => reloadSources(List(pos.source)) try typedTreeAt(pos) - finally afterRunRemoveUnitOf(pos.source) + finally afterRunRemoveUnitsOf(List(pos.source)) case Some(unit) => informIDE("typedTreeAt " + pos) parseAndEnter(unit) @@ -763,14 +763,23 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") respond(response)(typedTree(source, forceReload)) } + private def withTempUnits[T](sources: List[SourceFile])(f: (SourceFile => RichCompilationUnit) => T): T = { + val unitOfSrc: SourceFile => RichCompilationUnit = src => unitOfFile(src.file) + sources filterNot (getUnit(_).isDefined) match { + case Nil => + f(unitOfSrc) + case unknown => + reloadSources(unknown) + try { + f(unitOfSrc) + } finally + afterRunRemoveUnitsOf(unknown) + } + } + private def withTempUnit[T](source: SourceFile)(f: RichCompilationUnit => T): T = - getUnit(source) match { - case None => - reloadSources(List(source)) - try f(getUnit(source).get) - finally afterRunRemoveUnitOf(source) - case Some(unit) => - f(unit) + withTempUnits(List(source)){ srcToUnit => + f(srcToUnit(source)) } /** Find a 'mirror' of symbol `sym` in unit `unit`. Pre: `unit is loaded. */ @@ -834,50 +843,36 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") } } + private def forceDocComment(sym: Symbol, unit: RichCompilationUnit) { + unit.body foreachPartial { + case DocDef(comment, defn) if defn.symbol == sym => + fillDocComment(defn.symbol, comment) + EmptyTree + case _: ValOrDefDef => + EmptyTree + } + } + /** Implements CompilerControl.askDocComment */ - private[interactive] def getDocComment(sym: Symbol, site: Symbol, source: SourceFile, response: Response[(String, String, Position)]) { - informIDE("getDocComment "+sym+" "+source) + private[interactive] def getDocComment(sym: Symbol, source: SourceFile, site: Symbol, fragments: List[(Symbol,SourceFile)], + response: Response[(String, String, Position)]) { + informIDE(s"getDocComment $sym at $source site $site") respond(response) { - withTempUnit(source){ u => - val mirror = findMirrorSymbol(sym, u) + withTempUnits(fragments.toList.unzip._2){ units => + for((sym, src) <- fragments) { + val mirror = findMirrorSymbol(sym, units(src)) + if (mirror ne NoSymbol) forceDocComment(mirror, units(src)) + } + val mirror = findMirrorSymbol(sym, units(source)) if (mirror eq NoSymbol) ("", "", NoPosition) else { - forceDocComment(mirror, u) - (expandedDocComment(mirror), rawDocComment(mirror), docCommentPos(mirror)) + (expandedDocComment(mirror, site), rawDocComment(mirror), docCommentPos(mirror)) } } } } - private def forceDocComment(sym: Symbol, unit: RichCompilationUnit) { - // Either typer has been run and we don't find DocDef, - // or we force the targeted typecheck here. - // In both cases doc comment maps should be filled for the subject symbol. - val docTree = - unit.body find { - case DocDef(_, defn) if defn.symbol eq sym => true - case _ => false - } - - for (t <- docTree) { - debugLog("Found DocDef tree for "+sym) - // Cannot get a typed tree at position since DocDef range is transparent. - val prevPos = unit.targetPos - val prevInterruptsEnabled = interruptsEnabled - try { - unit.targetPos = t.pos - interruptsEnabled = true - typeCheck(unit) - } catch { - case _: TyperResult => // ignore since we are after the side effect. - } finally { - unit.targetPos = prevPos - interruptsEnabled = prevInterruptsEnabled - } - } - } - def stabilizedType(tree: Tree): Type = tree match { case Ident(_) if tree.symbol.isStable => singleType(NoPrefix, tree.symbol) diff --git a/src/compiler/scala/tools/nsc/interactive/Picklers.scala b/src/compiler/scala/tools/nsc/interactive/Picklers.scala index 84cb03c140..2b389158c3 100644 --- a/src/compiler/scala/tools/nsc/interactive/Picklers.scala +++ b/src/compiler/scala/tools/nsc/interactive/Picklers.scala @@ -166,8 +166,8 @@ trait Picklers { self: Global => .asClass (classOf[AskLinkPosItem]) implicit def askDocCommentItem: CondPickler[AskDocCommentItem] = - (pkl[Symbol] ~ pkl[Symbol] ~ pkl[SourceFile]) - .wrapped { case sym ~ site ~ source => new AskDocCommentItem(sym, site, source, new Response) } { item => item.sym ~ item.site ~ item.source } + (pkl[Symbol] ~ pkl[SourceFile] ~ pkl[Symbol] ~ pkl[List[(Symbol,SourceFile)]]) + .wrapped { case sym ~ source ~ site ~ fragments => new AskDocCommentItem(sym, source, site, fragments, new Response) } { item => item.sym ~ item.source ~ item.site ~ item.fragments } .asClass (classOf[AskDocCommentItem]) implicit def askLoadedTypedItem: CondPickler[AskLoadedTypedItem] = diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 889d309ba9..cb5268c422 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -477,6 +477,7 @@ abstract class Erasure extends AddInterfaces def checkPair(member: Symbol, other: Symbol) { val otpe = specialErasure(root)(other.tpe) val bridgeNeeded = afterErasure ( + !member.isMacro && !(other.tpe =:= member.tpe) && !(deconstMap(other.tpe) =:= deconstMap(member.tpe)) && { var e = bridgesScope.lookupEntry(member.name) diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala index 9af4800a70..22eabb6d6f 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala @@ -287,236 +287,9 @@ trait Logic extends Debugging { def findModelFor(f: Formula): Model def findAllModelsFor(f: Formula): List[Model] } - - trait CNF extends PropositionalLogic { - - /** Override Array creation for efficiency (to not go through reflection). */ - private implicit val clauseTag: scala.reflect.ClassTag[Clause] = new scala.reflect.ClassTag[Clause] { - def runtimeClass: java.lang.Class[Clause] = classOf[Clause] - final override def newArray(len: Int): Array[Clause] = new Array[Clause](len) - } - - import scala.collection.mutable.ArrayBuffer - type FormulaBuilder = ArrayBuffer[Clause] - def formulaBuilder = ArrayBuffer[Clause]() - def formulaBuilderSized(init: Int) = new ArrayBuffer[Clause](init) - def addFormula(buff: FormulaBuilder, f: Formula): Unit = buff ++= f - def toFormula(buff: FormulaBuilder): Formula = buff - - // CNF: a formula is a conjunction of clauses - type Formula = FormulaBuilder - def formula(c: Clause*): Formula = ArrayBuffer(c: _*) - - type Clause = Set[Lit] - // a clause is a disjunction of distinct literals - def clause(l: Lit*): Clause = l.toSet - - type Lit - def Lit(sym: Sym, pos: Boolean = true): Lit - - def andFormula(a: Formula, b: Formula): Formula = a ++ b - def simplifyFormula(a: Formula): Formula = a.distinct - - private def merge(a: Clause, b: Clause) = a ++ b - - // throws an AnalysisBudget.Exception when the prop results in a CNF that's too big - // TODO: be smarter/more efficient about this (http://lara.epfl.ch/w/sav09:tseitin_s_encoding) - def eqFreePropToSolvable(p: Prop): Formula = { - def negationNormalFormNot(p: Prop, budget: Int): Prop = - if (budget <= 0) throw AnalysisBudget.exceeded - else p match { - case And(a, b) => Or(negationNormalFormNot(a, budget - 1), negationNormalFormNot(b, budget - 1)) - case Or(a, b) => And(negationNormalFormNot(a, budget - 1), negationNormalFormNot(b, budget - 1)) - case Not(p) => negationNormalForm(p, budget - 1) - case True => False - case False => True - case s: Sym => Not(s) - } - - def negationNormalForm(p: Prop, budget: Int = AnalysisBudget.max): Prop = - if (budget <= 0) throw AnalysisBudget.exceeded - else p match { - case And(a, b) => And(negationNormalForm(a, budget - 1), negationNormalForm(b, budget - 1)) - case Or(a, b) => Or(negationNormalForm(a, budget - 1), negationNormalForm(b, budget - 1)) - case Not(negated) => negationNormalFormNot(negated, budget - 1) - case True - | False - | (_ : Sym) => p - } - - val TrueF = formula() - val FalseF = formula(clause()) - def lit(s: Sym) = formula(clause(Lit(s))) - def negLit(s: Sym) = formula(clause(Lit(s, false))) - - def conjunctiveNormalForm(p: Prop, budget: Int = AnalysisBudget.max): Formula = { - def distribute(a: Formula, b: Formula, budget: Int): Formula = - if (budget <= 0) throw AnalysisBudget.exceeded - else - (a, b) match { - // true \/ _ = true - // _ \/ true = true - case (trueA, trueB) if trueA.size == 0 || trueB.size == 0 => TrueF - // lit \/ lit - case (a, b) if a.size == 1 && b.size == 1 => formula(merge(a(0), b(0))) - // (c1 /\ ... /\ cn) \/ d = ((c1 \/ d) /\ ... /\ (cn \/ d)) - // d \/ (c1 /\ ... /\ cn) = ((d \/ c1) /\ ... /\ (d \/ cn)) - case (cs, ds) => - val (big, small) = if (cs.size > ds.size) (cs, ds) else (ds, cs) - big flatMap (c => distribute(formula(c), small, budget - (big.size*small.size))) - } - - if (budget <= 0) throw AnalysisBudget.exceeded - - p match { - case True => TrueF - case False => FalseF - case s: Sym => lit(s) - case Not(s: Sym) => negLit(s) - case And(a, b) => - val cnfA = conjunctiveNormalForm(a, budget - 1) - val cnfB = conjunctiveNormalForm(b, budget - cnfA.size) - cnfA ++ cnfB - case Or(a, b) => - val cnfA = conjunctiveNormalForm(a) - val cnfB = conjunctiveNormalForm(b) - distribute(cnfA, cnfB, budget - (cnfA.size + cnfB.size)) - } - } - - val start = if (Statistics.canEnable) Statistics.startTimer(patmatCNF) else null - val res = conjunctiveNormalForm(negationNormalForm(p)) - - if (Statistics.canEnable) Statistics.stopTimer(patmatCNF, start) - - // - if (Statistics.canEnable) patmatCNFSizes(res.size).value += 1 - -// debug.patmat("cnf for\n"+ p +"\nis:\n"+cnfString(res)) - res - } - } - - trait DPLLSolver extends CNF { - // a literal is a (possibly negated) variable - def Lit(sym: Sym, pos: Boolean = true) = new Lit(sym, pos) - class Lit(val sym: Sym, val pos: Boolean) { - override def toString = if (!pos) "-"+ sym.toString else sym.toString - override def equals(o: Any) = o match { - case o: Lit => (o.sym eq sym) && (o.pos == pos) - case _ => false - } - override def hashCode = sym.hashCode + pos.hashCode - - def unary_- = Lit(sym, !pos) - } - - def cnfString(f: Formula) = alignAcrossRows(f map (_.toList) toList, "\\/", " /\\\n") - - // adapted from http://lara.epfl.ch/w/sav10:simple_sat_solver (original by Hossein Hojjat) - val EmptyModel = Map.empty[Sym, Boolean] - val NoModel: Model = null - - // returns all solutions, if any (TODO: better infinite recursion backstop -- detect fixpoint??) - def findAllModelsFor(f: Formula): List[Model] = { - val vars: Set[Sym] = f.flatMap(_ collect {case l: Lit => l.sym}).toSet - // debug.patmat("vars "+ vars) - // the negation of a model -(S1=True/False /\ ... /\ SN=True/False) = clause(S1=False/True, ...., SN=False/True) - def negateModel(m: Model) = clause(m.toSeq.map{ case (sym, pos) => Lit(sym, !pos) } : _*) - - def findAllModels(f: Formula, models: List[Model], recursionDepthAllowed: Int = 10): List[Model]= - if (recursionDepthAllowed == 0) models - else { - debug.patmat("find all models for\n"+ cnfString(f)) - val model = findModelFor(f) - // if we found a solution, conjunct the formula with the model's negation and recurse - if (model ne NoModel) { - val unassigned = (vars -- model.keySet).toList - debug.patmat("unassigned "+ unassigned +" in "+ model) - def force(lit: Lit) = { - val model = withLit(findModelFor(dropUnit(f, lit)), lit) - if (model ne NoModel) List(model) - else Nil - } - val forced = unassigned flatMap { s => - force(Lit(s, true)) ++ force(Lit(s, false)) - } - debug.patmat("forced "+ forced) - val negated = negateModel(model) - findAllModels(f :+ negated, model :: (forced ++ models), recursionDepthAllowed - 1) - } - else models - } - - findAllModels(f, Nil) - } - - private def withLit(res: Model, l: Lit): Model = if (res eq NoModel) NoModel else res + (l.sym -> l.pos) - private def dropUnit(f: Formula, unitLit: Lit): Formula = { - val negated = -unitLit - // drop entire clauses that are trivially true - // (i.e., disjunctions that contain the literal we're making true in the returned model), - // and simplify clauses by dropping the negation of the literal we're making true - // (since False \/ X == X) - val dropped = formulaBuilderSized(f.size) - for { - clause <- f - if !(clause contains unitLit) - } dropped += (clause - negated) - dropped - } - - def findModelFor(f: Formula): Model = { - @inline def orElse(a: Model, b: => Model) = if (a ne NoModel) a else b - - debug.patmat("DPLL\n"+ cnfString(f)) - - val start = if (Statistics.canEnable) Statistics.startTimer(patmatAnaDPLL) else null - - val satisfiableWithModel: Model = - if (f isEmpty) EmptyModel - else if(f exists (_.isEmpty)) NoModel - else f.find(_.size == 1) match { - case Some(unitClause) => - val unitLit = unitClause.head - // debug.patmat("unit: "+ unitLit) - withLit(findModelFor(dropUnit(f, unitLit)), unitLit) - case _ => - // partition symbols according to whether they appear in positive and/or negative literals - val pos = new mutable.HashSet[Sym]() - val neg = new mutable.HashSet[Sym]() - f.foreach{_.foreach{ lit => - if (lit.pos) pos += lit.sym else neg += lit.sym - }} - // appearing in both positive and negative - val impures = pos intersect neg - // appearing only in either positive/negative positions - val pures = (pos ++ neg) -- impures - - if (pures nonEmpty) { - val pureSym = pures.head - // turn it back into a literal - // (since equality on literals is in terms of equality - // of the underlying symbol and its positivity, simply construct a new Lit) - val pureLit = Lit(pureSym, pos(pureSym)) - // debug.patmat("pure: "+ pureLit +" pures: "+ pures +" impures: "+ impures) - val simplified = f.filterNot(_.contains(pureLit)) - withLit(findModelFor(simplified), pureLit) - } else { - val split = f.head.head - // debug.patmat("split: "+ split) - orElse(findModelFor(f :+ clause(split)), findModelFor(f :+ clause(-split))) - } - } - - if (Statistics.canEnable) Statistics.stopTimer(patmatAnaDPLL, start) - - satisfiableWithModel - } - } } -trait ScalaLogic extends Logic { self: PatternMatching => +trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { trait TreesAndTypesDomain extends PropositionalLogic with CheckableTreeAndTypeAnalysis { type Type = global.Type type Tree = global.Tree diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala index ed990105fd..d9f93f27b6 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala @@ -125,23 +125,15 @@ trait TreeAndTypeAnalysis extends Debugging { } } -trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching => - import PatternMatchingStats._ - import global.{Tree, Type, Symbol, CaseDef, atPos, - Select, Block, ThisType, SingleType, NoPrefix, NoType, definitions, needsOuterTest, - ConstantType, Literal, Constant, gen, This, analyzer, EmptyTree, map2, NoSymbol, Traverser, - Function, Typed, treeInfo, DefTree, ValDef, nme, appliedType, Name, WildcardType, Ident, TypeRef, - UniqueType, RefinedType, currentUnit, SingletonType, singleType, ModuleClassSymbol, - nestedMemberType, TypeMap, EmptyScope, Apply, If, Bind, lub, Alternative, deriveCaseDef, Match, MethodType, LabelDef, TypeTree, Throw, newTermName} - - import definitions._ - import analyzer.{Typer, ErrorUtils, formalTypes} +trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchTreeMaking { + import global.{Tree, Type, NoType, Symbol, NoSymbol, ConstantType, Literal, Constant, Ident, UniqueType, RefinedType, EmptyScope} + import global.definitions.{ListClass, NilModule} /** * Represent a match as a formula in propositional logic that encodes whether the match matches (abstractly: we only consider types) * */ - trait TreeMakerApproximation extends TreeMakers with PropositionalLogic with TreesAndTypesDomain with CheckableTreeAndTypeAnalysis { self: CodegenCore => + trait MatchApproximator extends TreeMakers with TreesAndTypesDomain { object Test { var currId = 0 } @@ -348,7 +340,14 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching => } } - trait SymbolicMatchAnalysis extends TreeMakerApproximation { self: CodegenCore => +} + +trait MatchAnalysis extends MatchApproximation { + import PatternMatchingStats._ + import global.{Tree, Type, Symbol, NoSymbol, Ident, Select} + import global.definitions.{isPrimitiveValueClass, ConsClass, isTupleSymbol} + + trait MatchAnalyzer extends MatchApproximator { def uncheckedWarning(pos: Position, msg: String) = global.currentUnit.uncheckedWarning(pos, msg) def warn(pos: Position, ex: AnalysisBudget.Exception, kind: String) = uncheckedWarning(pos, s"Cannot check match for $kind.\n${ex.advice}") @@ -498,7 +497,7 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching => // a way to construct a value that will make the match fail: a constructor invocation, a constant, an object of some type) class CounterExample { - protected[SymbolicMatchAnalysis] def flattenConsArgs: List[CounterExample] = Nil + protected[MatchAnalyzer] def flattenConsArgs: List[CounterExample] = Nil def coveredBy(other: CounterExample): Boolean = this == other || other == WildcardExample } case class ValueExample(c: ValueConst) extends CounterExample { override def toString = c.toString } @@ -513,11 +512,11 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching => } } case class ListExample(ctorArgs: List[CounterExample]) extends CounterExample { - protected[SymbolicMatchAnalysis] override def flattenConsArgs: List[CounterExample] = ctorArgs match { + protected[MatchAnalyzer] override def flattenConsArgs: List[CounterExample] = ctorArgs match { case hd :: tl :: Nil => hd :: tl.flattenConsArgs case _ => Nil } - protected[SymbolicMatchAnalysis] lazy val elems = flattenConsArgs + protected[MatchAnalyzer] lazy val elems = flattenConsArgs override def coveredBy(other: CounterExample): Boolean = other match { @@ -691,5 +690,18 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching => // this is the variable we want a counter example for VariableAssignment(scrutVar).toCounterExample() } + + def analyzeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, suppression: Suppression): Unit = { + if (!suppression.unreachable) { + unreachableCase(prevBinder, cases, pt) foreach { caseIndex => + reportUnreachable(cases(caseIndex).last.pos) + } + } + if (!suppression.exhaustive) { + val counterExamples = exhaustive(prevBinder, cases, pt) + if (counterExamples.nonEmpty) + reportMissingCases(prevBinder.pos, counterExamples) + } + } } } diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala index ce19d9cba8..57fab4eafa 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala @@ -17,7 +17,7 @@ import scala.reflect.internal.util.NoPosition * We have two modes in which to emit trees: optimized (the default) * and pure (aka "virtualized": match is parametric in its monad). */ -trait MatchCodeGen { self: PatternMatching => +trait MatchCodeGen extends Interface { import PatternMatchingStats._ import global.{nme, treeInfo, definitions, gen, Tree, Type, Symbol, NoSymbol, appliedType, NoType, MethodType, newTermName, Name, diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala index c14b4ebc3b..dcf2413b15 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala @@ -19,7 +19,7 @@ import scala.reflect.internal.util.NoPosition * * TODO: split out match analysis */ -trait MatchOptimization { self: PatternMatching => +trait MatchOptimization extends MatchTreeMaking with MatchAnalysis { import PatternMatchingStats._ import global.{Tree, Type, Symbol, NoSymbol, CaseDef, atPos, ConstantType, Literal, Constant, gen, EmptyTree, @@ -30,7 +30,7 @@ trait MatchOptimization { self: PatternMatching => //// - trait CommonSubconditionElimination extends TreeMakerApproximation { self: OptimizedCodegen => + trait CommonSubconditionElimination extends OptimizedCodegen with MatchApproximator { /** a flow-sensitive, generalised, common sub-expression elimination * reuse knowledge from performed tests * the only sub-expressions we consider are the conditions and results of the three tests (type, type&equality, equality) @@ -205,19 +205,19 @@ trait MatchOptimization { self: PatternMatching => //// DCE - trait DeadCodeElimination extends TreeMakers { self: CodegenCore => - // TODO: non-trivial dead-code elimination - // e.g., the following match should compile to a simple instanceof: - // case class Ident(name: String) - // for (Ident(name) <- ts) println(name) - def doDCE(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type): List[List[TreeMaker]] = { - // do minimal DCE - cases - } - } +// trait DeadCodeElimination extends TreeMakers { +// // TODO: non-trivial dead-code elimination +// // e.g., the following match should compile to a simple instanceof: +// // case class Ident(name: String) +// // for (Ident(name) <- ts) println(name) +// def doDCE(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type): List[List[TreeMaker]] = { +// // do minimal DCE +// cases +// } +// } //// SWITCHES -- TODO: operate on Tests rather than TreeMakers - trait SwitchEmission extends TreeMakers with OptimizedMatchMonadInterface { self: CodegenCore => + trait SwitchEmission extends TreeMakers with OptimizedMatchMonadInterface { import treeInfo.isGuardedCase abstract class SwitchMaker { @@ -589,26 +589,12 @@ trait MatchOptimization { self: PatternMatching => } } - - - - trait MatchOptimizations extends CommonSubconditionElimination - with DeadCodeElimination - with SwitchEmission - with OptimizedCodegen - with SymbolicMatchAnalysis - with DPLLSolver { self: TreeMakers => - override def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): (List[List[TreeMaker]], List[Tree]) = { - unreachableCase(prevBinder, cases, pt) foreach { caseIndex => - reportUnreachable(cases(caseIndex).last.pos) - } - if (!unchecked) { - val counterExamples = exhaustive(prevBinder, cases, pt) - if (counterExamples.nonEmpty) - reportMissingCases(prevBinder.pos, counterExamples) - } - - val optCases = doCSE(prevBinder, doDCE(prevBinder, cases, pt), pt) + trait MatchOptimizer extends OptimizedCodegen + with SwitchEmission + with CommonSubconditionElimination { + override def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type): (List[List[TreeMaker]], List[Tree]) = { + // TODO: do CSE on result of doDCE(prevBinder, cases, pt) + val optCases = doCSE(prevBinder, cases, pt) val toHoist = ( for (treeMakers <- optCases) yield treeMakers.collect{case tm: ReusedCondTreeMaker => tm.treesToHoist} diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala index 5d11fb6459..90c52e3eb6 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala @@ -24,7 +24,7 @@ trait MatchTranslation { self: PatternMatching => repeatedToSeq, isRepeatedParamType, getProductArgs} import global.analyzer.{ErrorUtils, formalTypes} - trait MatchTranslator extends MatchMonadInterface { self: TreeMakers with CodegenCore => + trait MatchTranslator extends TreeMakers { import typer.context // Why is it so difficult to say "here's a name and a context, give me any diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala index c9285f9229..202f3444f8 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala @@ -18,21 +18,26 @@ import scala.reflect.internal.util.NoPosition * The IR is mostly concerned with sequencing, substitution, and rendering all necessary conditions, * mostly agnostic to whether we're in optimized/pure (virtualized) mode. */ -trait MatchTreeMaking { self: PatternMatching => +trait MatchTreeMaking extends MatchCodeGen with Debugging { import PatternMatchingStats._ import global.{Tree, Type, Symbol, CaseDef, atPos, settings, Select, Block, ThisType, SingleType, NoPrefix, NoType, needsOuterTest, ConstantType, Literal, Constant, gen, This, EmptyTree, map2, NoSymbol, Traverser, - Function, Typed, treeInfo, TypeRef, DefTree} + Function, Typed, treeInfo, TypeRef, DefTree, Ident, nme} import global.definitions.{SomeClass, AnyRefClass, UncheckedClass, BooleanClass} + final case class Suppression(exhaustive: Boolean, unreachable: Boolean) + object Suppression { + val NoSuppression = Suppression(false, false) + } + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // the making of the trees /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - trait TreeMakers extends TypedSubstitution { self: CodegenCore => - def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): (List[List[TreeMaker]], List[Tree]) = - (cases, Nil) + trait TreeMakers extends TypedSubstitution with CodegenCore { + def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type): (List[List[TreeMaker]], List[Tree]) + def analyzeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, suppression: Suppression): Unit def emitSwitch(scrut: Tree, scrutSym: Symbol, cases: List[List[TreeMaker]], pt: Type, matchFailGenOverride: Option[Tree => Tree], unchecked: Boolean): Option[Tree] = None @@ -522,18 +527,24 @@ trait MatchTreeMaking { self: PatternMatching => def matchFailGen = (matchFailGenOverride orElse Some(CODE.MATCHERROR(_: Tree))) debug.patmat("combining cases: "+ (casesNoSubstOnly.map(_.mkString(" >> ")).mkString("{", "\n", "}"))) - val (unchecked, requireSwitch) = - if (settings.XnoPatmatAnalysis.value) (true, false) + val (suppression, requireSwitch): (Suppression, Boolean) = + if (settings.XnoPatmatAnalysis.value) (Suppression.NoSuppression, false) else scrut match { - case Typed(_, tpt) => - (tpt.tpe hasAnnotation UncheckedClass, - // matches with two or fewer cases need not apply for switchiness (if-then-else will do) - treeInfo.isSwitchAnnotation(tpt.tpe) && casesNoSubstOnly.lengthCompare(2) > 0) + case Typed(tree, tpt) => + val suppressExhaustive = tpt.tpe hasAnnotation UncheckedClass + val supressUnreachable = tree match { + case Ident(name) if name startsWith nme.CHECK_IF_REFUTABLE_STRING => true // SI-7183 don't warn for withFilter's that turn out to be irrefutable. + case _ => false + } + val suppression = Suppression(suppressExhaustive, supressUnreachable) + // matches with two or fewer cases need not apply for switchiness (if-then-else will do) + val requireSwitch = treeInfo.isSwitchAnnotation(tpt.tpe) && casesNoSubstOnly.lengthCompare(2) > 0 + (suppression, requireSwitch) case _ => - (false, false) + (Suppression.NoSuppression, false) } - emitSwitch(scrut, scrutSym, casesNoSubstOnly, pt, matchFailGenOverride, unchecked).getOrElse{ + emitSwitch(scrut, scrutSym, casesNoSubstOnly, pt, matchFailGenOverride, suppression.exhaustive).getOrElse{ if (requireSwitch) typer.context.unit.warning(scrut.pos, "could not emit switch for @switch annotated match") if (casesNoSubstOnly nonEmpty) { @@ -550,7 +561,9 @@ trait MatchTreeMaking { self: PatternMatching => }) None else matchFailGen - val (cases, toHoist) = optimizeCases(scrutSym, casesNoSubstOnly, pt, unchecked) + analyzeCases(scrutSym, casesNoSubstOnly, pt, suppression) + + val (cases, toHoist) = optimizeCases(scrutSym, casesNoSubstOnly, pt) val matchRes = codegen.matcher(scrut, scrutSym, pt)(cases map combineExtractors, synthCatchAll) diff --git a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala index 07eed2cd94..df4e699620 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala @@ -34,13 +34,14 @@ import scala.reflect.internal.util.Position * - recover GADT typing by locally inserting implicit witnesses to type equalities derived from the current case, and considering these witnesses during subtyping (?) * - recover exhaustivity/unreachability of user-defined extractors by partitioning the types they match on using an HList or similar type-level structure */ -trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL +trait PatternMatching extends Transform with TypingTransformers with Debugging with Interface with MatchTranslation with MatchTreeMaking with MatchCodeGen with ScalaLogic + with Solving with MatchAnalysis with MatchOptimization { import global._ @@ -78,15 +79,20 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL } } - class PureMatchTranslator(val typer: analyzer.Typer, val matchStrategy: Tree) extends MatchTranslator with TreeMakers with PureCodegen - class OptimizingMatchTranslator(val typer: analyzer.Typer) extends MatchTranslator with TreeMakers with MatchOptimizations + class PureMatchTranslator(val typer: analyzer.Typer, val matchStrategy: Tree) extends MatchTranslator with PureCodegen { + def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type) = (cases, Nil) + def analyzeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, suppression: Suppression): Unit = {} + } + + class OptimizingMatchTranslator(val typer: analyzer.Typer) extends MatchTranslator + with MatchOptimizer + with MatchAnalyzer + with Solver } -trait HasGlobal { +trait Debugging { val global: Global -} -trait Debugging extends HasGlobal { // TODO: the inliner fails to inline the closures to debug.patmat unless the method is nested in an object object debug { val printPatmat = global.settings.Ypatmatdebug.value @@ -94,7 +100,7 @@ trait Debugging extends HasGlobal { } } -trait Interface { self: ast.TreeDSL with HasGlobal => +trait Interface extends ast.TreeDSL { import global.{newTermName, analyzer, Type, ErrorType, Symbol, Tree} import analyzer.Typer diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala new file mode 100644 index 0000000000..843f831ea1 --- /dev/null +++ b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala @@ -0,0 +1,242 @@ +/* NSC -- new Scala compiler + * + * Copyright 2011-2013 LAMP/EPFL + * @author Adriaan Moors + */ + +package scala.tools.nsc.transform.patmat + +import scala.collection.mutable +import scala.reflect.internal.util.Statistics + +// naive CNF translation and simple DPLL solver +trait Solving extends Logic { + import PatternMatchingStats._ + trait CNF extends PropositionalLogic { + + /** Override Array creation for efficiency (to not go through reflection). */ + private implicit val clauseTag: scala.reflect.ClassTag[Clause] = new scala.reflect.ClassTag[Clause] { + def runtimeClass: java.lang.Class[Clause] = classOf[Clause] + final override def newArray(len: Int): Array[Clause] = new Array[Clause](len) + } + + import scala.collection.mutable.ArrayBuffer + type FormulaBuilder = ArrayBuffer[Clause] + def formulaBuilder = ArrayBuffer[Clause]() + def formulaBuilderSized(init: Int) = new ArrayBuffer[Clause](init) + def addFormula(buff: FormulaBuilder, f: Formula): Unit = buff ++= f + def toFormula(buff: FormulaBuilder): Formula = buff + + // CNF: a formula is a conjunction of clauses + type Formula = FormulaBuilder + def formula(c: Clause*): Formula = ArrayBuffer(c: _*) + + type Clause = Set[Lit] + // a clause is a disjunction of distinct literals + def clause(l: Lit*): Clause = l.toSet + + type Lit + def Lit(sym: Sym, pos: Boolean = true): Lit + + def andFormula(a: Formula, b: Formula): Formula = a ++ b + def simplifyFormula(a: Formula): Formula = a.distinct + + private def merge(a: Clause, b: Clause) = a ++ b + + // throws an AnalysisBudget.Exception when the prop results in a CNF that's too big + // TODO: be smarter/more efficient about this (http://lara.epfl.ch/w/sav09:tseitin_s_encoding) + def eqFreePropToSolvable(p: Prop): Formula = { + def negationNormalFormNot(p: Prop, budget: Int): Prop = + if (budget <= 0) throw AnalysisBudget.exceeded + else p match { + case And(a, b) => Or(negationNormalFormNot(a, budget - 1), negationNormalFormNot(b, budget - 1)) + case Or(a, b) => And(negationNormalFormNot(a, budget - 1), negationNormalFormNot(b, budget - 1)) + case Not(p) => negationNormalForm(p, budget - 1) + case True => False + case False => True + case s: Sym => Not(s) + } + + def negationNormalForm(p: Prop, budget: Int = AnalysisBudget.max): Prop = + if (budget <= 0) throw AnalysisBudget.exceeded + else p match { + case And(a, b) => And(negationNormalForm(a, budget - 1), negationNormalForm(b, budget - 1)) + case Or(a, b) => Or(negationNormalForm(a, budget - 1), negationNormalForm(b, budget - 1)) + case Not(negated) => negationNormalFormNot(negated, budget - 1) + case True + | False + | (_ : Sym) => p + } + + val TrueF = formula() + val FalseF = formula(clause()) + def lit(s: Sym) = formula(clause(Lit(s))) + def negLit(s: Sym) = formula(clause(Lit(s, false))) + + def conjunctiveNormalForm(p: Prop, budget: Int = AnalysisBudget.max): Formula = { + def distribute(a: Formula, b: Formula, budget: Int): Formula = + if (budget <= 0) throw AnalysisBudget.exceeded + else + (a, b) match { + // true \/ _ = true + // _ \/ true = true + case (trueA, trueB) if trueA.size == 0 || trueB.size == 0 => TrueF + // lit \/ lit + case (a, b) if a.size == 1 && b.size == 1 => formula(merge(a(0), b(0))) + // (c1 /\ ... /\ cn) \/ d = ((c1 \/ d) /\ ... /\ (cn \/ d)) + // d \/ (c1 /\ ... /\ cn) = ((d \/ c1) /\ ... /\ (d \/ cn)) + case (cs, ds) => + val (big, small) = if (cs.size > ds.size) (cs, ds) else (ds, cs) + big flatMap (c => distribute(formula(c), small, budget - (big.size*small.size))) + } + + if (budget <= 0) throw AnalysisBudget.exceeded + + p match { + case True => TrueF + case False => FalseF + case s: Sym => lit(s) + case Not(s: Sym) => negLit(s) + case And(a, b) => + val cnfA = conjunctiveNormalForm(a, budget - 1) + val cnfB = conjunctiveNormalForm(b, budget - cnfA.size) + cnfA ++ cnfB + case Or(a, b) => + val cnfA = conjunctiveNormalForm(a) + val cnfB = conjunctiveNormalForm(b) + distribute(cnfA, cnfB, budget - (cnfA.size + cnfB.size)) + } + } + + val start = if (Statistics.canEnable) Statistics.startTimer(patmatCNF) else null + val res = conjunctiveNormalForm(negationNormalForm(p)) + + if (Statistics.canEnable) Statistics.stopTimer(patmatCNF, start) + + // + if (Statistics.canEnable) patmatCNFSizes(res.size).value += 1 + +// debug.patmat("cnf for\n"+ p +"\nis:\n"+cnfString(res)) + res + } + } + + // simple solver using DPLL + trait Solver extends CNF { + // a literal is a (possibly negated) variable + def Lit(sym: Sym, pos: Boolean = true) = new Lit(sym, pos) + class Lit(val sym: Sym, val pos: Boolean) { + override def toString = if (!pos) "-"+ sym.toString else sym.toString + override def equals(o: Any) = o match { + case o: Lit => (o.sym eq sym) && (o.pos == pos) + case _ => false + } + override def hashCode = sym.hashCode + pos.hashCode + + def unary_- = Lit(sym, !pos) + } + + def cnfString(f: Formula) = alignAcrossRows(f map (_.toList) toList, "\\/", " /\\\n") + + // adapted from http://lara.epfl.ch/w/sav10:simple_sat_solver (original by Hossein Hojjat) + val EmptyModel = Map.empty[Sym, Boolean] + val NoModel: Model = null + + // returns all solutions, if any (TODO: better infinite recursion backstop -- detect fixpoint??) + def findAllModelsFor(f: Formula): List[Model] = { + val vars: Set[Sym] = f.flatMap(_ collect {case l: Lit => l.sym}).toSet + // debug.patmat("vars "+ vars) + // the negation of a model -(S1=True/False /\ ... /\ SN=True/False) = clause(S1=False/True, ...., SN=False/True) + def negateModel(m: Model) = clause(m.toSeq.map{ case (sym, pos) => Lit(sym, !pos) } : _*) + + def findAllModels(f: Formula, models: List[Model], recursionDepthAllowed: Int = 10): List[Model]= + if (recursionDepthAllowed == 0) models + else { + debug.patmat("find all models for\n"+ cnfString(f)) + val model = findModelFor(f) + // if we found a solution, conjunct the formula with the model's negation and recurse + if (model ne NoModel) { + val unassigned = (vars -- model.keySet).toList + debug.patmat("unassigned "+ unassigned +" in "+ model) + def force(lit: Lit) = { + val model = withLit(findModelFor(dropUnit(f, lit)), lit) + if (model ne NoModel) List(model) + else Nil + } + val forced = unassigned flatMap { s => + force(Lit(s, true)) ++ force(Lit(s, false)) + } + debug.patmat("forced "+ forced) + val negated = negateModel(model) + findAllModels(f :+ negated, model :: (forced ++ models), recursionDepthAllowed - 1) + } + else models + } + + findAllModels(f, Nil) + } + + private def withLit(res: Model, l: Lit): Model = if (res eq NoModel) NoModel else res + (l.sym -> l.pos) + private def dropUnit(f: Formula, unitLit: Lit): Formula = { + val negated = -unitLit + // drop entire clauses that are trivially true + // (i.e., disjunctions that contain the literal we're making true in the returned model), + // and simplify clauses by dropping the negation of the literal we're making true + // (since False \/ X == X) + val dropped = formulaBuilderSized(f.size) + for { + clause <- f + if !(clause contains unitLit) + } dropped += (clause - negated) + dropped + } + + def findModelFor(f: Formula): Model = { + @inline def orElse(a: Model, b: => Model) = if (a ne NoModel) a else b + + debug.patmat("DPLL\n"+ cnfString(f)) + + val start = if (Statistics.canEnable) Statistics.startTimer(patmatAnaDPLL) else null + + val satisfiableWithModel: Model = + if (f isEmpty) EmptyModel + else if(f exists (_.isEmpty)) NoModel + else f.find(_.size == 1) match { + case Some(unitClause) => + val unitLit = unitClause.head + // debug.patmat("unit: "+ unitLit) + withLit(findModelFor(dropUnit(f, unitLit)), unitLit) + case _ => + // partition symbols according to whether they appear in positive and/or negative literals + val pos = new mutable.HashSet[Sym]() + val neg = new mutable.HashSet[Sym]() + f.foreach{_.foreach{ lit => + if (lit.pos) pos += lit.sym else neg += lit.sym + }} + // appearing in both positive and negative + val impures = pos intersect neg + // appearing only in either positive/negative positions + val pures = (pos ++ neg) -- impures + + if (pures nonEmpty) { + val pureSym = pures.head + // turn it back into a literal + // (since equality on literals is in terms of equality + // of the underlying symbol and its positivity, simply construct a new Lit) + val pureLit = Lit(pureSym, pos(pureSym)) + // debug.patmat("pure: "+ pureLit +" pures: "+ pures +" impures: "+ impures) + val simplified = f.filterNot(_.contains(pureLit)) + withLit(findModelFor(simplified), pureLit) + } else { + val split = f.head.head + // debug.patmat("split: "+ split) + orElse(findModelFor(f :+ clause(split)), findModelFor(f :+ clause(-split))) + } + } + + if (Statistics.canEnable) Statistics.stopTimer(patmatAnaDPLL, start) + + satisfiableWithModel + } + } +} diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index c4ae18ba48..01ae0a7a94 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1015,7 +1015,7 @@ trait Implicits { args foreach (getParts(_)) } } else if (sym.isAliasType) { - getParts(tp.dealias) + getParts(tp.normalize) // SI-7180 Normalize needed to expand HK type refs } else if (sym.isAbstractType) { getParts(tp.bounds.hi) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 341dbfbe1f..7a3ab00578 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -908,6 +908,7 @@ trait Namers extends MethodSynthesis { // to use. clazz is the ModuleClass. sourceModule works also for classes defined in methods. val module = clazz.sourceModule for (cda <- module.attachments.get[ConstructorDefaultsAttachment]) { + debuglog(s"Storing the template namer in the ConstructorDefaultsAttachment of ${module.debugLocationString}.") cda.companionModuleClassNamer = templateNamer } val classTp = ClassInfoType(parents, decls, clazz) @@ -1229,8 +1230,11 @@ trait Namers extends MethodSynthesis { // module's templateNamer to classAndNamerOfModule module.attachments.get[ConstructorDefaultsAttachment] match { // by martin: the null case can happen in IDE; this is really an ugly hack on top of an ugly hack but it seems to work - // later by lukas: disabled when fixing SI-5975, i think it cannot happen anymore - case Some(cda) /*if cma.companionModuleClassNamer == null*/ => + case Some(cda) => + if (cda.companionModuleClassNamer == null) { + debugwarn(s"SI-6576 The companion module namer for $meth was unexpectedly null") + return + } val p = (cda.classWithDefault, cda.companionModuleClassNamer) moduleNamer = Some(p) p diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9dde952d25..fcf7ba6efb 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -222,8 +222,13 @@ trait Typers extends Modes with Adaptations with Tags { new SubstWildcardMap(tparams).apply(tp) case TypeRef(_, sym, _) if sym.isAliasType => val tp0 = tp.dealias - val tp1 = dropExistential(tp0) - if (tp1 eq tp0) tp else tp1 + if (tp eq tp0) { + debugwarn(s"dropExistential did not progress dealiasing $tp, see SI-7126") + tp + } else { + val tp1 = dropExistential(tp0) + if (tp1 eq tp0) tp else tp1 + } case _ => tp } @@ -1818,7 +1823,9 @@ trait Typers extends Modes with Adaptations with Tags { def pkgObjectWarning(m : Symbol, mdef : ModuleDef, restricted : String) = { val pkgName = mdef.symbol.ownerChain find (_.isPackage) map (_.decodedName) getOrElse mdef.symbol.toString - context.warning(if (m.pos.isDefined) m.pos else mdef.pos, s"${m} should be placed directly in package ${pkgName} instead of package object ${pkgName}. Under some circumstances companion objects and case classes in package objects can fail to recompile. See https://issues.scala-lang.org/browse/SI-5954.") + val pos = if (m.pos.isDefined) m.pos else mdef.pos + debugwarn(s"${m} should be placed directly in package ${pkgName} instead of package object ${pkgName}. Under some circumstances companion objects and case classes in package objects can fail to recompile. See https://issues.scala-lang.org/browse/SI-5954.") + debugwarn(pos.lineContent + (if (pos.isDefined) " " * (pos.column - 1) + "^" else "")) } } @@ -5285,8 +5292,7 @@ trait Typers extends Modes with Adaptations with Tags { def typedDocDef(docdef: DocDef) = { if (forScaladoc && (sym ne null) && (sym ne NoSymbol)) { val comment = docdef.comment - docComments(sym) = comment - comment.defineVariables(sym) + fillDocComment(sym, comment) val typer1 = newTyper(context.makeNewScope(tree, context.owner)) for (useCase <- comment.useCases) { typer1.silent(_.typedUseCase(useCase)) match { diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 93fafda463..c05c59d5ff 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -352,19 +352,15 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => lazy val importer = compiler.mkImporter(u) lazy val exporter = importer.reverse - private[this] val toolBoxLock = new Object - - def typeCheck(tree: u.Tree, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = toolBoxLock.synchronized { - compiler.withCleanupCaches { - if (compiler.settings.verbose.value) println("importing "+tree+", expectedType = "+expectedType) - var ctree: compiler.Tree = importer.importTree(tree) - var cexpectedType: compiler.Type = importer.importType(expectedType) - - if (compiler.settings.verbose.value) println("typing "+ctree+", expectedType = "+expectedType) - val ttree: compiler.Tree = compiler.typeCheck(ctree, cexpectedType, silent = silent, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled) - val uttree = exporter.importTree(ttree) - uttree - } + def typeCheck(tree: u.Tree, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = compiler.withCleanupCaches { + if (compiler.settings.verbose.value) println("importing "+tree+", expectedType = "+expectedType) + var ctree: compiler.Tree = importer.importTree(tree) + var cexpectedType: compiler.Type = importer.importType(expectedType) + + if (compiler.settings.verbose.value) println("typing "+ctree+", expectedType = "+expectedType) + val ttree: compiler.Tree = compiler.typeCheck(ctree, cexpectedType, silent = silent, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled) + val uttree = exporter.importTree(ttree) + uttree } def inferImplicitValue(pt: u.Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: u.Position = u.NoPosition): u.Tree = { @@ -376,28 +372,26 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => inferImplicit(tree, viewTpe, isView = true, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = pos) } - private def inferImplicit(tree: u.Tree, pt: u.Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: u.Position): u.Tree = toolBoxLock.synchronized { - compiler.withCleanupCaches { - if (compiler.settings.verbose.value) println("importing "+pt, ", tree = "+tree+", pos = "+pos) - var ctree: compiler.Tree = importer.importTree(tree) - var cpt: compiler.Type = importer.importType(pt) - var cpos: compiler.Position = importer.importPosition(pos) - - if (compiler.settings.verbose.value) println("inferring implicit %s of type %s, macros = %s".format(if (isView) "view" else "value", pt, !withMacrosDisabled)) - val itree: compiler.Tree = compiler.inferImplicit(ctree, cpt, isView = isView, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = cpos) - val uitree = exporter.importTree(itree) - uitree - } + private def inferImplicit(tree: u.Tree, pt: u.Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: u.Position): u.Tree = compiler.withCleanupCaches { + if (compiler.settings.verbose.value) println("importing "+pt, ", tree = "+tree+", pos = "+pos) + var ctree: compiler.Tree = importer.importTree(tree) + var cpt: compiler.Type = importer.importType(pt) + var cpos: compiler.Position = importer.importPosition(pos) + + if (compiler.settings.verbose.value) println("inferring implicit %s of type %s, macros = %s".format(if (isView) "view" else "value", pt, !withMacrosDisabled)) + val itree: compiler.Tree = compiler.inferImplicit(ctree, cpt, isView = isView, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = cpos) + val uitree = exporter.importTree(itree) + uitree } - def resetAllAttrs(tree: u.Tree): u.Tree = toolBoxLock.synchronized { + def resetAllAttrs(tree: u.Tree): u.Tree = { val ctree: compiler.Tree = importer.importTree(tree) val ttree: compiler.Tree = compiler.resetAllAttrs(ctree) val uttree = exporter.importTree(ttree) uttree } - def resetLocalAttrs(tree: u.Tree): u.Tree = toolBoxLock.synchronized { + def resetLocalAttrs(tree: u.Tree): u.Tree = { val ctree: compiler.Tree = importer.importTree(tree) val ttree: compiler.Tree = compiler.resetLocalAttrs(ctree) val uttree = exporter.importTree(ttree) @@ -407,14 +401,14 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => def showAttributed(tree: u.Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = compiler.showAttributed(importer.importTree(tree), printTypes, printIds, printKinds) - def parse(code: String): u.Tree = toolBoxLock.synchronized { + def parse(code: String): u.Tree = { if (compiler.settings.verbose.value) println("parsing "+code) val ctree: compiler.Tree = compiler.parse(code) val utree = exporter.importTree(ctree) utree } - def compile(tree: u.Tree): () => Any = toolBoxLock.synchronized { + def compile(tree: u.Tree): () => Any = { if (compiler.settings.verbose.value) println("importing "+tree) var ctree: compiler.Tree = importer.importTree(tree) diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index 696bc4ab5c..2bb5bd1df9 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -1111,7 +1111,7 @@ trait Iterator[+A] extends TraversableOnce[A] { * $willNotTerminateInf */ def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Unit = { - require(start >= 0 && start < xs.length, s"start $start out of range ${xs.length}") + require(start >= 0 && (start < xs.length || xs.length == 0), s"start $start out of range ${xs.length}") var i = start val end = start + math.min(len, xs.length - start) while (i < end && hasNext) { diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index 9765e7c52f..2d6952ff92 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -643,6 +643,10 @@ object List extends SeqFactory[List] { } /** Only used for list serialization */ +@SerialVersionUID(0L - 8287891243975527522L) +private[scala] case object ListSerializeStart + +/** Only used for list serialization */ @SerialVersionUID(0L - 8476791151975527571L) private[scala] case object ListSerializeEnd diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 02c10700b1..802e16605d 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -77,7 +77,6 @@ extends scala.collection.AbstractSeq[Int] final val terminalElement = start + numRangeElements * step override def last = if (isEmpty) Nil.last else lastElement - override def head = if (isEmpty) Nil.head else start override def min[A1 >: Int](implicit ord: Ordering[A1]): Int = if (ord eq Ordering.Int) { diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala index bb938a7aeb..25ba7e4ce6 100644 --- a/src/library/scala/collection/mutable/ArrayOps.scala +++ b/src/library/scala/collection/mutable/ArrayOps.scala @@ -76,18 +76,21 @@ trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParalleliza * @return An array obtained by replacing elements of this arrays with rows the represent. */ def transpose[U](implicit asArray: T => Array[U]): Array[Array[U]] = { - def mkRowBuilder() = Array.newBuilder(ClassTag[U](arrayElementClass(elementClass))) - val bs = asArray(head) map (_ => mkRowBuilder()) - for (xs <- this) { - var i = 0 - for (x <- asArray(xs)) { - bs(i) += x - i += 1 + val bb: Builder[Array[U], Array[Array[U]]] = Array.newBuilder(ClassTag[Array[U]](elementClass)) + if (isEmpty) bb.result() + else { + def mkRowBuilder() = Array.newBuilder(ClassTag[U](arrayElementClass(elementClass))) + val bs = asArray(head) map (_ => mkRowBuilder()) + for (xs <- this) { + var i = 0 + for (x <- asArray(xs)) { + bs(i) += x + i += 1 + } } + for (b <- bs) bb += b.result() + bb.result() } - val bb: Builder[Array[U], Array[Array[U]]] = Array.newBuilder(ClassTag[Array[U]](elementClass)) - for (b <- bs) bb += b.result - bb.result } def seq = thisCollection diff --git a/src/library/scala/collection/mutable/MutableList.scala b/src/library/scala/collection/mutable/MutableList.scala index fd92d2e555..bc6272bfdb 100644 --- a/src/library/scala/collection/mutable/MutableList.scala +++ b/src/library/scala/collection/mutable/MutableList.scala @@ -61,7 +61,8 @@ extends AbstractSeq[A] tl } - protected final def tailImpl(tl: MutableList[A]) { + // this method must be private for binary compatibility + private final def tailImpl(tl: MutableList[A]) { require(nonEmpty, "tail of empty list") tl.first0 = first0.tail tl.len = len - 1 diff --git a/src/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala index b947fa3cca..8ef5f6aeb7 100644 --- a/src/library/scala/collection/mutable/Queue.scala +++ b/src/library/scala/collection/mutable/Queue.scala @@ -167,6 +167,13 @@ extends MutableList[A] */ def front: A = head + // this method (duplicated from MutableList) must be private for binary compatibility + private final def tailImpl(tl: Queue[A]) { + require(nonEmpty, "tail of empty list") + tl.first0 = first0.tail + tl.len = len - 1 + tl.last0 = if (tl.len == 0) tl.first0 else last0 + } // TODO - Don't override this just for new to create appropriate type.... override def tail: Queue[A] = { diff --git a/src/library/scala/concurrent/BatchingExecutor.scala b/src/library/scala/concurrent/BatchingExecutor.scala deleted file mode 100644 index a0d7aaea47..0000000000 --- a/src/library/scala/concurrent/BatchingExecutor.scala +++ /dev/null @@ -1,117 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.concurrent - -import java.util.concurrent.Executor -import scala.annotation.tailrec - -/** - * Mixin trait for an Executor - * which groups multiple nested `Runnable.run()` calls - * into a single Runnable passed to the original - * Executor. This can be a useful optimization - * because it bypasses the original context's task - * queue and keeps related (nested) code on a single - * thread which may improve CPU affinity. However, - * if tasks passed to the Executor are blocking - * or expensive, this optimization can prevent work-stealing - * and make performance worse. Also, some ExecutionContext - * may be fast enough natively that this optimization just - * adds overhead. - * The default ExecutionContext.global is already batching - * or fast enough not to benefit from it; while - * `fromExecutor` and `fromExecutorService` do NOT add - * this optimization since they don't know whether the underlying - * executor will benefit from it. - * A batching executor can create deadlocks if code does - * not use `scala.concurrent.blocking` when it should, - * because tasks created within other tasks will block - * on the outer task completing. - * This executor may run tasks in any order, including LIFO order. - * There are no ordering guarantees. - * - * WARNING: The underlying Executor's execute-method must not execute the submitted Runnable - * in the calling thread synchronously. It must enqueue/handoff the Runnable. - */ -private[concurrent] trait BatchingExecutor extends Executor { - - // invariant: if "_tasksLocal.get ne null" then we are inside BatchingRunnable.run; if it is null, we are outside - private val _tasksLocal = new ThreadLocal[List[Runnable]]() - - private class Batch(val initial: List[Runnable]) extends Runnable with BlockContext { - private var parentBlockContext: BlockContext = _ - // this method runs in the delegate ExecutionContext's thread - override def run(): Unit = { - require(_tasksLocal.get eq null) - - val prevBlockContext = BlockContext.current - BlockContext.withBlockContext(this) { - try { - parentBlockContext = prevBlockContext - - @tailrec def processBatch(batch: List[Runnable]): Unit = batch match { - case Nil => () - case head :: tail => - _tasksLocal set tail - try { - head.run() - } catch { - case t: Throwable => - // if one task throws, move the - // remaining tasks to another thread - // so we can throw the exception - // up to the invoking executor - val remaining = _tasksLocal.get - _tasksLocal set Nil - unbatchedExecute(new Batch(remaining)) //TODO what if this submission fails? - throw t // rethrow - } - processBatch(_tasksLocal.get) // since head.run() can add entries, always do _tasksLocal.get here - } - - processBatch(initial) - } finally { - _tasksLocal.remove() - parentBlockContext = null - } - } - } - - override def blockOn[T](thunk: => T)(implicit permission: CanAwait): T = { - // if we know there will be blocking, we don't want to keep tasks queued up because it could deadlock. - { - val tasks = _tasksLocal.get - _tasksLocal set Nil - if ((tasks ne null) && tasks.nonEmpty) - unbatchedExecute(new Batch(tasks)) - } - - // now delegate the blocking to the previous BC - require(parentBlockContext ne null) - parentBlockContext.blockOn(thunk) - } - } - - protected def unbatchedExecute(r: Runnable): Unit - - override def execute(runnable: Runnable): Unit = { - if (batchable(runnable)) { // If we can batch the runnable - _tasksLocal.get match { - case null => unbatchedExecute(new Batch(List(runnable))) // If we aren't in batching mode yet, enqueue batch - case some => _tasksLocal.set(runnable :: some) // If we are already in batching mode, add to batch - } - } else unbatchedExecute(runnable) // If not batchable, just delegate to underlying - } - - /** Override this to define which runnables will be batched. */ - def batchable(runnable: Runnable): Boolean = runnable match { - case _: OnCompleteRunnable => true - case _ => false - } -} diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala index 0670da137c..6b6ad29074 100644 --- a/src/library/scala/concurrent/Future.scala +++ b/src/library/scala/concurrent/Future.scala @@ -675,11 +675,111 @@ object Future { // by just not ever using it itself. scala.concurrent // doesn't need to create defaultExecutionContext as // a side effect. - private[concurrent] object InternalCallbackExecutor extends ExecutionContext with BatchingExecutor { - override protected def unbatchedExecute(r: Runnable): Unit = - r.run() + private[concurrent] object InternalCallbackExecutor extends ExecutionContext with java.util.concurrent.Executor { override def reportFailure(t: Throwable): Unit = throw new IllegalStateException("problem in scala.concurrent internal callback", t) + + /** + * The BatchingExecutor trait had to be inlined into InternalCallbackExecutor for binary compatibility. + * + * BatchingExecutor is a trait for an Executor + * which groups multiple nested `Runnable.run()` calls + * into a single Runnable passed to the original + * Executor. This can be a useful optimization + * because it bypasses the original context's task + * queue and keeps related (nested) code on a single + * thread which may improve CPU affinity. However, + * if tasks passed to the Executor are blocking + * or expensive, this optimization can prevent work-stealing + * and make performance worse. Also, some ExecutionContext + * may be fast enough natively that this optimization just + * adds overhead. + * The default ExecutionContext.global is already batching + * or fast enough not to benefit from it; while + * `fromExecutor` and `fromExecutorService` do NOT add + * this optimization since they don't know whether the underlying + * executor will benefit from it. + * A batching executor can create deadlocks if code does + * not use `scala.concurrent.blocking` when it should, + * because tasks created within other tasks will block + * on the outer task completing. + * This executor may run tasks in any order, including LIFO order. + * There are no ordering guarantees. + * + * WARNING: The underlying Executor's execute-method must not execute the submitted Runnable + * in the calling thread synchronously. It must enqueue/handoff the Runnable. + */ + // invariant: if "_tasksLocal.get ne null" then we are inside BatchingRunnable.run; if it is null, we are outside + private val _tasksLocal = new ThreadLocal[List[Runnable]]() + + private class Batch(val initial: List[Runnable]) extends Runnable with BlockContext { + private[this] var parentBlockContext: BlockContext = _ + // this method runs in the delegate ExecutionContext's thread + override def run(): Unit = { + require(_tasksLocal.get eq null) + + val prevBlockContext = BlockContext.current + BlockContext.withBlockContext(this) { + try { + parentBlockContext = prevBlockContext + + @tailrec def processBatch(batch: List[Runnable]): Unit = batch match { + case Nil => () + case head :: tail => + _tasksLocal set tail + try { + head.run() + } catch { + case t: Throwable => + // if one task throws, move the + // remaining tasks to another thread + // so we can throw the exception + // up to the invoking executor + val remaining = _tasksLocal.get + _tasksLocal set Nil + unbatchedExecute(new Batch(remaining)) //TODO what if this submission fails? + throw t // rethrow + } + processBatch(_tasksLocal.get) // since head.run() can add entries, always do _tasksLocal.get here + } + + processBatch(initial) + } finally { + _tasksLocal.remove() + parentBlockContext = null + } + } + } + + override def blockOn[T](thunk: => T)(implicit permission: CanAwait): T = { + // if we know there will be blocking, we don't want to keep tasks queued up because it could deadlock. + { + val tasks = _tasksLocal.get + _tasksLocal set Nil + if ((tasks ne null) && tasks.nonEmpty) + unbatchedExecute(new Batch(tasks)) + } + + // now delegate the blocking to the previous BC + require(parentBlockContext ne null) + parentBlockContext.blockOn(thunk) + } + } + + override def execute(runnable: Runnable): Unit = runnable match { + // If we can batch the runnable + case _: OnCompleteRunnable => + _tasksLocal.get match { + case null => unbatchedExecute(new Batch(List(runnable))) // If we aren't in batching mode yet, enqueue batch + case some => _tasksLocal.set(runnable :: some) // If we are already in batching mode, add to batch + } + + // If not batchable, just delegate to underlying + case _ => + unbatchedExecute(runnable) + } + + private def unbatchedExecute(r: Runnable): Unit = r.run() } } diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala index 77625e381c..0aa6b37ffc 100644 --- a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala +++ b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala @@ -19,16 +19,16 @@ import scala.util.control.NonFatal private[scala] class ExecutionContextImpl private[impl] (es: Executor, reporter: Throwable => Unit) extends ExecutionContextExecutor { + // Placed here since the creation of the executor needs to read this val + private[this] val uncaughtExceptionHandler: Thread.UncaughtExceptionHandler = new Thread.UncaughtExceptionHandler { + def uncaughtException(thread: Thread, cause: Throwable): Unit = reporter(cause) + } val executor: Executor = es match { case null => createExecutorService case some => some } - private val uncaughtExceptionHandler: Thread.UncaughtExceptionHandler = new Thread.UncaughtExceptionHandler { - def uncaughtException(thread: Thread, cause: Throwable): Unit = reporter(cause) - } - // Implement BlockContext on FJP threads class DefaultThreadFactory(daemonic: Boolean) extends ThreadFactory with ForkJoinPool.ForkJoinWorkerThreadFactory { def wire[T <: Thread](thread: T): T = { @@ -96,11 +96,24 @@ private[scala] class ExecutionContextImpl private[impl] (es: Executor, reporter: } } + def execute(runnable: Runnable): Unit = executor match { case fj: ForkJoinPool => val fjt = runnable match { case t: ForkJoinTask[_] => t - case r => new ExecutionContextImpl.AdaptedForkJoinTask(r) + case runnable => new ForkJoinTask[Unit] { + final override def setRawResult(u: Unit): Unit = () + final override def getRawResult(): Unit = () + final override def exec(): Boolean = try { runnable.run(); true } catch { + case anything: Throwable ⇒ + val t = Thread.currentThread + t.getUncaughtExceptionHandler match { + case null ⇒ + case some ⇒ some.uncaughtException(t, anything) + } + throw anything + } + } } Thread.currentThread match { case fjw: ForkJoinWorkerThread if fjw.getPool eq fj => fjt.fork() @@ -112,23 +125,7 @@ private[scala] class ExecutionContextImpl private[impl] (es: Executor, reporter: def reportFailure(t: Throwable) = reporter(t) } - private[concurrent] object ExecutionContextImpl { - - final class AdaptedForkJoinTask(runnable: Runnable) extends ForkJoinTask[Unit] { - final override def setRawResult(u: Unit): Unit = () - final override def getRawResult(): Unit = () - final override def exec(): Boolean = try { runnable.run(); true } catch { - case anything: Throwable ⇒ - val t = Thread.currentThread - t.getUncaughtExceptionHandler match { - case null ⇒ - case some ⇒ some.uncaughtException(t, anything) - } - throw anything - } - } - def fromExecutor(e: Executor, reporter: Throwable => Unit = ExecutionContext.defaultReporter): ExecutionContextImpl = new ExecutionContextImpl(e, reporter) def fromExecutorService(es: ExecutorService, reporter: Throwable => Unit = ExecutionContext.defaultReporter): ExecutionContextImpl with ExecutionContextExecutorService = new ExecutionContextImpl(es, reporter) with ExecutionContextExecutorService { diff --git a/src/library/scala/util/Random.scala b/src/library/scala/util/Random.scala index 2b11594f66..24c4cd7a32 100644 --- a/src/library/scala/util/Random.scala +++ b/src/library/scala/util/Random.scala @@ -17,7 +17,7 @@ import scala.language.{implicitConversions, higherKinds} * @author Stephane Micheloud * */ -class Random(val self: java.util.Random) extends AnyRef with Serializable { +class Random(val self: java.util.Random) { /** Creates a new random number generator using a single long seed. */ def this(seed: Long) = this(new java.util.Random(seed)) diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala index 768ebb055b..3c2b128c52 100644 --- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala +++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala @@ -37,7 +37,7 @@ trait BaseTypeSeqs { * This is necessary because when run from reflection every base type sequence needs to have a * SynchronizedBaseTypeSeq as mixin. */ - class BaseTypeSeq protected[reflect] (private[BaseTypeSeqs] val parents: List[Type], private[BaseTypeSeqs] val elems: Array[Type]) { + class BaseTypeSeq protected[BaseTypeSeqs] (private[BaseTypeSeqs] val parents: List[Type], private[BaseTypeSeqs] val elems: Array[Type]) { self => if (Statistics.canEnable) Statistics.incCounter(baseTypeSeqCount) if (Statistics.canEnable) Statistics.incCounter(baseTypeSeqLenTotal, elems.length) diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 7a3bdff1f8..6e4ca76382 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -1189,7 +1189,7 @@ trait Definitions extends api.StandardDefinitions { /** Is the symbol that of a parent which is added during parsing? */ lazy val isPossibleSyntheticParent = ProductClass.toSet[Symbol] + ProductRootClass + SerializableClass - lazy val boxedValueClassesSet = boxedClass.values.toSet[Symbol] + BoxedUnitClass + private lazy val boxedValueClassesSet = boxedClass.values.toSet[Symbol] + BoxedUnitClass /** Is symbol a value class? */ def isPrimitiveValueClass(sym: Symbol) = ScalaValueClasses contains sym @@ -1248,24 +1248,8 @@ trait Definitions extends api.StandardDefinitions { def init() { if (isInitialized) return - // forcing ScalaPackageClass first thing during startup is important, because syntheticCoreClasses such as AnyRefClass - // need to be entered into ScalaPackageClass, which entails calling ScalaPackageClass.info.decls.enter - // if ScalaPackageClass isn't initialized by that moment, the following will happen for runtime reflection: - // 1) initialization of ScalaPackageClass will trigger unpickling - // 2) unpickling will need to load some auxiliary types such as, for example, String - // 3) to load String, runtime reflection will call mirrorDefining(classOf[String]) - // 4) this, in turn, will call runtimeMirror(classOf[String].getClassLoader) - // 5) for some classloader configurations, the resulting mirror will be different from rootMirror - // 6) in that case, initialization of the resulting mirror will try to import definitions.syntheticCoreClasses into the mirror - // 7) this will force all the lazy vals corresponding to syntheticCoreClasses - // 8) by that time, the completer of ScalaPackageClass will have already called setInfo on ScalaPackageClass, so there won't be any stack overflow - // so far so good, but there's a subtle detail. if forcing of ScalaPackageClass was called by a syntheticCoreClasses lazy val, - // then this lazy val will be entered twice: once during step 7 and once when returning from the original call - // to avoid this we need to initialize ScalaPackageClass first and only then synthesize the core classes - ScalaPackageClass.initialize // force initialization of every symbol that is synthesized or hijacked by the compiler - val forced1 = symbolsNotPresentInBytecode - val forced2 = NoSymbol + val forced = symbolsNotPresentInBytecode isInitialized = true } //init diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala index 80c05666af..0beb8e368f 100644 --- a/src/reflect/scala/reflect/internal/Mirrors.scala +++ b/src/reflect/scala/reflect/internal/Mirrors.scala @@ -239,19 +239,6 @@ trait Mirrors extends api.Mirrors { RootClass.info.decls enter EmptyPackage RootClass.info.decls enter RootPackage - - if (rootOwner != NoSymbol) { - // synthetic core classes are only present in root mirrors - // because Definitions.scala, which initializes and enters them, only affects rootMirror - // therefore we need to enter them manually for non-root mirrors - definitions.syntheticCoreClasses foreach (theirSym => { - val theirOwner = theirSym.owner - assert(theirOwner.isPackageClass, s"theirSym = $theirSym, theirOwner = $theirOwner") - val ourOwner = staticPackage(theirOwner.fullName) - val ourSym = theirSym // just copy the symbol into our branch of the symbol table - ourOwner.info.decls enter ourSym - }) - } } } @@ -275,45 +262,34 @@ trait Mirrors extends api.Mirrors { def mirror = thisMirror.asInstanceOf[Mirror] } - class RootPackage extends ModuleSymbol(rootOwner, NoPosition, nme.ROOTPKG) with RootSymbol { + // This is the package _root_. The actual root cannot be referenced at + // the source level, but _root_ is essentially a function => <root>. + final object RootPackage extends ModuleSymbol(rootOwner, NoPosition, nme.ROOTPKG) with RootSymbol { this setInfo NullaryMethodType(RootClass.tpe) RootClass.sourceModule = this override def isRootPackage = true } - - // This is the package _root_. The actual root cannot be referenced at - // the source level, but _root_ is essentially a function => <root>. - lazy val RootPackage = new RootPackage - - class RootClass extends PackageClassSymbol(rootOwner, NoPosition, tpnme.ROOT) with RootSymbol { - this setInfo rootLoader - - override def isRoot = true - override def isEffectiveRoot = true - override def isNestedClass = false - } - // This is <root>, the actual root of everything except the package _root_. // <root> and _root_ (RootPackage and RootClass) should be the only "well known" // symbols owned by NoSymbol. All owner chains should go through RootClass, // although it is probable that some symbols are created as direct children // of NoSymbol to ensure they will not be stumbled upon. (We should designate // a better encapsulated place for that.) - lazy val RootClass = new RootClass + final object RootClass extends PackageClassSymbol(rootOwner, NoPosition, tpnme.ROOT) with RootSymbol { + this setInfo rootLoader - class EmptyPackage extends ModuleSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { - override def isEmptyPackage = true + override def isRoot = true + override def isEffectiveRoot = true + override def isNestedClass = false } - // The empty package, which holds all top level types without given packages. - lazy val EmptyPackage = new EmptyPackage - - class EmptyPackageClass extends PackageClassSymbol(RootClass, NoPosition, tpnme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { + final object EmptyPackage extends ModuleSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { + override def isEmptyPackage = true + } + final object EmptyPackageClass extends PackageClassSymbol(RootClass, NoPosition, tpnme.EMPTY_PACKAGE_NAME) with WellKnownSymbol { override def isEffectiveRoot = true override def isEmptyPackageClass = true } - - lazy val EmptyPackageClass = new EmptyPackageClass } } diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala index 01ad18d3a0..c78ba72dfb 100644 --- a/src/reflect/scala/reflect/internal/Names.scala +++ b/src/reflect/scala/reflect/internal/Names.scala @@ -21,7 +21,7 @@ trait LowPriorityNames { * @author Martin Odersky * @version 1.0, 05/02/2005 */ -trait Names extends api.Names with LowPriorityNames { self => +trait Names extends api.Names with LowPriorityNames { implicit def promoteTermNamesAsNecessary(name: Name): TermName = name.toTermName // Operations ------------------------------------------------------------- @@ -109,26 +109,6 @@ trait Names extends api.Names with LowPriorityNames { self => protected def newTypeName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TypeName = newTermName(cs, offset, len, cachedString).toTypeName - protected def toTypeName(termName: TermName): TypeName = { - val h = hashValue(chrs, termName.index, termName.len) & HASH_MASK - var n = typeHashtable(h) - while ((n ne null) && n.start != termName.index) - n = n.next - - if (n ne null) n - else termName.createCompanionName(h) - } - - protected def toTermName(typeName: TypeName): TermName = { - val h = hashValue(chrs, typeName.index, typeName.len) & HASH_MASK - var n = termHashtable(h) - while ((n ne null) && n.start != typeName.index) - n = n.next - - if (n ne null) n - else typeName.createCompanionName(h) - } - /** Create a term name from string. */ def newTermName(s: String): TermName = newTermName(s.toCharArray(), 0, s.length(), null) @@ -165,7 +145,7 @@ trait Names extends api.Names with LowPriorityNames { self => * or Strings as Names. Give names the key functions the absence of which * make people want Strings all the time. */ - sealed abstract class Name(protected[Names] val index: Int, protected[Names] val len: Int) extends NameApi { + sealed abstract class Name(protected val index: Int, protected val len: Int) extends NameApi { type ThisNameType >: Null <: Name protected[this] def thisName: ThisNameType @@ -483,21 +463,21 @@ trait Names extends api.Names with LowPriorityNames { self => * TermName_R and TypeName_R recreate it each time toString is called. */ private class TermName_S(index0: Int, len0: Int, hash: Int, override val toString: String) extends TermName(index0, len0, hash) { - @inline final def createCompanionName(h: Int): TypeName = new TypeName_S(index, len, h, toString) + protected def createCompanionName(h: Int): TypeName = new TypeName_S(index, len, h, toString) override def newName(str: String): TermName = newTermNameCached(str) } private class TypeName_S(index0: Int, len0: Int, hash: Int, override val toString: String) extends TypeName(index0, len0, hash) { - @inline final def createCompanionName(h: Int): TermName = new TermName_S(index, len, h, toString) + protected def createCompanionName(h: Int): TermName = new TermName_S(index, len, h, toString) override def newName(str: String): TypeName = newTypeNameCached(str) } private class TermName_R(index0: Int, len0: Int, hash: Int) extends TermName(index0, len0, hash) { - @inline final def createCompanionName(h: Int): TypeName = new TypeName_R(index, len, h) + protected def createCompanionName(h: Int): TypeName = new TypeName_R(index, len, h) override def toString = new String(chrs, index, len) } private class TypeName_R(index0: Int, len0: Int, hash: Int) extends TypeName(index0, len0, hash) { - @inline final def createCompanionName(h: Int): TermName = new TermName_R(index, len, h) + protected def createCompanionName(h: Int): TermName = new TermName_R(index, len, h) override def toString = new String(chrs, index, len) } @@ -510,14 +490,22 @@ trait Names extends api.Names with LowPriorityNames { self => def isTermName: Boolean = true def isTypeName: Boolean = false def toTermName: TermName = this - def toTypeName: TypeName = self.toTypeName(this) + def toTypeName: TypeName = { + val h = hashValue(chrs, index, len) & HASH_MASK + var n = typeHashtable(h) + while ((n ne null) && n.start != index) + n = n.next + + if (n ne null) n + else createCompanionName(h) + } def newName(str: String): TermName = newTermName(str) def companionName: TypeName = toTypeName def subName(from: Int, to: Int): TermName = newTermName(chrs, start + from, to - from) def nameKind = "term" - def createCompanionName(h: Int): TypeName + protected def createCompanionName(h: Int): TypeName } implicit val TermNameTag = ClassTag[TermName](classOf[TermName]) @@ -530,7 +518,15 @@ trait Names extends api.Names with LowPriorityNames { self => typeHashtable(hash) = this def isTermName: Boolean = false def isTypeName: Boolean = true - def toTermName: TermName = self.toTermName(this) + def toTermName: TermName = { + val h = hashValue(chrs, index, len) & HASH_MASK + var n = termHashtable(h) + while ((n ne null) && n.start != index) + n = n.next + + if (n ne null) n + else createCompanionName(h) + } def toTypeName: TypeName = this def newName(str: String): TypeName = newTypeName(str) def companionName: TermName = toTermName diff --git a/src/reflect/scala/reflect/internal/PrivateWithin.scala b/src/reflect/scala/reflect/internal/PrivateWithin.scala deleted file mode 100644 index 9b99b94b41..0000000000 --- a/src/reflect/scala/reflect/internal/PrivateWithin.scala +++ /dev/null @@ -1,23 +0,0 @@ -package scala.reflect -package internal - -import ClassfileConstants._ - -trait PrivateWithin { - self: SymbolTable => - - def importPrivateWithinFromJavaFlags(sym: Symbol, jflags: Int): Symbol = { - if ((jflags & (JAVA_ACC_PRIVATE | JAVA_ACC_PROTECTED | JAVA_ACC_PUBLIC)) == 0) - // See ticket #1687 for an example of when topLevelClass is NoSymbol: it - // apparently occurs when processing v45.3 bytecode. - if (sym.enclosingTopLevelClass != NoSymbol) - sym.privateWithin = sym.enclosingTopLevelClass.owner - - // protected in java means package protected. #3946 - if ((jflags & JAVA_ACC_PROTECTED) != 0) - if (sym.enclosingTopLevelClass != NoSymbol) - sym.privateWithin = sym.enclosingTopLevelClass.owner - - sym - } -}
\ No newline at end of file diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 09d1e649d9..bcda2bc1ae 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -265,8 +265,6 @@ trait StdNames { final val SourceFileATTR: NameType = "SourceFile" final val SyntheticATTR: NameType = "Synthetic" - final val scala_ : NameType = "scala" - def dropSingletonName(name: Name): TypeName = (name dropRight SINGLETON_SUFFIX.length).toTypeName def singletonName(name: Name): TypeName = (name append SINGLETON_SUFFIX).toTypeName def implClassName(name: Name): TypeName = (name append IMPL_CLASS_SUFFIX).toTypeName diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index e096bac990..5ccf81b4b5 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -38,7 +38,6 @@ abstract class SymbolTable extends macros.Universe with StdAttachments with StdCreators with BuildUtils - with PrivateWithin { val gen = new TreeGen { val global: SymbolTable.this.type = SymbolTable.this } @@ -209,8 +208,6 @@ abstract class SymbolTable extends macros.Universe finally popPhase(saved) } - def slowButSafeAtPhase[T](ph: Phase)(op: => T): T = - if (isCompilerUniverse) atPhase(ph)(op) else op /** Since when it is to be "at" a phase is inherently ambiguous, * a couple unambiguously named methods. @@ -223,9 +220,6 @@ abstract class SymbolTable extends macros.Universe @inline final def atPhaseNotLaterThan[T](target: Phase)(op: => T): T = if (isAtPhaseAfter(target)) atPhase(target)(op) else op - def slowButSafeAtPhaseNotLaterThan[T](target: Phase)(op: => T): T = - if (isCompilerUniverse) atPhaseNotLaterThan(target)(op) else op - final def isValid(period: Period): Boolean = period != 0 && runId(period) == currentRunId && { val pid = phaseId(period) @@ -357,6 +351,21 @@ abstract class SymbolTable extends macros.Universe */ implicit val StringContextStripMarginOps: StringContext => StringContextStripMarginOps = util.StringContextStripMarginOps + def importPrivateWithinFromJavaFlags(sym: Symbol, jflags: Int): Symbol = { + import ClassfileConstants._ + if ((jflags & (JAVA_ACC_PRIVATE | JAVA_ACC_PROTECTED | JAVA_ACC_PUBLIC)) == 0) + // See ticket #1687 for an example of when topLevelClass is NoSymbol: it + // apparently occurs when processing v45.3 bytecode. + if (sym.enclosingTopLevelClass != NoSymbol) + sym.privateWithin = sym.enclosingTopLevelClass.owner + + // protected in java means package protected. #3946 + if ((jflags & JAVA_ACC_PROTECTED) != 0) + if (sym.enclosingTopLevelClass != NoSymbol) + sym.privateWithin = sym.enclosingTopLevelClass.owner + + sym + } } object SymbolTableStats { diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index df17e3b751..d9eb48ff2d 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -91,14 +91,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => children } - def selfType = { - if (!isCompilerUniverse && needsInitialize(isFlagRelated = false, mask = 0)) initialize - typeOfThis - } - def baseClasses = info.baseClasses def module = sourceModule def thisPrefix: Type = thisType + def selfType: Type = typeOfThis def typeSignature: Type = { fullyInitializeSymbol(this); info } def typeSignatureIn(site: Type): Type = { fullyInitializeSymbol(this); site memberInfo this } @@ -112,8 +108,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => def setter: Symbol = setter(owner) } - case class SymbolKind(accurate: String, sanitized: String, abbreviation: String) - /** The class for all symbols */ abstract class Symbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: Name) extends SymbolContextApiImpl @@ -899,13 +893,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isInitialized: Boolean = validTo != NoPeriod - /** Some completers call sym.setInfo when still in-flight and then proceed with initialization (e.g. see LazyPackageType) - * setInfo sets _validTo to current period, which means that after a call to setInfo isInitialized will start returning true. - * Unfortunately, this doesn't mean that info becomes ready to be used, because subsequent initialization might change the info. - * Therefore we need this method to distinguish between initialized and really initialized symbol states. - */ - final def isFullyInitialized: Boolean = _validTo != NoPeriod && (flags & LOCKED) == 0 - /** Can this symbol be loaded by a reflective mirror? * * Scalac relies on `ScalaSignature' annotation to retain symbols across compilation runs. @@ -2261,6 +2248,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => else if (isTerm && (!isParameter || isParamAccessor)) "val" else "" + private case class SymbolKind(accurate: String, sanitized: String, abbreviation: String) private def symbolKind: SymbolKind = { var kind = if (isTermMacro) ("macro method", "macro method", "MAC") @@ -3019,8 +3007,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def thisType: Type = { val period = thisTypePeriod if (period != currentPeriod) { - if (!isValid(period)) thisTypeCache = ThisType(this) thisTypePeriod = currentPeriod + if (!isValid(period)) thisTypeCache = ThisType(this) } thisTypeCache } @@ -3096,9 +3084,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def typeOfThis = { val period = typeOfThisPeriod if (period != currentPeriod) { + typeOfThisPeriod = currentPeriod if (!isValid(period)) typeOfThisCache = singleType(owner.thisType, sourceModule) - typeOfThisPeriod = currentPeriod } typeOfThisCache } @@ -3109,9 +3097,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => // Skip a package object class, because the members are also in // the package and we wish to avoid spurious ambiguities as in pos/t3999. if (!isPackageObjectClass) { - implicitMembersCacheValue = tp.implicitMembers implicitMembersCacheKey1 = tp implicitMembersCacheKey2 = tp.decls.elems + implicitMembersCacheValue = tp.implicitMembers } } implicitMembersCacheValue @@ -3219,11 +3207,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => def name = nme.NO_NAME override def name_=(n: Name) = abort("Cannot set NoSymbol's name to " + n) - // Syncnote: no need to synchronize this, because NoSymbol's initialization is triggered by JavaUniverse.init - // which is called in universe's constructor - something that's inherently single-threaded - setInfo(NoType) - privateWithin = this - + synchronized { + setInfo(NoType) + privateWithin = this + } override def info_=(info: Type) = { infos = TypeHistory(1, NoType, null) unlock() diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index 3040486076..3e74b5d22d 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -98,7 +98,8 @@ abstract class TreeInfo { // However, before typing, applications of nullary functional values are also // Apply(function, Nil) trees. To prevent them from being treated as pure, // we check that the callee is a method. - fn.symbol.isMethod && !fn.symbol.isLazy && isExprSafeToInline(fn) + // The callee might also be a Block, which has a null symbol, so we guard against that (SI-7185) + fn.symbol != null && fn.symbol.isMethod && !fn.symbol.isLazy && isExprSafeToInline(fn) case Typed(expr, _) => isExprSafeToInline(expr) case Block(stats, expr) => diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 81e0457916..ea193465ad 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -2066,6 +2066,10 @@ trait Types extends api.Types { self: SymbolTable => def apply(value: Constant) = unique(new UniqueConstantType(value)) } + /* Syncnote: The `volatile` var and `pendingVolatiles` mutable set need not be protected + * with synchronized, because they are accessed only from isVolatile, which is called only from + * Typer. + */ private var volatileRecursions: Int = 0 private val pendingVolatiles = new mutable.HashSet[Symbol] @@ -3179,12 +3183,19 @@ trait Types extends api.Types { self: SymbolTable => * ?TC[?T] <: Any * }}} */ - def unifySimple = ( - (params.isEmpty || tp.typeSymbol == NothingClass || tp.typeSymbol == AnyClass) && { + def unifySimple = { + val sym = tp.typeSymbol + if (sym == NothingClass || sym == AnyClass) { // kind-polymorphic + // SI-7126 if we register some type alias `T=Any`, we can later end + // with malformed types like `T[T]` during type inference in + // `handlePolymorphicCall`. No such problem if we register `Any`. + addBound(sym.tpe) + true + } else if (params.isEmpty) { addBound(tp) true - } - ) + } else false + } /** Full case: involving a check of the form * {{{ @@ -3926,8 +3937,8 @@ trait Types extends api.Types { self: SymbolTable => /** @PP: Unable to see why these apparently constant types should need vals * in every TypeConstraint, I lifted them out. */ - lazy val numericLoBound = IntClass.tpe - lazy val numericHiBound = intersectionType(List(ByteClass.tpe, CharClass.tpe), ScalaPackageClass) + private lazy val numericLoBound = IntClass.tpe + private lazy val numericHiBound = intersectionType(List(ByteClass.tpe, CharClass.tpe), ScalaPackageClass) /** A class expressing upper and lower bounds constraints of type variables, * as well as their instantiations. diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index 4d61e4178a..603fff4f1c 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -853,7 +853,7 @@ abstract class UnPickler { private val p = phase override def complete(sym: Symbol) : Unit = try { val tp = at(i, () => readType(sym.isTerm)) // after NMT_TRANSITION, revert `() => readType(sym.isTerm)` to `readType` - slowButSafeAtPhase(p)(sym setInfo tp) + atPhase(p) (sym setInfo tp) if (currentRunId != definedAtRunId) sym.setInfo(adaptToNewRunMap(tp)) } @@ -871,7 +871,7 @@ abstract class UnPickler { super.complete(sym) var alias = at(j, readSymbol) if (alias.isOverloaded) - alias = slowButSafeAtPhase(picklerPhase)((alias suchThat (alt => sym.tpe =:= sym.owner.thisType.memberType(alt)))) + alias = atPhase(picklerPhase)((alias suchThat (alt => sym.tpe =:= sym.owner.thisType.memberType(alt)))) sym.asInstanceOf[TermSymbol].setAlias(alias) } diff --git a/src/reflect/scala/reflect/runtime/Gil.scala b/src/reflect/scala/reflect/runtime/Gil.scala deleted file mode 100644 index cf6f1431d7..0000000000 --- a/src/reflect/scala/reflect/runtime/Gil.scala +++ /dev/null @@ -1,25 +0,0 @@ -package scala.reflect -package runtime - -private[reflect] trait Gil { - self: SymbolTable => - - // fixme... please... - // there are the following avenues of optimization we discussed with Roland: - // 1) replace PackageScope locks with ConcurrentHashMap, because PackageScope materializers seem to be idempotent - // 2) unlock unpickling completers by verifying that they are idempotent or moving non-idempotent parts - // 3) remove the necessity in global state for isSubType - lazy val gil = new java.util.concurrent.locks.ReentrantLock - - @inline final def gilSynchronized[T](body: => T): T = { - if (isCompilerUniverse) body - else { - try { - gil.lock() - body - } finally { - gil.unlock() - } - } - } -} diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 58ade961a7..3442e3d22e 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -24,9 +24,9 @@ import scala.language.existentials import scala.runtime.{ScalaRunTime, BoxesRunTime} import scala.reflect.internal.util.Collections._ -private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse with TwoWayCaches { thisUniverse: SymbolTable => +private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { thisUniverse: SymbolTable => - lazy val mirrors = new WeakHashMap[ClassLoader, WeakReference[JavaMirror]]() + private lazy val mirrors = new WeakHashMap[ClassLoader, WeakReference[JavaMirror]]() private def createMirror(owner: Symbol, cl: ClassLoader): Mirror = { val jm = new JavaMirror(owner, cl) @@ -46,11 +46,19 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni trait JavaClassCompleter extends FlagAssigningCompleter - def runtimeMirror(cl: ClassLoader): Mirror = gilSynchronized { - mirrors get cl match { - case Some(WeakReference(m)) => m - case _ => createMirror(rootMirror.RootClass, cl) - } + def init() = { + definitions.AnyValClass // force it. + + // establish root association to avoid cyclic dependency errors later + rootMirror.classToScala(classOf[java.lang.Object]).initialize + + // println("initializing definitions") + definitions.init() + } + + def runtimeMirror(cl: ClassLoader): Mirror = mirrors get cl match { + case Some(WeakReference(m)) => m + case _ => createMirror(rootMirror.RootClass, cl) } /** The API of a mirror for a reflective universe */ @@ -63,23 +71,6 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni import definitions._ - override lazy val RootPackage = new RootPackage with SynchronizedTermSymbol - override lazy val RootClass = new RootClass with SynchronizedModuleClassSymbol - override lazy val EmptyPackage = new EmptyPackage with SynchronizedTermSymbol - override lazy val EmptyPackageClass = new EmptyPackageClass with SynchronizedModuleClassSymbol - - override def init() = { - super.init() - - // see an explanation of this in JavaUniverse.init() - RootPackage - RootClass - EmptyPackage - EmptyPackageClass - unpickler - rootLoader - } - /** The lazy type for root. */ override lazy val rootLoader = new LazyType with FlagAgnosticCompleter { @@ -583,7 +574,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni case None => // class does not have a Scala signature; it's a Java class info("translating reflection info for Java " + jclazz) //debug - initClassAndModule(clazz, module, new FromJavaClassCompleter(clazz, module, jclazz)) + initClassModule(clazz, module, new FromJavaClassCompleter(clazz, module, jclazz)) } } } catch { @@ -676,7 +667,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni completeRest() } - def completeRest(): Unit = gilSynchronized { + def completeRest(): Unit = thisUniverse.synchronized { val tparams = clazz.rawInfo.typeParams val parents = try { @@ -695,9 +686,9 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni def enter(sym: Symbol, mods: Int) = (if (jModifier.isStatic(mods)) module.moduleClass else clazz).info.decls enter sym - for (jinner <- jclazz.getDeclaredClasses) - jclassAsScala(jinner) // inner class is entered as a side-effect - // no need to call enter explicitly + for (jinner <- jclazz.getDeclaredClasses) { + enter(jclassAsScala(jinner, clazz), jinner.getModifiers) + } pendingLoadActions = { () => @@ -892,7 +883,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni * The Scala package with given fully qualified name. Unlike `packageNameToScala`, * this one bypasses the cache. */ - private[JavaMirrors] def makeScalaPackage(fullname: String): ModuleSymbol = gilSynchronized { + private[JavaMirrors] def makeScalaPackage(fullname: String): ModuleSymbol = { val split = fullname lastIndexOf '.' val ownerModule: ModuleSymbol = if (split > 0) packageNameToScala(fullname take split) else this.RootPackage @@ -1055,14 +1046,14 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni * @param jclazz The Java class * @return A Scala class symbol that wraps all reflection info of `jclazz` */ - private def jclassAsScala(jclazz: jClass[_]): ClassSymbol = - toScala(classCache, jclazz)(_ jclassAsScala1 _) + private def jclassAsScala(jclazz: jClass[_]): Symbol = jclassAsScala(jclazz, sOwner(jclazz)) - private def jclassAsScala1(jclazz: jClass[_]): ClassSymbol = { - val owner = sOwner(jclazz) + private def jclassAsScala(jclazz: jClass[_], owner: Symbol): ClassSymbol = { val name = scalaSimpleName(jclazz) val completer = (clazz: Symbol, module: Symbol) => new FromJavaClassCompleter(clazz, module, jclazz) - initAndEnterClassAndModule(owner, name, completer)._1 + val (clazz, module) = createClassModule(owner, name, completer) + classCache enter (jclazz, clazz) + clazz } /** @@ -1255,6 +1246,11 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni case _ => abort(s"${sym}.enclosingRootClass = ${sym.enclosingRootClass}, which is not a RootSymbol") } + private lazy val syntheticCoreClasses: Map[(String, Name), Symbol] = { + def mapEntry(sym: Symbol): ((String, Name), Symbol) = (sym.owner.fullName, sym.name) -> sym + Map() ++ (definitions.syntheticCoreClasses map mapEntry) + } + /** 1. If `owner` is a package class (but not the empty package) and `name` is a term name, make a new package * <owner>.<name>, otherwise return NoSymbol. * Exception: If owner is root and a java class with given name exists, create symbol in empty package instead @@ -1264,20 +1260,22 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni override def missingHook(owner: Symbol, name: Name): Symbol = { if (owner.hasPackageFlag) { val mirror = mirrorThatLoaded(owner) + // todo. this makes toolbox tests pass, but it's a mere workaround for SI-5865 +// assert((owner.info decl name) == NoSymbol, s"already exists: $owner . $name") if (owner.isRootSymbol && mirror.tryJavaClass(name.toString).isDefined) return mirror.EmptyPackageClass.info decl name if (name.isTermName && !owner.isEmptyPackageClass) return mirror.makeScalaPackage( if (owner.isRootSymbol) name.toString else owner.fullName+"."+name) - if (name == tpnme.AnyRef && owner.owner.isRoot && owner.name == tpnme.scala_) - // when we synthesize the scala.AnyRef symbol, we need to add it to the scope of the scala package - // the problem is that adding to the scope implies doing something like `owner.info.decls enter anyRef` - // which entails running a completer for the scala package - // which will try to unpickle the stuff in scala/package.class - // which will transitively load scala.AnyRef - // which doesn't exist yet, because it hasn't been added to the scope yet - // this missing hook ties the knot without introducing synchronization problems like before - return definitions.AnyRefClass + syntheticCoreClasses get (owner.fullName, name) match { + case Some(tsym) => + // synthetic core classes are only present in root mirrors + // because Definitions.scala, which initializes and enters them, only affects rootMirror + // therefore we need to enter them manually for non-root mirrors + if (mirror ne thisUniverse.rootMirror) owner.info.decls enter tsym + return tsym + case None => + } } info("*** missing: "+name+"/"+name.isTermName+"/"+owner+"/"+owner.hasPackageFlag+"/"+owner.info.decls.getClass) super.missingHook(owner, name) diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala index cee243fb29..e18435d5b0 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala @@ -17,1040 +17,12 @@ class JavaUniverse extends internal.SymbolTable with ReflectSetup with runtime.S def forInteractive = false def forScaladoc = false - def log(msg: => AnyRef): Unit = if (settings.debug.value) println(" [] "+msg) + def log(msg: => AnyRef): Unit = println(" [] "+msg) type TreeCopier = InternalTreeCopierOps def newStrictTreeCopier: TreeCopier = new StrictTreeCopier def newLazyTreeCopier: TreeCopier = new LazyTreeCopier init() - - def init() { - definitions.init() - - // workaround for http://groups.google.com/group/scala-internals/browse_thread/thread/97840ba4fd37b52e - // constructors are by definition single-threaded, so we initialize all lazy vals (and local object) in advance - // in order to avoid deadlocks later (e.g. one thread holds a global reflection lock and waits for definitions.Something to initialize, - // whereas another thread holds a definitions.Something initialization lock and needs a global reflection lock to complete the initialization) - - // the list of lzycompute methods is mined by a simple python script - // #!/usr/bin/env python - // import os, sys, re, glob, fnmatch - // from subprocess import check_call, check_output - // root = check_output(["git", "rev-parse", "--show-toplevel"]).strip() - // root = os.path.join(root, "build/quick/classes/reflect/scala/reflect") - // classfiles = [] - // for container, dirnames, filenames in os.walk(root): - // for filename in fnmatch.filter(filenames, '*.class'): - // classfiles.append(os.path.join(container, filename)) - // for classfile in classfiles: - // blob = open(classfile).read() - // for found in re.findall(r"[\w\$]+\$lzycompute", blob): - // print found, "in", classfile[len(root) + 1:] - - - // ======== Exprs ======== - // NOFORCE: tree$lzycompute in api/Exprs$ExprImpl.class - // NOFORCE: staticType$lzycompute in api/Exprs$ExprImpl.class - // NOFORCE: value$lzycompute in api/Exprs$ExprImpl.class - // FORCE: Expr$lzycompute in api/Universe.class - // FORCE: FixedMirrorTreeCreator$lzycompute in internal/SymbolTable.class - // probably not used by runtime reflection, but better be safe than sorry - Expr - FixedMirrorTreeCreator - - // ======== Type tags ======== - // FORCE: WeakTypeTag$lzycompute in api/Universe.class - // FORCE: TypeTag$lzycompute in api/Universe.class - // NOFORCE: tpe$lzycompute in api/TypeTags$WeakTypeTagImpl.class - // TODO: validate that scala-reflect never uses TypeTags itself (we have StdTags, but they are in compiler, so it should be okay) - // FORCE: tpe$lzycompute in api/TypeTags$PredefTypeTag.class - // FORCE: FixedMirrorTypeCreator$lzycompute in internal/SymbolTable.class - // probably not used by runtime reflection, but better be safe than sorry - WeakTypeTag - TypeTag - TypeTag.Byte.tpe - TypeTag.Short.tpe - TypeTag.Char.tpe - TypeTag.Int.tpe - TypeTag.Long.tpe - TypeTag.Float.tpe - TypeTag.Double.tpe - TypeTag.Boolean.tpe - TypeTag.Unit.tpe - TypeTag.Any.tpe - TypeTag.AnyVal.tpe - TypeTag.AnyRef.tpe - TypeTag.Object.tpe - TypeTag.Nothing.tpe - TypeTag.Null.tpe - FixedMirrorTypeCreator - - // ======== Annotations ======== - // NOFORCE: isTrivial$lzycompute in internal/AnnotationInfos$AnnotationInfo.class - // looks like isTrivial just calls into Type.isTrivial, which cannot go back to the calling annotationinfo, so we're safe from deadlocks - // NOFORCE: forcedInfo$lzycompute in internal/AnnotationInfos$LazyAnnotationInfo.class - // I can't immediately see that the completer cannot call into one of the methods of the calling AnnotationInfo - // TODO: leaving this as a todo and for now we're at a mercy of chance - // NOFORCE: encodedBytes$lzycompute in internal/AnnotationInfos$ScalaSigBytes.class - // NOFORCE: sevenBitsMayBeZero$lzycompute in internal/AnnotationInfos$ScalaSigBytes.class - // these are just bit/byte twiddling, they don't call into reflection at all - // FORCE: UnmappableAnnotArg$lzycompute in internal/SymbolTable.class - // FORCE: LiteralAnnotArg$lzycompute in internal/SymbolTable.class - // FORCE: ArrayAnnotArg$lzycompute in internal/SymbolTable.class - // FORCE: NestedAnnotArg$lzycompute in internal/SymbolTable.class - // FORCE: ScalaSigBytes$lzycompute in internal/SymbolTable.class - // FORCE: AnnotationInfo$lzycompute in internal/SymbolTable.class - // FORCE: Annotation$lzycompute in internal/SymbolTable.class - // FORCE: UnmappableAnnotation$lzycompute in internal/SymbolTable.class - // FORCE: ThrownException$lzycompute in internal/SymbolTable.class - UnmappableAnnotArg - LiteralAnnotArg - ArrayAnnotArg - NestedAnnotArg - ScalaSigBytes - AnnotationInfo - Annotation - UnmappableAnnotation - ThrownException - - // ======== Importers ======== - // NOFORCE: symMap$lzycompute in internal/Importers$StandardImporter.class - // NOFORCE: tpeMap$lzycompute in internal/Importers$StandardImporter.class - // NOFORCE: fixups$lzycompute in internal/Importers$StandardImporter.class - // NOFORCE: reverse$lzycompute in internal/Importers$StandardImporter.class - // these are simple constructors, which don't call into reflection - // actually the first three of those could be non-lazy - - // ======== Mirrors ======== - // NOFORCE: RootPackage$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: RootClass$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: EmptyPackage$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: EmptyPackageClass$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: RootPackage$lzycompute in internal/Mirrors$Roots.class - // NOFORCE: RootClass$lzycompute in internal/Mirrors$Roots.class - // NOFORCE: EmptyPackage$lzycompute in internal/Mirrors$Roots.class - // NOFORCE: EmptyPackageClass$lzycompute in internal/Mirrors$Roots.class - // NOFORCE: unpickler$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: rootLoader$lzycompute in runtime/JavaMirrors$JavaMirror.class - // these are already forced in JavaMirror.init() - // NOFORCE: universe$lzycompute in runtime/package$.class - // that's the scala.reflect.runtime.universe - // FORCE: 5scala$reflect$runtime$JavaMirrors$$mirrors$lzycompute in runtime/JavaUniverse.class - rootMirror - mirrors - - // ======== Names ======== - // FORCE: tpnme$lzycompute in internal/SymbolTable.class - // FORCE: fulltpnme$lzycompute in internal/SymbolTable.class - // FORCE: binarynme$lzycompute in internal/SymbolTable.class - // FORCE: nme$lzycompute in internal/SymbolTable.class - // FORCE: sn$lzycompute in internal/SymbolTable.class - // FORCE: raw$lzycompute in internal/StdNames$TermNames.class - // FORCE: Ascala$reflect$internal$SymbolTable$$SimpleNameOrdering$lzycompute in internal/SymbolTable.class - // FORCE: 6scala$reflect$internal$StdNames$$compactify$lzycompute in internal/SymbolTable.class - // probably most of these are already initialized by definitions.init() - // but better be safe than sorry - // NOFORCE: GetClassLoader$lzycompute in internal/StdNames$MSILNames.class - // MSIL has been eol'd. probably we shouldn't care anymore - // runtime reflection doesn't support MSIL anyways - tpnme - fulltpnme - binarynme - nme - sn - nme.raw - lowPriorityNameOrdering - nme.flattenedName() - - // ======== Attachments ======== - // FORCE: BackquotedIdentifierAttachment$lzycompute in internal/SymbolTable.class - // FORCE: CompoundTypeTreeOriginalAttachment$lzycompute in internal/SymbolTable.class - // FORCE: MacroExpansionAttachment$lzycompute in internal/SymbolTable.class - // FORCE: SuppressMacroExpansionAttachment$lzycompute in internal/SymbolTable.class - // probably not used by runtime reflection - // but better be safe than sorry - BackquotedIdentifierAttachment - CompoundTypeTreeOriginalAttachment - MacroExpansionAttachment - SuppressMacroExpansionAttachment - - // ======== TreeInfo ======== - // NOFORCE: DynamicUpdate$lzycompute in internal/TreeInfo.class - // NOFORCE: DynamicApplication$lzycompute in internal/TreeInfo.class - // NOFORCE: DynamicApplicationNamed$lzycompute in internal/TreeInfo.class - // NOFORCE: MacroImplReference$lzycompute in internal/TreeInfo.class - // NOFORCE: StripCast$lzycompute in internal/TreeInfo.class - // NOFORCE: Applied$lzycompute in internal/TreeInfo.class - // NOFORCE: IsTrue$lzycompute in internal/TreeInfo.class - // NOFORCE: IsFalse$lzycompute in internal/TreeInfo.class - // NOFORCE: IsIf$lzycompute in internal/TreeInfo.class - // TreeInfo is never instantiated by runtime reflection - - // ======== Miscellaneous ======== - // FORCE: BooleanFlag$lzycompute in api/Universe.class - // FORCE: traceSymbols$lzycompute in internal/SymbolTable.class - // FORCE: perRunCaches$lzycompute in internal/SymbolTable.class - // FORCE: typeDebug$lzycompute in internal/SymbolTable.class - // FORCE: str$lzycompute in internal/TypeDebugging$typeDebug$.class - // FORCE: ConsoleWriter$lzycompute in internal/SymbolTable.class - // FORCE: settings$lzycompute in runtime/JavaUniverse.class - // NOFORCE: Lscala$reflect$internal$util$TraceSymbolActivity$$findErasurePhase$lzycompute in internal/SymbolTable$traceSymbols$.class - // NOFORCE: lineIndices$lzycompute in internal/util/BatchSourceFile.class - // NOFORCE: extension$lzycompute in io/AbstractFile.class - // NOFORCE: in_s$lzycompute in io/File.class - // NOFORCE: out_s$lzycompute in io/File.class - // NOFORCE: in$lzycompute in io/File.class - // NOFORCE: out$lzycompute in io/File.class - // NOFORCE: in$lzycompute in io/Streamable$Bytes$class.class - // noforced guys don't call into reflection, so even when not initialized they don't pose a deadlock threat - // FORCE: Scope$lzycompute in internal/SymbolTable.class - // FORCE: EmptyScope$lzycompute in internal/SymbolTable.class - // FORCE: Flag$lzycompute in internal/SymbolTable.class - // FORCE: KindErrors$lzycompute in internal/SymbolTable.class - BooleanFlag - traceSymbols - perRunCaches - typeDebug - typeDebug.str - ConsoleWriter - settings - Scope - EmptyScope - Flag - KindErrors - - // ======== Transforms ======== - // NOFORCE: ObjectArray$lzycompute in internal/transform/Erasure$ErasureMap.class - // NOFORCE: ErasedObject$lzycompute in internal/transform/Erasure$ErasureMap.class - // too much hassle to force those, and they cannot be called back from reflection => safe from deadlocks - // FORCE: GenericArray$lzycompute in internal/transform/Transforms$$anonfun$3$$anon$1.class - // FORCE: scalaErasure$lzycompute in internal/transform/Transforms$$anonfun$3$$anon$1.class - // FORCE: specialScalaErasure$lzycompute in internal/transform/Transforms$$anonfun$3$$anon$1.class - // FORCE: javaErasure$lzycompute in internal/transform/Transforms$$anonfun$3$$anon$1.class - // FORCE: verifiedJavaErasure$lzycompute in internal/transform/Transforms$$anonfun$3$$anon$1.class - // FORCE: boxingErasure$lzycompute in internal/transform/Transforms$$anonfun$3$$anon$1.class - refChecks - uncurry - erasure - erasure.GenericArray - erasure.scalaErasure - erasure.specialScalaErasure - erasure.javaErasure - erasure.verifiedJavaErasure - erasure.boxingErasure - - // ======== Symbols ======== - // FORCE: NoSymbol$lzycompute in internal/SymbolTable.class - // FORCE: 6scala$reflect$internal$Symbols$$TypeHistory$lzycompute in internal/SymbolTable.class - // FORCE: SymbolKind$lzycompute in internal/Symbols$Symbol.class - NoSymbol - definitions.AnyRefClass.info - SymbolKind - - // ======== Trees ======== - // FORCE: PackageDef$lzycompute in internal/SymbolTable.class - // FORCE: ClassDef$lzycompute in internal/SymbolTable.class - // FORCE: ModuleDef$lzycompute in internal/SymbolTable.class - // FORCE: ValDef$lzycompute in internal/SymbolTable.class - // FORCE: DefDef$lzycompute in internal/SymbolTable.class - // FORCE: TypeDef$lzycompute in internal/SymbolTable.class - // FORCE: LabelDef$lzycompute in internal/SymbolTable.class - // FORCE: ImportSelector$lzycompute in internal/SymbolTable.class - // FORCE: Import$lzycompute in internal/SymbolTable.class - // FORCE: Template$lzycompute in internal/SymbolTable.class - // FORCE: Block$lzycompute in internal/SymbolTable.class - // FORCE: CaseDef$lzycompute in internal/SymbolTable.class - // FORCE: Alternative$lzycompute in internal/SymbolTable.class - // FORCE: Star$lzycompute in internal/SymbolTable.class - // FORCE: Bind$lzycompute in internal/SymbolTable.class - // FORCE: UnApply$lzycompute in internal/SymbolTable.class - // FORCE: ArrayValue$lzycompute in internal/SymbolTable.class - // FORCE: Function$lzycompute in internal/SymbolTable.class - // FORCE: Assign$lzycompute in internal/SymbolTable.class - // FORCE: AssignOrNamedArg$lzycompute in internal/SymbolTable.class - // FORCE: If$lzycompute in internal/SymbolTable.class - // FORCE: Match$lzycompute in internal/SymbolTable.class - // FORCE: Return$lzycompute in internal/SymbolTable.class - // FORCE: Try$lzycompute in internal/SymbolTable.class - // FORCE: Throw$lzycompute in internal/SymbolTable.class - // FORCE: New$lzycompute in internal/SymbolTable.class - // FORCE: Typed$lzycompute in internal/SymbolTable.class - // FORCE: TypeApply$lzycompute in internal/SymbolTable.class - // FORCE: Apply$lzycompute in internal/SymbolTable.class - // FORCE: ApplyDynamic$lzycompute in internal/SymbolTable.class - // FORCE: Super$lzycompute in internal/SymbolTable.class - // FORCE: This$lzycompute in internal/SymbolTable.class - // FORCE: Select$lzycompute in internal/SymbolTable.class - // FORCE: Ident$lzycompute in internal/SymbolTable.class - // FORCE: ReferenceToBoxed$lzycompute in internal/SymbolTable.class - // FORCE: Literal$lzycompute in internal/SymbolTable.class - // FORCE: Annotated$lzycompute in internal/SymbolTable.class - // FORCE: SingletonTypeTree$lzycompute in internal/SymbolTable.class - // FORCE: SelectFromTypeTree$lzycompute in internal/SymbolTable.class - // FORCE: CompoundTypeTree$lzycompute in internal/SymbolTable.class - // FORCE: AppliedTypeTree$lzycompute in internal/SymbolTable.class - // FORCE: TypeBoundsTree$lzycompute in internal/SymbolTable.class - // FORCE: ExistentialTypeTree$lzycompute in internal/SymbolTable.class - // FORCE: TypeTree$lzycompute in internal/SymbolTable.class - // FORCE: Modifiers$lzycompute in internal/SymbolTable.class - // FORCE: Constant$lzycompute in internal/SymbolTable.class - // FORCE: treeBuild$lzycompute in internal/SymbolTable.class - // FORCE: posAssigner$lzycompute in internal/SymbolTable.class - // FORCE: NoMods$lzycompute in api/Universe.class - // FORCE: EmptyTree$lzycompute in internal/SymbolTable.class - // FORCE: emptyValDef$lzycompute in internal/SymbolTable.class - // FORCE: EmptyTreeTypeSubstituter$lzycompute in internal/SymbolTable.class - // FORCE: 3scala$reflect$internal$Trees$$duplicator$lzycompute in internal/SymbolTable.class - PackageDef - ClassDef - ModuleDef - ValDef - DefDef - TypeDef - LabelDef - ImportSelector - Import - Template - Block - CaseDef - Alternative - Star - Bind - UnApply - ArrayValue - Function - Assign - AssignOrNamedArg - If - Match - Return - Try - Throw - New - Typed - TypeApply - Apply - ApplyDynamic - Super - This - Select - Ident - ReferenceToBoxed - Literal - Annotated - SingletonTypeTree - SelectFromTypeTree - CompoundTypeTree - AppliedTypeTree - TypeBoundsTree - ExistentialTypeTree - TypeTree - Modifiers - Constant - treeBuild - posAssigner - NoMods - EmptyTree - emptyValDef - EmptyTreeTypeSubstituter - Literal(Constant(42)).duplicate - - // ======== Types ======== - // FORCE: undoLog$lzycompute in internal/SymbolTable.class - // FORCE: UnmappableTree$lzycompute in internal/SymbolTable.class - // FORCE: NotNullType$lzycompute in internal/SymbolTable.class - // FORCE: ErrorType$lzycompute in internal/SymbolTable.class - // FORCE: WildcardType$lzycompute in internal/SymbolTable.class - // FORCE: BoundedWildcardType$lzycompute in internal/SymbolTable.class - // FORCE: NoType$lzycompute in internal/SymbolTable.class - // FORCE: NoPrefix$lzycompute in internal/SymbolTable.class - // FORCE: ThisType$lzycompute in internal/SymbolTable.class - // FORCE: SingleType$lzycompute in internal/SymbolTable.class - // FORCE: SuperType$lzycompute in internal/SymbolTable.class - // FORCE: TypeBounds$lzycompute in internal/SymbolTable.class - // NOFORCE: annotationArgRewriter$1$lzycompute in internal/Types$AsSeenFromMap.class - // local object => not a problem - // FORCE: RefinedType$lzycompute in internal/SymbolTable.class - // FORCE: ClassInfoType$lzycompute in internal/SymbolTable.class - // FORCE: ConstantType$lzycompute in internal/SymbolTable.class - // FORCE: TypeRef$lzycompute in internal/SymbolTable.class - // FORCE: MethodType$lzycompute in internal/SymbolTable.class - // FORCE: NullaryMethodType$lzycompute in internal/SymbolTable.class - // FORCE: PolyType$lzycompute in internal/SymbolTable.class - // FORCE: ExistentialType$lzycompute in internal/SymbolTable.class - // FORCE: OverloadedType$lzycompute in internal/SymbolTable.class - // FORCE: AntiPolyType$lzycompute in internal/SymbolTable.class - // FORCE: HasTypeMember$lzycompute in internal/SymbolTable.class - // FORCE: HasTypeParams$lzycompute in internal/SymbolTable.class - // FORCE: TypeVar$lzycompute in internal/SymbolTable.class - // FORCE: AnnotatedType$lzycompute in internal/SymbolTable.class - // FORCE: NamedType$lzycompute in internal/SymbolTable.class - // FORCE: DeBruijnIndex$lzycompute in internal/SymbolTable.class - // FORCE: DeBruijnBinder$lzycompute in internal/SymbolTable.class - // FORCE: ErasedValueType$lzycompute in internal/SymbolTable.class - // FORCE: GenPolyType$lzycompute in internal/SymbolTable.class - // FORCE: normalizeAliases$lzycompute in internal/SymbolTable.class - // FORCE: dropSingletonType$lzycompute in internal/SymbolTable.class - // FORCE: dropAllRefinements$lzycompute in internal/SymbolTable.class - // FORCE: dropRepeatedParamType$lzycompute in internal/SymbolTable.class - // FORCE: toDeBruijn$lzycompute in internal/SymbolTable.class - // FORCE: numericLoBound$lzycompute in internal/SymbolTable.class - // FORCE: numericHiBound$lzycompute in internal/SymbolTable.class - // FORCE: TypeConstraint$lzycompute in internal/SymbolTable.class - // FORCE: unwrapToClass$lzycompute in internal/SymbolTable.class - // FORCE: unwrapToStableClass$lzycompute in internal/SymbolTable.class - // FORCE: unwrapWrapperTypes$lzycompute in internal/SymbolTable.class - // FORCE: IsDependentCollector$lzycompute in internal/SymbolTable.class - // FORCE: ApproximateDependentMap$lzycompute in internal/SymbolTable.class - // FORCE: StripAnnotationsMap$lzycompute in internal/SymbolTable.class - // FORCE: wildcardToTypeVarMap$lzycompute in internal/SymbolTable.class - // FORCE: typeVarToOriginMap$lzycompute in internal/SymbolTable.class - // FORCE: ErroneousCollector$lzycompute in internal/SymbolTable.class - // NOFORCE: scala$reflect$internal$Types$$commonOwnerMapObj$lzycompute in internal/SymbolTable.class - // not used in runtime reflection, overridden to provide thread-safety - // FORCE: RecoverableCyclicReference$lzycompute in internal/SymbolTable.class - // FORCE: CyclicReference$lzycompute in internal/SymbolTable.class - // NOFORCE: scala$reflect$internal$Types$ClassInfoType$$enterRefs$lzycompute in internal/Types$ClassInfoType.class - // not used in runtime reflection, only called by typer - // NOFORCE: Jscala$reflect$internal$Types$InstantiateDependentMap$$StableArg$lzycompute in internal/Types$InstantiateDependentMap.class - // NOFORCE: Dscala$reflect$internal$Types$InstantiateDependentMap$$Arg$lzycompute in internal/Types$InstantiateDependentMap.class - // don't call into reflection - // NOFORCE: trans$1$lzycompute in internal/Types$SubstSymMap.class - // NOFORCE: trans$2$lzycompute in internal/Types$SubstTypeMap.class - // NOFORCE: treeTrans$1$lzycompute in internal/Types$InstantiateDependentMap.class - // local objects => we're fine - // FORCE: adaptToNewRunMap$lzycompute in internal/SymbolTable.class - // NOFORCE?! maxDepth$lzycompute in internal/BaseTypeSeqs$BaseTypeSeq.class - // NOFORCE?! maxDepth$lzycompute in runtime/SynchronizedOps$$anon$4.class - // NOFORCE?! maxDepth$lzycompute in runtime/SynchronizedOps$SynchronizedBaseTypeSeq$$anon$3.class - // it's totally not obvious whether typeDepth, which is called by maxDepth, - // can or cannot indirectly call into one of the methods of the calling BaseTypeSeq - // TODO: leaving this for further investigation risking to get a deadlock for now - undoLog - UnmappableTree - NotNullType - ErrorType - WildcardType - BoundedWildcardType - NoType - NoPrefix - ThisType - SingleType - SuperType - TypeBounds - RefinedType - ClassInfoType - ConstantType - TypeRef - MethodType - NullaryMethodType - PolyType - ExistentialType - OverloadedType - AntiPolyType - HasTypeMember - HasTypeParams - TypeVar - AnnotatedType - NamedType - DeBruijnIndex - DeBruijnBinder - ErasedValueType - GenPolyType - normalizeAliases - dropSingletonType - dropAllRefinements - dropRepeatedParamType - toDeBruijn - numericLoBound - numericHiBound - TypeConstraint - unwrapToClass - unwrapToStableClass - unwrapWrapperTypes - IsDependentCollector - ApproximateDependentMap - StripAnnotationsMap - wildcardToTypeVarMap - typeVarToOriginMap - ErroneousCollector - RecoverableCyclicReference - CyclicReference - adaptToNewRunMap - - // ======== JavaMirrors ======== - // NOFORCE: assocs$lzycompute in runtime/JavaMirrors$JavaMirror$JavaAnnotationProxy.class - // NOFORCE: jconstr$lzycompute in runtime/JavaMirrors$JavaMirror$JavaConstructorMirror.class - // NOFORCE: jfield$lzycompute in runtime/JavaMirrors$JavaMirror$JavaFieldMirror.class - // NOFORCE: jmeth$lzycompute in runtime/JavaMirrors$JavaMirror$JavaMethodMirror.class - // NOFORCE: signature$lzycompute in runtime/JavaMirrors$JavaMirror$JavaTemplateMirror.class - // NOFORCE: PrimitiveClass$lzycompute in runtime/JavaMirrors$JavaMirror$toAnnotArg$.class - // NOFORCE: EnumClass$lzycompute in runtime/JavaMirrors$JavaMirror$toAnnotArg$.class - // NOFORCE: ArrayClass$lzycompute in runtime/JavaMirrors$JavaMirror$toAnnotArg$.class - // NOFORCE: AnnotationClass$lzycompute in runtime/JavaMirrors$JavaMirror$toAnnotArg$.class - // NOFORCE: ConstantArg$lzycompute in runtime/JavaMirrors$JavaMirror$toAnnotArg$.class - // NOFORCE: Cscala$reflect$runtime$JavaMirrors$JavaMirror$$toAnnotArg$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: Lscala$reflect$runtime$JavaMirrors$JavaMirror$$JavaAnnotationProxy$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: Bscala$reflect$runtime$TwoWayCaches$TwoWayCache$$SomeRef$lzycompute in runtime/TwoWayCaches$TwoWayCache.class - // NOFORCE: bytecodelessMethodOwners$lzycompute in runtime/JavaMirrors$JavaMirror.class - // NOFORCE: bytecodefulObjectMethods$lzycompute in runtime/JavaMirrors$JavaMirror.class - // functionality from JavaMirrors cannot be called from reflect.internal, so there's no danger of deadlock - - // ======== Locks ======== - // locks in runtime reflection look like `lazy val XXXlock = new Object` - // since initializers don't call into reflection, there's no problem in not forcing those lazy vals here - - // ======== Definitions ======== - // FORCE: definitions$lzycompute in internal/SymbolTable.class - // FORCE: JavaLangPackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaLangPackageClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaPackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaPackageClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RuntimePackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RuntimePackageClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaLangEnumClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: anyparam$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: anyvalparam$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: anyrefparam$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyRefClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ObjectClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyRefTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ObjectTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyRefModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyValClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnyValTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RuntimeNothingClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RuntimeNullClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NothingClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NullClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NothingTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NullTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ClassCastExceptionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: IndexOutOfBoundsExceptionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: InvocationTargetExceptionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MatchErrorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NonLocalReturnControlClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: $NullPointerExceptionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ThrowableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UninitializedErrorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: PartialFunctionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AbstractPartialFunctionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SymbolClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StringClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StringModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ClassClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DynamicClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SysPackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UnqualifiedModules$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UnqualifiedOwners$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: PredefModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: PredefModuleClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SpecializableModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: GroupOfSpecializable$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ConsoleModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaRunTimeModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SymbolModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Symbol_apply$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StringAddClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ArrowAssocClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StringAdd_$plus$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NotNullClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaNumberClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TraitSetterAnnotationClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DelayedInitClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TypeConstraintClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SingletonClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SerializableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaSerializableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ComparableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: CloneableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaCloneableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaNumberClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RemoteInterfaceClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RemoteExceptionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ByNameParamClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: EqualsPatternClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaRepeatedParamClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RepeatedParamClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MatchingStrategyClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ConsClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: IterableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: IteratorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ListClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SeqClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StringBuilderClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TraversableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ListModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: List_apply$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NilModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SeqModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: IteratorModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Iterator_apply$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ArrayModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ArrayModule_overloadedApply$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ArrayClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Array_apply$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Array_update$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Array_length$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Array_clone$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SoftReferenceClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: WeakReferenceClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MethodClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: EmptyMethodCacheClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MethodCacheClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ReflectPackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ReflectApiPackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ReflectRuntimePackage$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: PartialManifestClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: PartialManifestModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: FullManifestClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: FullManifestModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: OptManifestClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NoManifest$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ExprsClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ExprClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ExprModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ClassTagModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ClassTagClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TypeTagsClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: WeakTypeTagClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: WeakTypeTagModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TypeTagClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TypeTagModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ApiUniverseClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: JavaUniverseClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MirrorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TypeCreatorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TreeCreatorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MacroContextClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MacroImplAnnotation$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StringContextClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaSignatureAnnotation$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaLongSignatureAnnotation$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: OptionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: OptionModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Option_apply$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SomeClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NoneModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SomeModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ProductClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TupleClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: FunctionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AbstractFunctionClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ProductRootClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ObjectArray$lzycompute in internal/Definitions$DefinitionsClass.class - // NOFORCE: ComparatorClass$lzycompute in internal/Definitions$DefinitionsClass.class - // NOFORCE: ValueTypeClass$lzycompute in internal/Definitions$DefinitionsClass.class - // NOFORCE: DelegateClass$lzycompute in internal/Definitions$DefinitionsClass.class - // NOFORCE: Delegate_scalaCallerTargets$lzycompute in internal/Definitions$DefinitionsClass.class - // MSIL has been eol'd. probably we shouldn't care anymore - // runtime reflection doesn't support MSIL anyways - // FORCE: Any_$eq$eq$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_$bang$eq$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_equals$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_hashCode$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_toString$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_$hash$hash$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_getClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_isInstanceOf$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Any_asInstanceOf$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_$hash$hash$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_$eq$eq$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_$bang$eq$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_eq$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_ne$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_isInstanceOf$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_asInstanceOf$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Object_synchronized$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: String_$plus$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ObjectRefClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: VolatileObjectRefClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RuntimeStaticsModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxesRunTimeModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxesRunTimeClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedNumberClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedCharacterClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedBooleanClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedByteClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedShortClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedIntClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedLongClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedFloatClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedDoubleClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Boxes_isNumberOrBool$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Boxes_isNumber$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedUnitClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BoxedUnitModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnnotationClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ClassfileAnnotationClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: StaticAnnotationClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BridgeClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ElidableMethodClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ImplicitNotFoundClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MigrationAnnotationClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaStrictFPAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SerializableAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SwitchClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TailrecClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: VarargsClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: uncheckedStableClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: uncheckedVarianceClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BeanPropertyAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BooleanBeanPropertyAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: CloneableAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: CompileTimeOnlyAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DeprecatedAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DeprecatedNameAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: $DeprecatedInheritanceAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DeprecatedOverridingAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: NativeAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: RemoteAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaInlineClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaNoInlineClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SerialVersionUIDAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SpecializedClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ThrowsClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: TransientAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UncheckedClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UnspecializedClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: VolatileAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BeanGetterTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BeanSetterTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: FieldTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: GetterTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ParamTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: SetterTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ClassTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ObjectTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MethodTargetClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: LanguageFeatureAnnot$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: languageFeatureModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: experimentalModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: MacrosFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DynamicsFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: PostfixOpsFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ReflectiveCallsFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ImplicitConversionsFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: HigherKindsFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ExistentialsFeature$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: metaAnnotations$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: AnnotationDefaultAttr$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: boxedClassValues$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: isUnbox$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: isBox$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: isPhantomClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: syntheticCoreClasses$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: syntheticCoreMethods$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: hijackedCoreClasses$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: symbolsNotPresentInBytecode$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: $isPossibleSyntheticParent$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: boxedValueClassesSet$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: abbrvTag$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: numericWeight$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: boxedModule$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: boxedClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: refClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: volatileRefClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: boxMethod$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: unboxMethod$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UnitClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ByteClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ShortClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: CharClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: IntClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: LongClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: FloatClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DoubleClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BooleanClass$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Boolean_and$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Boolean_or$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: Boolean_not$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: UnitTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ByteTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ShortTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: CharTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: IntTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: LongTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: FloatTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: DoubleTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: BooleanTpe$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaNumericValueClasses$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaValueClassesNoUnit$lzycompute in internal/Definitions$DefinitionsClass.class - // FORCE: ScalaValueClasses$lzycompute in internal/Definitions$DefinitionsClass.class - definitions.JavaLangPackage - definitions.JavaLangPackageClass - definitions.ScalaPackage - definitions.ScalaPackageClass - definitions.RuntimePackage - definitions.RuntimePackageClass - definitions.JavaLangEnumClass - definitions.anyparam - definitions.anyvalparam - definitions.anyrefparam - definitions.AnyClass - definitions.AnyRefClass - definitions.ObjectClass - definitions.AnyTpe - definitions.AnyRefTpe - definitions.ObjectTpe - // FIXME: definitions.AnyRefModule - definitions.AnyValClass - definitions.AnyValTpe - definitions.RuntimeNothingClass - definitions.RuntimeNullClass - definitions.NothingClass - definitions.NullClass - definitions.NothingTpe - definitions.NullTpe - definitions.ClassCastExceptionClass - definitions.IndexOutOfBoundsExceptionClass - definitions.InvocationTargetExceptionClass - definitions.MatchErrorClass - definitions.NonLocalReturnControlClass - definitions.NullPointerExceptionClass - definitions.ThrowableClass - definitions.UninitializedErrorClass - definitions.PartialFunctionClass - definitions.AbstractPartialFunctionClass - definitions.SymbolClass - definitions.StringClass - definitions.StringModule - definitions.ClassClass - definitions.DynamicClass - definitions.SysPackage - definitions.UnqualifiedModules - definitions.UnqualifiedOwners - definitions.PredefModule - definitions.PredefModuleClass - definitions.SpecializableModule - definitions.GroupOfSpecializable - definitions.ConsoleModule - definitions.ScalaRunTimeModule - definitions.SymbolModule - definitions.Symbol_apply - definitions.StringAddClass - definitions.ArrowAssocClass - definitions.StringAdd_$plus - definitions.NotNullClass - definitions.ScalaNumberClass - definitions.TraitSetterAnnotationClass - definitions.DelayedInitClass - definitions.TypeConstraintClass - definitions.SingletonClass - definitions.SerializableClass - definitions.JavaSerializableClass - definitions.ComparableClass - definitions.CloneableClass - definitions.JavaCloneableClass - definitions.JavaNumberClass - definitions.RemoteInterfaceClass - definitions.RemoteExceptionClass - definitions.ByNameParamClass - definitions.EqualsPatternClass - definitions.JavaRepeatedParamClass - definitions.RepeatedParamClass - // FIXME: definitions.MatchingStrategyClass - definitions.ConsClass - definitions.IterableClass - definitions.IteratorClass - definitions.ListClass - definitions.SeqClass - definitions.StringBuilderClass - definitions.TraversableClass - definitions.ListModule - definitions.List_apply - definitions.NilModule - definitions.SeqModule - definitions.IteratorModule - definitions.Iterator_apply - definitions.ArrayModule - definitions.ArrayModule_overloadedApply - definitions.ArrayClass - definitions.Array_apply - definitions.Array_update - definitions.Array_length - definitions.Array_clone - definitions.SoftReferenceClass - definitions.WeakReferenceClass - definitions.MethodClass - definitions.EmptyMethodCacheClass - definitions.MethodCacheClass - definitions.ReflectPackage - definitions.ReflectApiPackage - definitions.ReflectRuntimePackage - definitions.PartialManifestClass - definitions.PartialManifestModule - definitions.FullManifestClass - definitions.FullManifestModule - definitions.OptManifestClass - definitions.NoManifest - definitions.ExprsClass - definitions.ExprClass - definitions.ExprModule - definitions.ClassTagModule - definitions.ClassTagClass - definitions.TypeTagsClass - definitions.WeakTypeTagClass - definitions.WeakTypeTagModule - definitions.TypeTagClass - definitions.TypeTagModule - definitions.ApiUniverseClass - definitions.JavaUniverseClass - definitions.MirrorClass - definitions.TypeCreatorClass - definitions.TreeCreatorClass - definitions.MacroContextClass - definitions.MacroImplAnnotation - definitions.StringContextClass - definitions.ScalaSignatureAnnotation - definitions.ScalaLongSignatureAnnotation - definitions.OptionClass - definitions.OptionModule - definitions.Option_apply - definitions.SomeClass - definitions.NoneModule - definitions.SomeModule - definitions.ProductClass - definitions.TupleClass - definitions.FunctionClass - definitions.AbstractFunctionClass - definitions.ProductRootClass - definitions.ObjectArray - definitions.Any_$eq$eq - definitions.Any_$bang$eq - definitions.Any_equals - definitions.Any_hashCode - definitions.Any_toString - definitions.Any_$hash$hash - definitions.Any_getClass - definitions.Any_isInstanceOf - definitions.Any_asInstanceOf - definitions.Object_$hash$hash - definitions.Object_$eq$eq - definitions.Object_$bang$eq - definitions.Object_eq - definitions.Object_ne - definitions.Object_isInstanceOf - definitions.Object_asInstanceOf - definitions.Object_synchronized - definitions.String_$plus - definitions.ObjectRefClass - definitions.VolatileObjectRefClass - definitions.RuntimeStaticsModule - definitions.BoxesRunTimeModule - definitions.BoxesRunTimeClass - definitions.BoxedNumberClass - definitions.BoxedCharacterClass - definitions.BoxedBooleanClass - definitions.BoxedByteClass - definitions.BoxedShortClass - definitions.BoxedIntClass - definitions.BoxedLongClass - definitions.BoxedFloatClass - definitions.BoxedDoubleClass - definitions.Boxes_isNumberOrBool - definitions.Boxes_isNumber - definitions.BoxedUnitClass - definitions.BoxedUnitModule - definitions.AnnotationClass - definitions.ClassfileAnnotationClass - definitions.StaticAnnotationClass - definitions.BridgeClass - definitions.ElidableMethodClass - definitions.ImplicitNotFoundClass - definitions.MigrationAnnotationClass - definitions.ScalaStrictFPAttr - definitions.SerializableAttr - definitions.SwitchClass - definitions.TailrecClass - definitions.VarargsClass - definitions.uncheckedStableClass - definitions.uncheckedVarianceClass - definitions.BeanPropertyAttr - definitions.BooleanBeanPropertyAttr - definitions.CloneableAttr - definitions.CompileTimeOnlyAttr - definitions.DeprecatedAttr - definitions.DeprecatedNameAttr - definitions.DeprecatedInheritanceAttr - definitions.DeprecatedOverridingAttr - definitions.NativeAttr - definitions.RemoteAttr - definitions.ScalaInlineClass - definitions.ScalaNoInlineClass - definitions.SerialVersionUIDAttr - definitions.SpecializedClass - definitions.ThrowsClass - definitions.TransientAttr - definitions.UncheckedClass - definitions.UnspecializedClass - definitions.VolatileAttr - definitions.BeanGetterTargetClass - definitions.BeanSetterTargetClass - definitions.FieldTargetClass - definitions.GetterTargetClass - definitions.ParamTargetClass - definitions.SetterTargetClass - definitions.ClassTargetClass - definitions.ObjectTargetClass - definitions.MethodTargetClass - definitions.LanguageFeatureAnnot - definitions.languageFeatureModule - definitions.experimentalModule - definitions.MacrosFeature - definitions.DynamicsFeature - definitions.PostfixOpsFeature - definitions.ReflectiveCallsFeature - definitions.ImplicitConversionsFeature - definitions.HigherKindsFeature - definitions.ExistentialsFeature - definitions.metaAnnotations - definitions.AnnotationDefaultAttr - definitions.boxedClassValues - definitions.isUnbox - definitions.isBox - definitions.isPhantomClass - definitions.syntheticCoreClasses - definitions.syntheticCoreMethods - definitions.hijackedCoreClasses - definitions.symbolsNotPresentInBytecode - definitions.isPossibleSyntheticParent - definitions.boxedValueClassesSet - definitions.abbrvTag - definitions.numericWeight - definitions.boxedModule - definitions.boxedClass - definitions.refClass - definitions.volatileRefClass - definitions.boxMethod - definitions.unboxMethod - definitions.UnitClass - definitions.ByteClass - definitions.ShortClass - definitions.CharClass - definitions.IntClass - definitions.LongClass - definitions.FloatClass - definitions.DoubleClass - definitions.BooleanClass - definitions.Boolean_and - definitions.Boolean_or - definitions.Boolean_not - definitions.UnitTpe - definitions.ByteTpe - definitions.ShortTpe - definitions.CharTpe - definitions.IntTpe - definitions.LongTpe - definitions.FloatTpe - definitions.DoubleTpe - definitions.BooleanTpe - definitions.ScalaNumericValueClasses - definitions.ScalaValueClassesNoUnit - definitions.ScalaValueClasses - } } diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala index bd5be44b35..61663f6181 100644 --- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala +++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala @@ -15,13 +15,37 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => * is found, a package is created instead. */ class TopClassCompleter(clazz: Symbol, module: Symbol) extends SymLoader with FlagAssigningCompleter { +// def makePackage() { +// println("wrong guess; making package "+clazz) +// val ptpe = newPackageType(module.moduleClass) +// for (sym <- List(clazz, module, module.moduleClass)) { +// sym setFlag Flags.PACKAGE +// sym setInfo ptpe +// } +// } + override def complete(sym: Symbol) = { debugInfo("completing "+sym+"/"+clazz.fullName) assert(sym == clazz || sym == module || sym == module.moduleClass) - slowButSafeAtPhaseNotLaterThan(picklerPhase) { +// try { + atPhaseNotLaterThan(picklerPhase) { val loadingMirror = mirrorThatLoaded(sym) val javaClass = loadingMirror.javaClass(clazz.javaClassName) loadingMirror.unpickleClass(clazz, module, javaClass) +// } catch { +// case ex: ClassNotFoundException => makePackage() +// case ex: NoClassDefFoundError => makePackage() + // Note: We catch NoClassDefFoundError because there are situations + // where a package and a class have the same name except for capitalization. + // It seems in this case the class is loaded even if capitalization differs + // but then a NoClassDefFound error is issued with a ("wrong name: ...") + // reason. (I guess this is a concession to Windows). + // The present behavior is a bit too forgiving, in that it masks + // all class load errors, not just wrong name errors. We should try + // to be more discriminating. To get on the right track simply delete + // the clause above and load a collection class such as collection.Iterable. + // You'll see an error that class `parallel` has the wrong name. +// } } } override def load(sym: Symbol) = complete(sym) @@ -33,7 +57,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => * @param name The simple name of the newly created class * @param completer The completer to be used to set the info of the class and the module */ - protected def initAndEnterClassAndModule(owner: Symbol, name: TypeName, completer: (Symbol, Symbol) => LazyType) = { + protected def createClassModule(owner: Symbol, name: TypeName, completer: (Symbol, Symbol) => LazyType) = { assert(!(name.toString endsWith "[]"), name) val clazz = owner.newClass(name) val module = owner.newModule(name.toTermName) @@ -43,7 +67,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => owner.info.decls enter clazz owner.info.decls enter module } - initClassAndModule(clazz, module, completer(clazz, module)) + initClassModule(clazz, module, completer(clazz, module)) (clazz, module) } @@ -51,7 +75,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => List(clazz, module, module.moduleClass) foreach (_ setInfo info) } - protected def initClassAndModule(clazz: Symbol, module: Symbol, completer: LazyType) = + protected def initClassModule(clazz: Symbol, module: Symbol, completer: LazyType) = setAllInfos(clazz, module, completer) /** The type completer for packages. @@ -73,51 +97,18 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => 0 < dp && dp < (name.length - 1) } - // Since runtime reflection doesn't have a luxury of enumerating all classes - // on the classpath, it has to materialize symbols for top-level definitions - // (packages, classes, objects) on demand. - // - // Someone asks us for a class named `foo.Bar`? Easy. Let's speculatively create - // a package named `foo` and then look up `newTypeName("bar")` in its decls. - // This lookup, implemented in `SymbolLoaders.PackageScope` tests the waters by - // trying to to `Class.forName("foo.Bar")` and then creates a ClassSymbol upon - // success (the whole story is a bit longer, but the rest is irrelevant here). - // - // That's all neat, but these non-deterministic mutations of the global symbol - // table give a lot of trouble in multi-threaded setting. One of the popular - // reflection crashes happens when multiple threads happen to trigger symbol - // materialization multiple times for the same symbol, making subsequent - // reflective operations stumble upon outrageous stuff like overloaded packages. - // - // Short of significantly changing SymbolLoaders I see no other way than just - // to slap a global lock on materialization in runtime reflection. class PackageScope(pkgClass: Symbol) extends Scope(initFingerPrints = -1L) // disable fingerprinting as we do not know entries beforehand with SynchronizedScope { assert(pkgClass.isType) - - // materializing multiple copies of the same symbol in PackageScope is a very popular bug - // this override does its best to guard against it - override def enter[T <: Symbol](sym: T): T = { - val existing = super.lookupEntry(sym.name) - assert(existing == null || existing.sym.isMethod, s"pkgClass = $pkgClass, sym = $sym, existing = $existing") - super.enter(sym) - } - - // package scopes need to synchronize on the GIL - // because lookupEntry might cause changes to the global symbol table - override def syncLockSynchronized[T](body: => T): T = gilSynchronized(body) - private val negatives = new mutable.HashSet[Name] - override def lookupEntry(name: Name): ScopeEntry = syncLockSynchronized { - def lookupExisting: Option[ScopeEntry] = { - val e = super.lookupEntry(name) - if (e != null) - Some(e) - else if (isInvalidClassName(name) || (negatives contains name)) - Some(null) // TODO: omg - else - None - } - def materialize: ScopeEntry = { + // disable fingerprinting as we do not know entries beforehand + private val negatives = mutable.Set[Name]() // Syncnote: Performance only, so need not be protected. + override def lookupEntry(name: Name): ScopeEntry = { + val e = super.lookupEntry(name) + if (e != null) + e + else if (isInvalidClassName(name) || (negatives contains name)) + null + else { val path = if (pkgClass.isEmptyPackageClass) name.toString else pkgClass.fullName + "." + name @@ -127,7 +118,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => val loadingMirror = currentMirror.mirrorDefining(cls) val (clazz, module) = if (loadingMirror eq currentMirror) { - initAndEnterClassAndModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _)) + createClassModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _)) } else { val origOwner = loadingMirror.packageNameToScala(pkgClass.fullName) val clazz = origOwner.info decl name.toTypeName @@ -146,7 +137,6 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => null } } - lookupExisting getOrElse materialize } } diff --git a/src/reflect/scala/reflect/runtime/SymbolTable.scala b/src/reflect/scala/reflect/runtime/SymbolTable.scala index d317d6a12b..5c08e9a508 100644 --- a/src/reflect/scala/reflect/runtime/SymbolTable.scala +++ b/src/reflect/scala/reflect/runtime/SymbolTable.scala @@ -8,7 +8,7 @@ import scala.reflect.internal.Flags._ * It can be used either from a reflexive universe (class scala.reflect.runtime.JavaUniverse), or else from * a runtime compiler that uses reflection to get a class information (class scala.tools.reflect.ReflectGlobal) */ -private[scala] trait SymbolTable extends internal.SymbolTable with JavaMirrors with SymbolLoaders with SynchronizedOps with Gil { +private[scala] trait SymbolTable extends internal.SymbolTable with JavaMirrors with SymbolLoaders with SynchronizedOps { def info(msg: => String) = if (settings.verbose.value) println("[reflect-compiler] "+msg) diff --git a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala index f9f4a26b42..7b280e59b9 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala @@ -8,40 +8,28 @@ private[reflect] trait SynchronizedOps extends internal.SymbolTable // Names - // this lock isn't subsumed by the reflection GIL - // because there's no way newXXXName methods are going to call anything reflective - // therefore we don't have a danger of a deadlock from having a fine-grained lock for name creation private lazy val nameLock = new Object - // these three methods are the only gateways into name hashtable manipulations - // we need to protected them with a lock, because they are by far not atomic - override protected def newTermName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TermName = - nameLock.synchronized { super.newTermName(cs, offset, len, cachedString) } - override protected def toTypeName(termName: TermName): TypeName = nameLock.synchronized { super.toTypeName(termName) } - override protected def toTermName(typeName: TypeName): TermName = nameLock.synchronized { super.toTermName(typeName) } + override def newTermName(s: String): TermName = nameLock.synchronized { super.newTermName(s) } + override def newTypeName(s: String): TypeName = nameLock.synchronized { super.newTypeName(s) } // BaseTypeSeqs override protected def newBaseTypeSeq(parents: List[Type], elems: Array[Type]) = - // only need to synchronize BaseTypeSeqs if they contain refined types - if (elems.filter(_.isInstanceOf[RefinedType]).nonEmpty) new BaseTypeSeq(parents, elems) with SynchronizedBaseTypeSeq - else new BaseTypeSeq(parents, elems) + new BaseTypeSeq(parents, elems) with SynchronizedBaseTypeSeq trait SynchronizedBaseTypeSeq extends BaseTypeSeq { - override def apply(i: Int): Type = gilSynchronized { super.apply(i) } - override def rawElem(i: Int) = gilSynchronized { super.rawElem(i) } - override def typeSymbol(i: Int): Symbol = gilSynchronized { super.typeSymbol(i) } - override def toList: List[Type] = gilSynchronized { super.toList } - override def copy(head: Type, offset: Int): BaseTypeSeq = gilSynchronized { super.copy(head, offset) } - override def map(f: Type => Type): BaseTypeSeq = gilSynchronized { super.map(f) } - override def exists(p: Type => Boolean): Boolean = gilSynchronized { super.exists(p) } - override lazy val maxDepth = gilSynchronized { maxDepthOfElems } - override def toString = gilSynchronized { super.toString } - - override def lateMap(f: Type => Type): BaseTypeSeq = - // only need to synchronize BaseTypeSeqs if they contain refined types - if (map(f).toList.filter(_.isInstanceOf[RefinedType]).nonEmpty) new MappedBaseTypeSeq(this, f) with SynchronizedBaseTypeSeq - else new MappedBaseTypeSeq(this, f) + override def apply(i: Int): Type = synchronized { super.apply(i) } + override def rawElem(i: Int) = synchronized { super.rawElem(i) } + override def typeSymbol(i: Int): Symbol = synchronized { super.typeSymbol(i) } + override def toList: List[Type] = synchronized { super.toList } + override def copy(head: Type, offset: Int): BaseTypeSeq = synchronized { super.copy(head, offset) } + override def map(f: Type => Type): BaseTypeSeq = synchronized { super.map(f) } + override def exists(p: Type => Boolean): Boolean = synchronized { super.exists(p) } + override lazy val maxDepth = synchronized { maxDepthOfElems } + override def toString = synchronized { super.toString } + + override def lateMap(f: Type => Type): BaseTypeSeq = new MappedBaseTypeSeq(this, f) with SynchronizedBaseTypeSeq } // Scopes @@ -50,19 +38,15 @@ private[reflect] trait SynchronizedOps extends internal.SymbolTable override def newNestedScope(outer: Scope): Scope = new Scope(outer) with SynchronizedScope trait SynchronizedScope extends Scope { - // we can keep this lock fine-grained, because methods of Scope don't do anything extraordinary, which makes deadlocks impossible - // fancy subclasses of internal.Scopes#Scope should do synchronization themselves (e.g. see PackageScope for an example) - private lazy val syncLock = new Object - def syncLockSynchronized[T](body: => T): T = if (isCompilerUniverse) body else syncLock.synchronized { body } - override def isEmpty: Boolean = syncLockSynchronized { super.isEmpty } - override def size: Int = syncLockSynchronized { super.size } - override def enter[T <: Symbol](sym: T): T = syncLockSynchronized { super.enter(sym) } - override def rehash(sym: Symbol, newname: Name) = syncLockSynchronized { super.rehash(sym, newname) } - override def unlink(e: ScopeEntry) = syncLockSynchronized { super.unlink(e) } - override def unlink(sym: Symbol) = syncLockSynchronized { super.unlink(sym) } - override def lookupAll(name: Name) = syncLockSynchronized { super.lookupAll(name) } - override def lookupEntry(name: Name) = syncLockSynchronized { super.lookupEntry(name) } - override def lookupNextEntry(entry: ScopeEntry) = syncLockSynchronized { super.lookupNextEntry(entry) } - override def toList: List[Symbol] = syncLockSynchronized { super.toList } + override def isEmpty: Boolean = synchronized { super.isEmpty } + override def size: Int = synchronized { super.size } + override def enter[T <: Symbol](sym: T): T = synchronized { super.enter(sym) } + override def rehash(sym: Symbol, newname: Name) = synchronized { super.rehash(sym, newname) } + override def unlink(e: ScopeEntry) = synchronized { super.unlink(e) } + override def unlink(sym: Symbol) = synchronized { super.unlink(sym) } + override def lookupAll(name: Name) = synchronized { super.lookupAll(name) } + override def lookupEntry(name: Name) = synchronized { super.lookupEntry(name) } + override def lookupNextEntry(entry: ScopeEntry) = synchronized { super.lookupNextEntry(entry) } + override def toList: List[Symbol] = synchronized { super.toList } } } diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala index 5a0ac01ac4..00f6952dc1 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala @@ -5,18 +5,14 @@ import scala.reflect.io.AbstractFile private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => - // we can keep this lock fine-grained, because nextId is just a simple increment, which makes deadlocks impossible - private lazy val nextIdLock = new Object - override protected def nextId() = nextIdLock.synchronized { super.nextId() } + override protected def nextId() = synchronized { super.nextId() } - // we can keep this lock fine-grained, because freshExistentialName is just a simple increment, which makes deadlocks impossible - private lazy val freshExistentialNameLock = new Object override protected def freshExistentialName(suffix: String) = - freshExistentialNameLock.synchronized { super.freshExistentialName(suffix) } + synchronized { super.freshExistentialName(suffix) } // Set the fields which point companions at one another. Returns the module. override def connectModuleToClass(m: ModuleSymbol, moduleClass: ClassSymbol): ModuleSymbol = - gilSynchronized { super.connectModuleToClass(m, moduleClass) } + synchronized { super.connectModuleToClass(m, moduleClass) } override def newFreeTermSymbol(name: TermName, value: => Any, flags: Long = 0L, origin: String = null): FreeTermSymbol = new FreeTermSymbol(name, value, origin) with SynchronizedTermSymbol initFlags flags @@ -28,40 +24,35 @@ private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: Symb trait SynchronizedSymbol extends Symbol { - def gilSynchronizedIfNotInited[T](body: => T): T = { - if (isFullyInitialized) body - else gilSynchronized { body } - } - - override def validTo = gilSynchronizedIfNotInited { super.validTo } - override def info = gilSynchronizedIfNotInited { super.info } - override def rawInfo: Type = gilSynchronizedIfNotInited { super.rawInfo } - - override def typeParams: List[Symbol] = gilSynchronizedIfNotInited { - if (isCompilerUniverse) super.typeParams - else { - if (isMonomorphicType) Nil - else { - // analogously to the "info" getter, here we allow for two completions: - // one: sourceCompleter to LazyType, two: LazyType to completed type - if (validTo == NoPeriod) - rawInfo load this - if (validTo == NoPeriod) - rawInfo load this - - rawInfo.typeParams - } - } - } - override def unsafeTypeParams: List[Symbol] = gilSynchronizedIfNotInited { - if (isCompilerUniverse) super.unsafeTypeParams - else { - if (isMonomorphicType) Nil - else rawInfo.typeParams - } - } - - override def isStable: Boolean = gilSynchronized { super.isStable } + override def rawflags = synchronized { super.rawflags } + override def rawflags_=(x: Long) = synchronized { super.rawflags_=(x) } + + override def rawowner = synchronized { super.rawowner } + override def owner_=(owner: Symbol) = synchronized { super.owner_=(owner) } + + override def validTo = synchronized { super.validTo } + override def validTo_=(x: Period) = synchronized { super.validTo_=(x) } + + override def pos = synchronized { super.pos } + override def setPos(pos: Position): this.type = { synchronized { super.setPos(pos) }; this } + + override def privateWithin = synchronized { super.privateWithin } + override def privateWithin_=(sym: Symbol) = synchronized { super.privateWithin_=(sym) } + + override def info = synchronized { super.info } + override def info_=(info: Type) = synchronized { super.info_=(info) } + override def updateInfo(info: Type): Symbol = synchronized { super.updateInfo(info) } + override def rawInfo: Type = synchronized { super.rawInfo } + + override def typeParams: List[Symbol] = synchronized { super.typeParams } + + override def reset(completer: Type): this.type = synchronized { super.reset(completer) } + + override def infosString: String = synchronized { super.infosString } + + override def annotations: List[AnnotationInfo] = synchronized { super.annotations } + override def setAnnotations(annots: List[AnnotationInfo]): this.type = { synchronized { super.setAnnotations(annots) }; this } + // ------ creators ------------------------------------------------------------------- @@ -101,38 +92,49 @@ private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: Symb override protected def createModuleSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol = new ModuleSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags - override protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol = - createModuleSymbol(name, pos, newFlags) - - override protected def createValueParameterSymbol(name: TermName, pos: Position, newFlags: Long) = - new TermSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags + override protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol = createModuleSymbol(name, pos, newFlags) - override protected def createValueMemberSymbol(name: TermName, pos: Position, newFlags: Long) = - new TermSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags + // TODO + // override protected def createValueParameterSymbol(name: TermName, pos: Position, newFlags: Long) + // override protected def createValueMemberSymbol(name: TermName, pos: Position, newFlags: Long) } // ------- subclasses --------------------------------------------------------------------- - trait SynchronizedTermSymbol extends SynchronizedSymbol + trait SynchronizedTermSymbol extends TermSymbol with SynchronizedSymbol { + override def name_=(x: Name) = synchronized { super.name_=(x) } + override def rawname = synchronized { super.rawname } + override def referenced: Symbol = synchronized { super.referenced } + override def referenced_=(x: Symbol) = synchronized { super.referenced_=(x) } + } trait SynchronizedMethodSymbol extends MethodSymbol with SynchronizedTermSymbol { - // we can keep this lock fine-grained, because it's just a cache over asSeenFrom, which makes deadlocks impossible - // unfortunately we cannot elide this lock, because the cache depends on `pre` - private lazy val typeAsMemberOfLock = new Object - override def typeAsMemberOf(pre: Type): Type = gilSynchronizedIfNotInited { typeAsMemberOfLock.synchronized { super.typeAsMemberOf(pre) } } + override def typeAsMemberOf(pre: Type): Type = synchronized { super.typeAsMemberOf(pre) } + override def paramss: List[List[Symbol]] = synchronized { super.paramss } + override def returnType: Type = synchronized { super.returnType } } - trait SynchronizedModuleSymbol extends ModuleSymbol with SynchronizedTermSymbol - trait SynchronizedTypeSymbol extends TypeSymbol with SynchronizedSymbol { - // unlike with typeConstructor, a lock is necessary here, because tpe calculation relies on - // temporarily assigning NoType to tpeCache to detect cyclic reference errors - private lazy val tpeLock = new Object - override def tpe: Type = gilSynchronizedIfNotInited { tpeLock.synchronized { super.tpe } } + override def name_=(x: Name) = synchronized { super.name_=(x) } + override def rawname = synchronized { super.rawname } + override def typeConstructor: Type = synchronized { super.typeConstructor } + override def tpe: Type = synchronized { super.tpe } } - trait SynchronizedClassSymbol extends ClassSymbol with SynchronizedTypeSymbol + trait SynchronizedClassSymbol extends ClassSymbol with SynchronizedTypeSymbol { + override def associatedFile = synchronized { super.associatedFile } + override def associatedFile_=(f: AbstractFile) = synchronized { super.associatedFile_=(f) } + override def thisSym: Symbol = synchronized { super.thisSym } + override def thisType: Type = synchronized { super.thisType } + override def typeOfThis: Type = synchronized { super.typeOfThis } + override def typeOfThis_=(tp: Type) = synchronized { super.typeOfThis_=(tp) } + override def children = synchronized { super.children } + override def addChild(sym: Symbol) = synchronized { super.addChild(sym) } + } - trait SynchronizedModuleClassSymbol extends ModuleClassSymbol with SynchronizedClassSymbol + trait SynchronizedModuleClassSymbol extends ModuleClassSymbol with SynchronizedClassSymbol { + override def sourceModule = synchronized { super.sourceModule } + override def implicitMembers: Scope = synchronized { super.implicitMembers } + } } diff --git a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala index 939363f8b4..a3e7c28ca4 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala @@ -12,9 +12,8 @@ private[reflect] trait SynchronizedTypes extends internal.Types { self: SymbolTa // No sharing of map objects: override protected def commonOwnerMap = new CommonOwnerMap - // we can keep this lock fine-grained, because super.unique just updates the cache - // and, in particular, doesn't call any reflection APIs which makes deadlocks impossible - private lazy val uniqueLock = new Object + private object uniqueLock + private val uniques = WeakHashMap[Type, WeakReference[Type]]() override def unique[T <: Type](tp: T): T = uniqueLock.synchronized { // we need to have weak uniques for runtime reflection @@ -38,35 +37,46 @@ private[reflect] trait SynchronizedTypes extends internal.Types { self: SymbolTa } class SynchronizedUndoLog extends UndoLog { - final override def lock(): Unit = gil.lock() - final override def unlock(): Unit = gil.unlock() + private val actualLock = new java.util.concurrent.locks.ReentrantLock + + final override def lock(): Unit = actualLock.lock() + final override def unlock(): Unit = actualLock.unlock() } override protected def newUndoLog = new SynchronizedUndoLog override protected def baseTypeOfNonClassTypeRef(tpe: NonClassTypeRef, clazz: Symbol) = - gilSynchronized { super.baseTypeOfNonClassTypeRef(tpe, clazz) } + synchronized { super.baseTypeOfNonClassTypeRef(tpe, clazz) } + + private object subsametypeLock override def isSameType(tp1: Type, tp2: Type): Boolean = - gilSynchronized { super.isSameType(tp1, tp2) } + subsametypeLock.synchronized { super.isSameType(tp1, tp2) } override def isDifferentType(tp1: Type, tp2: Type): Boolean = - gilSynchronized { super.isDifferentType(tp1, tp2) } + subsametypeLock.synchronized { super.isDifferentType(tp1, tp2) } override def isSubType(tp1: Type, tp2: Type, depth: Int): Boolean = - gilSynchronized { super.isSubType(tp1, tp2, depth) } + subsametypeLock.synchronized { super.isSubType(tp1, tp2, depth) } + + private object lubglbLock override def glb(ts: List[Type]): Type = - gilSynchronized { super.glb(ts) } + lubglbLock.synchronized { super.glb(ts) } override def lub(ts: List[Type]): Type = - gilSynchronized { super.lub(ts) } + lubglbLock.synchronized { super.lub(ts) } + + private object indentLock + + override protected def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = { + indentLock.synchronized { super.explain(op, p, tp1, arg2) } + } - override protected def explain[T](op: String, p: (Type, T) => Boolean, tp1: Type, arg2: T): Boolean = - gilSynchronized { super.explain(op, p, tp1, arg2) } + private object toStringLock override protected def typeToString(tpe: Type): String = - gilSynchronized(super.typeToString(tpe)) + toStringLock.synchronized(super.typeToString(tpe)) /* The idea of caches is as follows. * When in reflexive mode, a cache is either null, or one sentinal @@ -79,18 +89,18 @@ private[reflect] trait SynchronizedTypes extends internal.Types { self: SymbolTa */ override protected def defineUnderlyingOfSingleType(tpe: SingleType) = - gilSynchronized { super.defineUnderlyingOfSingleType(tpe) } + tpe.synchronized { super.defineUnderlyingOfSingleType(tpe) } override protected def defineBaseTypeSeqOfCompoundType(tpe: CompoundType) = - gilSynchronized { super.defineBaseTypeSeqOfCompoundType(tpe) } + tpe.synchronized { super.defineBaseTypeSeqOfCompoundType(tpe) } override protected def defineBaseClassesOfCompoundType(tpe: CompoundType) = - gilSynchronized { super.defineBaseClassesOfCompoundType(tpe) } + tpe.synchronized { super.defineBaseClassesOfCompoundType(tpe) } override protected def defineParentsOfTypeRef(tpe: TypeRef) = - gilSynchronized { super.defineParentsOfTypeRef(tpe) } + tpe.synchronized { super.defineParentsOfTypeRef(tpe) } override protected def defineBaseTypeSeqOfTypeRef(tpe: TypeRef) = - gilSynchronized { super.defineBaseTypeSeqOfTypeRef(tpe) } + tpe.synchronized { super.defineBaseTypeSeqOfTypeRef(tpe) } } diff --git a/src/reflect/scala/reflect/runtime/TwoWayCache.scala b/src/reflect/scala/reflect/runtime/TwoWayCache.scala new file mode 100644 index 0000000000..05debcba65 --- /dev/null +++ b/src/reflect/scala/reflect/runtime/TwoWayCache.scala @@ -0,0 +1,66 @@ +package scala.reflect +package runtime + +import scala.collection.mutable.WeakHashMap +import java.lang.ref.WeakReference + +/** A cache that maintains a bijection between Java reflection type `J` + * and Scala reflection type `S`. + * + * The cache is two-way weak (i.e. is powered by weak references), + * so that neither Java artifacts prevent Scala artifacts from being garbage collected, + * nor the other way around. + */ +private[runtime] class TwoWayCache[J, S] { + + private val toScalaMap = new WeakHashMap[J, WeakReference[S]] + private val toJavaMap = new WeakHashMap[S, WeakReference[J]] + + def enter(j: J, s: S) = synchronized { + // debugInfo("cached: "+j+"/"+s) + toScalaMap(j) = new WeakReference(s) + toJavaMap(s) = new WeakReference(j) + } + + private object SomeRef { + def unapply[T](optRef: Option[WeakReference[T]]): Option[T] = + if (optRef.nonEmpty) { + val result = optRef.get.get + if (result != null) Some(result) else None + } else None + } + + def toScala(key: J)(body: => S): S = synchronized { + toScalaMap get key match { + case SomeRef(v) => + v + case _ => + val result = body + enter(key, result) + result + } + } + + def toJava(key: S)(body: => J): J = synchronized { + toJavaMap get key match { + case SomeRef(v) => + v + case _ => + val result = body + enter(result, key) + result + } + } + + def toJavaOption(key: S)(body: => Option[J]): Option[J] = synchronized { + toJavaMap get key match { + case SomeRef(v) => + Some(v) + case _ => + val result = body + for (value <- result) enter(value, key) + result + } + } +} + diff --git a/src/reflect/scala/reflect/runtime/TwoWayCaches.scala b/src/reflect/scala/reflect/runtime/TwoWayCaches.scala deleted file mode 100644 index 6e2890e536..0000000000 --- a/src/reflect/scala/reflect/runtime/TwoWayCaches.scala +++ /dev/null @@ -1,68 +0,0 @@ -package scala.reflect -package runtime - -import scala.collection.mutable.WeakHashMap -import java.lang.ref.WeakReference - -/** A cache that maintains a bijection between Java reflection type `J` - * and Scala reflection type `S`. - * - * The cache is two-way weak (i.e. is powered by weak references), - * so that neither Java artifacts prevent Scala artifacts from being garbage collected, - * nor the other way around. - */ -private[runtime] trait TwoWayCaches { self: SymbolTable => - class TwoWayCache[J, S] { - - private val toScalaMap = new WeakHashMap[J, WeakReference[S]] - private val toJavaMap = new WeakHashMap[S, WeakReference[J]] - - def enter(j: J, s: S) = gilSynchronized { - // debugInfo("cached: "+j+"/"+s) - toScalaMap(j) = new WeakReference(s) - toJavaMap(s) = new WeakReference(j) - } - - private object SomeRef { - def unapply[T](optRef: Option[WeakReference[T]]): Option[T] = - if (optRef.nonEmpty) { - val result = optRef.get.get - if (result != null) Some(result) else None - } else None - } - - def toScala(key: J)(body: => S): S = gilSynchronized { - toScalaMap get key match { - case SomeRef(v) => - v - case _ => - val result = body - enter(key, result) - result - } - } - - def toJava(key: S)(body: => J): J = gilSynchronized { - toJavaMap get key match { - case SomeRef(v) => - v - case _ => - val result = body - enter(result, key) - result - } - } - - def toJavaOption(key: S)(body: => Option[J]): Option[J] = gilSynchronized { - toJavaMap get key match { - case SomeRef(v) => - Some(v) - case _ => - val result = body - for (value <- result) enter(value, key) - result - } - } - } -} - diff --git a/src/swing/scala/swing/ColorChooser.scala b/src/swing/scala/swing/ColorChooser.scala deleted file mode 100644 index 9bd71e1df0..0000000000 --- a/src/swing/scala/swing/ColorChooser.scala +++ /dev/null @@ -1,45 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2007-2012, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.swing - -import javax.swing.JColorChooser -import event._ - -/** - * Wrapper for JColorChooser. Publishes `ColorChanged` events, when the color selection changes. - * - * @author andy@hicks.net - * @author Ingo Maier - * @see javax.swing.JColorChooser - */ -object ColorChooser { - def showDialog(parent: Component, title: String, color: Color): scala.Option[Color] = { - toOption[Color](javax.swing.JColorChooser.showDialog(parent.peer, title, color)) - } -} - -class ColorChooser(color0: Color) extends Component { - def this() = this(java.awt.Color.white) - - override lazy val peer: JColorChooser = new JColorChooser(color0) with SuperMixin - - peer.getSelectionModel.addChangeListener(new javax.swing.event.ChangeListener { - def stateChanged(e: javax.swing.event.ChangeEvent) { - publish(ColorChanged(ColorChooser.this, peer.getColor)) - } - }) - - def color: Color = peer.getColor - def color_=(c: Color) = peer.setColor(c) - - def dragEnabled: Boolean = peer.getDragEnabled - def dragEnabled_=(b: Boolean) = peer.setDragEnabled(b) -}
\ No newline at end of file diff --git a/src/swing/scala/swing/PopupMenu.scala b/src/swing/scala/swing/PopupMenu.scala deleted file mode 100644 index 0f292b11a2..0000000000 --- a/src/swing/scala/swing/PopupMenu.scala +++ /dev/null @@ -1,65 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2007-2012, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.swing - -import javax.swing.JPopupMenu -import javax.swing.event.{PopupMenuListener, PopupMenuEvent} -import event._ - -/** - * A popup menu. - * - * Example usage: - * - * {{{ - * val popupMenu = new PopupMenu { - * contents += new Menu("menu 1") { - * contents += new RadioMenuItem("radio 1.1") - * contents += new RadioMenuItem("radio 1.2") - * } - * contents += new Menu("menu 2") { - * contents += new RadioMenuItem("radio 2.1") - * contents += new RadioMenuItem("radio 2.2") - * } - * } - * val button = new Button("Show Popup Menu") - * reactions += { - * case e: ButtonClicked => popupMenu.show(button, 0, button.bounds.height) - * } - * listenTo(button) - * }}} - * - * @author John Sullivan - * @author Ingo Maier - * @see javax.swing.JPopupMenu - */ -class PopupMenu extends Component with SequentialContainer.Wrapper with Publisher { - override lazy val peer: JPopupMenu = new JPopupMenu with SuperMixin - - peer.addPopupMenuListener(new PopupMenuListener { - def popupMenuCanceled(e: PopupMenuEvent) { - publish(PopupMenuCanceled(PopupMenu.this)) - } - def popupMenuWillBecomeInvisible(e: PopupMenuEvent) { - publish(PopupMenuWillBecomeInvisible(PopupMenu.this)) - } - def popupMenuWillBecomeVisible(e: PopupMenuEvent) { - publish(PopupMenuWillBecomeVisible(PopupMenu.this)) - } - }) - - def show(invoker: Component, x: Int, y: Int): Unit = peer.show(invoker.peer, x, y) - - def margin: Insets = peer.getMargin - def label: String = peer.getLabel - def label_=(s: String) { peer.setLabel(s) } -} - diff --git a/src/swing/scala/swing/event/ColorChanged.scala b/src/swing/scala/swing/event/ColorChanged.scala deleted file mode 100644 index 44387aa864..0000000000 --- a/src/swing/scala/swing/event/ColorChanged.scala +++ /dev/null @@ -1,14 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.swing -package event - -case class ColorChanged(source: Component, c: Color) extends ComponentEvent with SelectionEvent diff --git a/src/swing/scala/swing/event/PopupMenuEvent.scala b/src/swing/scala/swing/event/PopupMenuEvent.scala deleted file mode 100644 index f7083c06de..0000000000 --- a/src/swing/scala/swing/event/PopupMenuEvent.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2007-2012, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.swing -package event - -abstract class PopupMenuEvent extends ComponentEvent - -case class PopupMenuCanceled(source: PopupMenu) extends PopupMenuEvent -case class PopupMenuWillBecomeInvisible(source: PopupMenu) extends PopupMenuEvent -case class PopupMenuWillBecomeVisible(source: PopupMenu) extends PopupMenuEvent
\ No newline at end of file |