diff options
8 files changed, 81 insertions, 119 deletions
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index 37caa06fe9..c2ef633d58 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -1425,7 +1425,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Reset symbol to initial state */ - def reset(completer: Type) { + def reset(completer: Type): this.type = { resetFlags() infos = null _validTo = NoPeriod @@ -2054,6 +2054,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def sealedDescendants: Set[Symbol] = children.flatMap(_.sealedDescendants) + this @inline final def orElse(alt: => Symbol): Symbol = if (this ne NoSymbol) this else alt + @inline final def andAlso(f: Symbol => Unit): Symbol = if (this eq NoSymbol) NoSymbol else { f(this) ; this } // ------ toString ------------------------------------------------------------------- @@ -2636,10 +2637,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => info.baseTypeIndex(that) >= 0 ) - override def reset(completer: Type) { + override def reset(completer: Type): this.type = { super.reset(completer) tpePeriod = NoPeriod tyconRunId = NoRunId + this } /*** example: @@ -2822,9 +2824,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => else super.sourceFile override def sourceFile_=(f: AbstractFileType) { source = f } - override def reset(completer: Type) { + override def reset(completer: Type): this.type = { super.reset(completer) thissym = this + this } /** the type this.type in this class */ @@ -3022,7 +3025,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def ownerChain: List[Symbol] = List() override def ownersIterator: Iterator[Symbol] = Iterator.empty override def alternatives: List[Symbol] = List() - override def reset(completer: Type) {} + override def reset(completer: Type): this.type = this override def info: Type = NoType override def existentialBound: Type = NoType override def rawInfo: Type = NoType diff --git a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala index 4048e94d0f..8378f1a892 100644 --- a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala @@ -46,7 +46,7 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => override def typeParams: List[Symbol] = synchronized { super.typeParams } - override def reset(completer: Type) = synchronized { super.reset(completer) } + override def reset(completer: Type): this.type = synchronized { super.reset(completer) } override def infosString: String = synchronized { super.infosString } diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index e2d4efab83..4584ba032d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -405,6 +405,17 @@ trait Contexts { self: Analyzer => case _ => outer.isLocal() } + /** Fast path for some slow checks (ambiguous assignment in Refchecks, and + * existence of __match for MatchTranslation in virtpatmat.) This logic probably + * needs improvement. + */ + def isNameInScope(name: Name) = ( + enclosingContextChain exists (ctx => + (ctx.scope.lookupEntry(name) != null) + || (ctx.owner.rawInfo.member(name) != NoSymbol) + ) + ) + // nextOuter determines which context is searched next for implicits // (after `this`, which contributes `newImplicits` below.) In // most cases, it is simply the outer context: if we're owned by diff --git a/src/compiler/scala/tools/nsc/typechecker/Modes.scala b/src/compiler/scala/tools/nsc/typechecker/Modes.scala index 48068b58d4..3eff5ef024 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Modes.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Modes.scala @@ -105,7 +105,7 @@ trait Modes { final def inFunMode(mode: Int) = (mode & FUNmode) != 0 final def inPolyMode(mode: Int) = (mode & POLYmode) != 0 final def inPatternMode(mode: Int) = (mode & PATTERNmode) != 0 - + final def inExprModeOr(mode: Int, others: Int) = (mode & (EXPRmode | others)) != 0 final def inExprModeButNot(mode: Int, prohibited: Int) = (mode & (EXPRmode | prohibited)) == EXPRmode diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index ffd00751e0..45f7d7e618 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -139,16 +139,9 @@ trait Namers extends MethodSynthesis { || vd.symbol.isLazy ) - def setPrivateWithin[Sym <: Symbol](tree: Tree, sym: Sym, mods: Modifiers): Sym = + def setPrivateWithin[T <: Symbol](tree: Tree, sym: T, mods: Modifiers): T = if (sym.isPrivateLocal || !mods.hasAccessBoundary) sym - else sym setPrivateWithin ( - typer.qualifyingClass(tree, mods.privateWithin, true) match { - case None => - NoSymbol - case Some(sym) => - sym - } - ) + else sym setPrivateWithin typer.qualifyingClass(tree, mods.privateWithin, packageOK = true) def setPrivateWithin(tree: MemberDef, sym: Symbol): Symbol = setPrivateWithin(tree, sym, tree.mods) @@ -160,24 +153,14 @@ trait Namers extends MethodSynthesis { def moduleClassFlags(moduleFlags: Long) = (moduleFlags & ModuleToClassFlags) | inConstructorFlag - private def resetKeepingFlags(sym: Symbol, keeping: Long): Symbol = { - val keep = sym.flags & keeping - sym reset NoType - sym setFlag keep - } - def updatePosFlags(sym: Symbol, pos: Position, flags: Long): Symbol = { debuglog("[overwrite] " + sym) - resetKeepingFlags(sym, LOCKED) - sym setFlag flags - sym setPos pos - - if (sym.isModule && sym.moduleClass != NoSymbol) - updatePosFlags(sym.moduleClass, pos, moduleClassFlags(flags)) + val newFlags = (sym.flags & LOCKED) | flags + sym reset NoType setFlag newFlags setPos pos + sym.moduleClass andAlso (updatePosFlags(_, pos, moduleClassFlags(flags))) if (sym.owner.isPackageClass) { - val companion = companionSymbolOf(sym, context) - if (companion != NoSymbol) { + companionSymbolOf(sym, context) andAlso { companion => val assignNoType = companion.rawInfo match { case _: SymLoader => true case tp => tp.isComplete && (runId(sym.validTo) != currentRunId) @@ -400,9 +383,7 @@ trait Namers extends MethodSynthesis { if (m.isModule && !m.isPackage && inCurrentScope(m) && (currentRun.canRedefine(m) || m.isSynthetic)) { updatePosFlags(m, tree.pos, moduleFlags) setPrivateWithin(tree, m) - if (m.moduleClass != NoSymbol) - setPrivateWithin(tree, m.moduleClass) - + m.moduleClass andAlso (setPrivateWithin(tree, _)) context.unit.synthetics -= m tree.symbol = m } @@ -475,8 +456,7 @@ trait Namers extends MethodSynthesis { val defSym = context.prefix.member(to) filter ( sym => sym.exists && context.isAccessible(sym, context.prefix, false)) - if (defSym != NoSymbol) - typer.permanentlyHiddenWarning(pos, to0, defSym) + defSym andAlso (typer.permanentlyHiddenWarning(pos, to0, _)) } } if (!tree.symbol.isSynthetic && expr.symbol != null && !expr.symbol.isInterpreterWrapper) { @@ -669,10 +649,9 @@ trait Namers extends MethodSynthesis { protected def enterExistingSym(sym: Symbol): Context = { if (forInteractive && sym != null && sym.owner.isTerm) { enterIfNotThere(sym) - if (sym.isLazy) { - val acc = sym.lazyAccessor - if (acc != NoSymbol) enterIfNotThere(acc) - } + if (sym.isLazy) + sym.lazyAccessor andAlso enterIfNotThere + defaultParametersOfMethod(sym) foreach { symRef => enterIfNotThere(symRef()) } } this.context @@ -1547,13 +1526,13 @@ trait Namers extends MethodSynthesis { * call this method? */ def companionSymbolOf(original: Symbol, ctx: Context): Symbol = { - try original.companionSymbol match { - case NoSymbol => + try { + original.companionSymbol orElse { ctx.lookup(original.name.companionName, original.owner).suchThat(sym => (original.isTerm || sym.hasModuleFlag) && (sym isCoDefinedWith original) ) - case sym => sym + } } catch { case e: InvalidCompanions => diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 3d9fc67389..898a9fee9f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -444,21 +444,12 @@ trait NamesDefaults { self: Analyzer => } } - /** Fast path for ambiguous assignment check. - */ - private def isNameInScope(context: Context, name: Name) = ( - context.enclosingContextChain exists (ctx => - (ctx.scope.lookupEntry(name) != null) - || (ctx.owner.rawInfo.member(name) != NoSymbol) - ) - ) - /** A full type check is very expensive; let's make sure there's a name * somewhere which could potentially be ambiguous before we go that route. */ private def isAmbiguousAssignment(typer: Typer, param: Symbol, arg: Tree) = { import typer.context - isNameInScope(context, param.name) && { + (context isNameInScope param.name) && { // for named arguments, check whether the assignment expression would // typecheck. if it does, report an ambiguous error. val paramtpe = param.tpe.cloneInfo(param) diff --git a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala index e5dc8e9ca9..e5b5746e8d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala @@ -55,10 +55,15 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer => def apply(typer: Typer): MatchTranslation with CodegenCore = { import typer._ // typing `_match` to decide which MatchTranslator to create adds 4% to quick.comp.timer - newTyper(context.makeImplicit(reportAmbiguousErrors = false)).silent(_.typed(Ident(vpmName._match), EXPRmode, WildcardType), reportAmbiguousErrors = false) match { - case SilentResultValue(ms) => new PureMatchTranslator(typer, ms) - case _ => new OptimizingMatchTranslator(typer) + val matchStrategy: Tree = ( + if (!context.isNameInScope(vpmName._match)) null // fast path, avoiding the next line if there's no __match to be seen + else newTyper(context.makeImplicit(reportAmbiguousErrors = false)).silent(_.typed(Ident(vpmName._match), EXPRmode, WildcardType), reportAmbiguousErrors = false) match { + case SilentResultValue(ms) => ms + case _ => null } + ) + if (matchStrategy eq null) new OptimizingMatchTranslator(typer) + else new PureMatchTranslator(typer, matchStrategy) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 6234c05258..89c30590c9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -458,13 +458,10 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser * of a this or super with prefix <code>qual</code>. * packageOk is equal false when qualifying class symbol */ - def qualifyingClass(tree: Tree, qual: Name, packageOK: Boolean = false): Option[Symbol] = + def qualifyingClass(tree: Tree, qual: Name, packageOK: Boolean) = context.enclClass.owner.ownerChain.find(o => qual.isEmpty || o.isClass && o.name == qual) match { - case Some(c) if packageOK || !c.isPackageClass => - Some(c) - case _ => - QualifyingClassError(tree, qual) - None + case Some(c) if packageOK || !c.isPackageClass => c + case _ => QualifyingClassError(tree, qual) ; NoSymbol } /** The typer for an expression, depending on where we are. If we are before a superclass @@ -4133,7 +4130,7 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser } def convertToAssignment(fun: Tree, qual: Tree, name: Name, args: List[Tree]): Tree = { - val prefix = name.subName(0, name.length - nme.EQL.length) + val prefix = name stripSuffix nme.EQL def mkAssign(vble: Tree): Tree = Assign( vble, @@ -4142,21 +4139,18 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser ) setPos tree.pos def mkUpdate(table: Tree, indices: List[Tree]) = { - gen.evalOnceAll(table :: indices, context.owner, context.unit) { ts => - val tab = ts.head - val is = ts.tail - Apply( - Select(tab(), nme.update) setPos table.pos, - ((is map (i => i())) ::: List( - Apply( - Select( - Apply( - Select(tab(), nme.apply) setPos table.pos, - is map (i => i())) setPos qual.pos, - prefix) setPos fun.pos, - args) setPos tree.pos) - ) - ) setPos tree.pos + gen.evalOnceAll(table :: indices, context.owner, context.unit) { + case tab :: is => + def mkCall(name: Name, extraArgs: Tree*) = ( + Apply( + Select(tab(), name) setPos table.pos, + is.map(i => i()) ++ extraArgs + ) setPos tree.pos + ) + mkCall( + nme.update, + Apply(Select(mkCall(nme.apply), prefix) setPos fun.pos, args) setPos tree.pos + ) } } @@ -4223,15 +4217,11 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser treeCopy.Super(tree, qual1, mix) setType SuperType(clazz.thisType, owntype) } - def typedThis(qual: Name) = { - val qualifyingClassSym = if (tree.symbol != NoSymbol) Some(tree.symbol) else qualifyingClass(tree, qual) - qualifyingClassSym match { - case Some(clazz) => - tree setSymbol clazz setType clazz.thisType.underlying - if (isStableContext(tree, mode, pt)) tree setType clazz.thisType - tree - case None => tree - } + def typedThis(qual: Name) = tree.symbol orElse qualifyingClass(tree, qual, packageOK = false) match { + case NoSymbol => tree + case clazz => + tree setSymbol clazz setType clazz.thisType.underlying + if (isStableContext(tree, mode, pt)) tree setType clazz.thisType else tree } /** Attribute a selection where <code>tree</code> is <code>qual.name</code>. @@ -4242,34 +4232,19 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser * @return ... */ def typedSelect(qual: Tree, name: Name): Tree = { - val sym = - if (tree.symbol != NoSymbol) { - if (phase.erasedTypes && qual.isInstanceOf[Super]) - qual.tpe = tree.symbol.owner.tpe - if (false && settings.debug.value) { // todo: replace by settings.check.value? - val alts = qual.tpe.member(tree.symbol.name).alternatives - if (!(alts exists (alt => - alt == tree.symbol || alt.isTerm && (alt.tpe matches tree.symbol.tpe)))) - assert(false, "symbol "+tree.symbol+tree.symbol.locationString+" not in "+alts+" of "+qual.tpe+ - "\n members = "+qual.tpe.members+ - "\n type history = "+qual.tpe.termSymbol.infosString+ - "\n phase = "+phase) - } - tree.symbol - } else { - member(qual, name) + val sym = tree.symbol orElse member(qual, name) orElse { + // symbol not found? --> try to convert implicitly to a type that does have the required + // member. Added `| PATTERNmode` to allow enrichment in patterns (so we can add e.g., an + // xml member to StringContext, which in turn has an unapply[Seq] method) + if (name != nme.CONSTRUCTOR && inExprModeOr(mode, PATTERNmode)) { + val qual1 = adaptToMemberWithArgs(tree, qual, name, mode, true, true) + if (qual1 ne qual) + return typed(treeCopy.Select(tree, qual1, name), mode, pt) } - - // symbol not found? --> try to convert implicitly to a type that does have the required member - // added `| PATTERNmode` to allow enrichment in patterns (so we can add e.g., an xml member to StringContext, which in turn has an unapply[Seq] method) - if (sym == NoSymbol && name != nme.CONSTRUCTOR && (mode & (EXPRmode | PATTERNmode)) != 0) { - val qual1 = - if (member(qual, name) != NoSymbol) qual - else adaptToMemberWithArgs(tree, qual, name, mode, true, true) - - if (qual1 ne qual) - return typed(treeCopy.Select(tree, qual1, name), mode, pt) + NoSymbol } + if (phase.erasedTypes && qual.isInstanceOf[Super] && tree.symbol != NoSymbol) + qual.tpe = tree.symbol.owner.tpe if (!reallyExists(sym)) { if (context.owner.enclosingTopLevelClass.isJavaDefined && name.isTypeName) { @@ -4284,14 +4259,12 @@ trait Typers extends Modes with Adaptations with Taggings with PatMatVirtualiser case _ => } - if (settings.debug.value) { - log( - "qual = "+qual+":"+qual.tpe+ - "\nSymbol="+qual.tpe.termSymbol+"\nsymbol-info = "+qual.tpe.termSymbol.info+ - "\nscope-id = "+qual.tpe.termSymbol.info.decls.hashCode()+"\nmembers = "+qual.tpe.members+ - "\nname = "+name+"\nfound = "+sym+"\nowner = "+context.enclClass.owner - ) - } + debuglog( + "qual = "+qual+":"+qual.tpe+ + "\nSymbol="+qual.tpe.termSymbol+"\nsymbol-info = "+qual.tpe.termSymbol.info+ + "\nscope-id = "+qual.tpe.termSymbol.info.decls.hashCode()+"\nmembers = "+qual.tpe.members+ + "\nname = "+name+"\nfound = "+sym+"\nowner = "+context.enclClass.owner + ) def makeInteractiveErrorTree = { val tree1 = tree match { |