diff options
27 files changed, 96 insertions, 127 deletions
diff --git a/src/compiler/scala/reflect/macros/compiler/Validators.scala b/src/compiler/scala/reflect/macros/compiler/Validators.scala index fafd79d1d7..af17fd87c0 100644 --- a/src/compiler/scala/reflect/macros/compiler/Validators.scala +++ b/src/compiler/scala/reflect/macros/compiler/Validators.scala @@ -81,7 +81,11 @@ trait Validators { // Technically this can be just an alias to MethodType, but promoting it to a first-class entity // provides better encapsulation and convenient syntax for pattern matching. - private case class MacroImplSig(tparams: List[Symbol], paramss: List[List[Symbol]], ret: Type) + private case class MacroImplSig(tparams: List[Symbol], paramss: List[List[Symbol]], ret: Type) { + private def tparams_s = if (tparams.isEmpty) "" else tparams.map(_.defString).mkString("[", ", ", "]") + private def paramss_s = paramss map (ps => ps.map(s => s"${s.name}: ${s.tpe_*}").mkString("(", ", ", ")")) mkString "" + override def toString = "MacroImplSig(" + tparams_s + paramss_s + ret + ")" + } /** An actual macro implementation signature extracted from a macro implementation method. * diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index a6c69091c5..dcb41752f7 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -258,6 +258,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) if (settings.debug) body } + + override protected def isDeveloper = settings.developer || super.isDeveloper + /** This is for WARNINGS which should reach the ears of scala developers * whenever they occur, but are not useful for normal users. They should * be precise, explanatory, and infrequent. Please don't use this as a @@ -265,7 +268,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) * to make them visually distinct. */ @inline final override def devWarning(msg: => String) { - if (settings.developer || settings.debug) + if (isDeveloper) warning("!!! " + msg) else log("!!! " + msg) // such warnings always at least logged diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 641ab9c279..381ffb1ed9 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -66,10 +66,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => */ def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], body: List[Tree], superPos: Position): ClassDef = { // "if they have symbols they should be owned by `sym`" - assert( - mforall(vparamss)(p => (p.symbol eq NoSymbol) || (p.symbol.owner == sym)), - ((mmap(vparamss)(_.symbol), sym)) - ) + assert(mforall(vparamss)(_.symbol.owner == sym), (mmap(vparamss)(_.symbol), sym)) ClassDef(sym, gen.mkTemplate(sym.info.parents map TypeTree, diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index 56191cc981..09095879bf 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -78,10 +78,10 @@ abstract class Inliners extends SubComponent { assert(clazz != NoSymbol, "Walked up past Object.superClass looking for " + sym + ", most likely this reveals the TFA at fault (receiver and callee don't match).") if (sym.owner == clazz || isBottomType(clazz)) sym - else sym.overridingSymbol(clazz) match { - case NoSymbol => if (sym.owner.isTrait) sym else lookup(clazz.superClass) - case imp => imp - } + else sym.overridingSymbol(clazz) orElse ( + if (sym.owner.isTrait) sym + else lookup(clazz.superClass) + ) } if (needsLookup) { val concreteMethod = lookup(clazz) diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index 0dcf4d00b7..d9d08dde1e 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -367,29 +367,3 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => } } } -/* - val ensureNoEscapes = new TypeTraverser { - def ensureNoEscape(sym: Symbol) { - if (sym.hasFlag(PRIVATE)) { - var o = currentOwner; - while (o != NoSymbol && o != sym.owner && !o.isLocal && !o.hasFlag(PRIVATE)) - o = o.owner - if (o == sym.owner) sym.makeNotPrivate(base); - } - } - def traverse(t: Type): TypeTraverser = { - t match { - case TypeRef(qual, sym, args) => - ensureNoEscape(sym) - mapOver(t) - case ClassInfoType(parents, decls, clazz) => - parents foreach { p => traverse; () } - traverse(t.typeOfThis) - case _ => - mapOver(t) - } - this - } - } - -*/ diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index ee687e56b0..0a66ba8a32 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -525,8 +525,7 @@ abstract class Erasure extends AddInterfaces private def isDifferentErasedValueType(tpe: Type, other: Type) = isErasedValueType(tpe) && (tpe ne other) - private def isPrimitiveValueMember(sym: Symbol) = - sym != NoSymbol && isPrimitiveValueClass(sym.owner) + private def isPrimitiveValueMember(sym: Symbol) = isPrimitiveValueClass(sym.owner) @inline private def box(tree: Tree, target: => String): Tree = { val result = box1(tree) diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index ce495ca8ca..515fa66cfa 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -489,7 +489,7 @@ abstract class LambdaLift extends InfoTransform { treeCopy.Assign(tree, qual, rhs) case Ident(name) => val tree1 = - if (sym != NoSymbol && sym.isTerm && !sym.isLabel) + if (sym.isTerm && !sym.isLabel) if (sym.isMethod) atPos(tree.pos)(memberRef(sym)) else if (sym.isLocal && !isSameOwnerEnclosure(sym)) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 1c44e86aca..3ec4d16bf5 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -734,10 +734,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { sym } - if (sym ne NoSymbol) - sym - else - createBitmap + sym orElse createBitmap } def maskForOffset(offset: Int, sym: Symbol, kind: ClassSymbol): Tree = { diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala index f089c8f5a5..dfd18d089e 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala @@ -222,7 +222,7 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT // so that we don't introduce new aliases for existing symbols, thus keeping the set of bound symbols minimal val (boundSubst, unboundSubst) = (subst.from zip subst.to) partition { case (f, t) => - t.isInstanceOf[Ident] && (t.symbol ne NoSymbol) && pointsToBound(f) + t.isInstanceOf[Ident] && t.symbol.exists && pointsToBound(f) } val (boundFrom, boundTo) = boundSubst.unzip val (unboundFrom, unboundTo) = unboundSubst.unzip @@ -624,9 +624,9 @@ trait MatchAnalysis extends MatchApproximation { private lazy val uniqueEqualTo = equalTo filterNot (subsumed => equalTo.exists(better => (better ne subsumed) && instanceOfTpImplies(better.tp, subsumed.tp))) private lazy val prunedEqualTo = uniqueEqualTo filterNot (subsumed => variable.staticTpCheckable <:< subsumed.tp) private lazy val ctor = (prunedEqualTo match { case List(TypeConst(tp)) => tp case _ => variable.staticTpCheckable }).typeSymbol.primaryConstructor - private lazy val ctorParams = if (ctor == NoSymbol || ctor.paramss.isEmpty) Nil else ctor.paramss.head - private lazy val cls = if (ctor == NoSymbol) NoSymbol else ctor.owner - private lazy val caseFieldAccs = if (cls == NoSymbol) Nil else cls.caseFieldAccessors + private lazy val ctorParams = if (ctor.paramss.isEmpty) Nil else ctor.paramss.head + private lazy val cls = ctor.safeOwner + private lazy val caseFieldAccs = cls.caseFieldAccessors def addField(symbol: Symbol, assign: VariableAssignment) { // SI-7669 Only register this field if if this class contains it. diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala index 1e4c56529c..6f597bef39 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala @@ -173,13 +173,13 @@ trait MatchCodeGen extends Interface { // catchAll.isEmpty iff no synthetic default case needed (the (last) user-defined case is a default) // if the last user-defined case is a default, it will never jump to the next case; it will go immediately to matchEnd val catchAllDef = matchFailGen map { matchFailGen => - val scrutRef = if(scrutSym ne NoSymbol) REF(scrutSym) else EmptyTree // for alternatives + val scrutRef = scrutSym.fold(EmptyTree: Tree)(REF) // for alternatives LabelDef(_currCase, Nil, matchEnd APPLY (matchFailGen(scrutRef))) } toList // at most 1 element // scrutSym == NoSymbol when generating an alternatives matcher - val scrutDef = if(scrutSym ne NoSymbol) List(VAL(scrutSym) === scrut) else Nil // for alternatives + val scrutDef = scrutSym.fold(List[Tree]())(sym => (VAL(sym) === scrut) :: Nil) // for alternatives // the generated block is taken apart in TailCalls under the following assumptions // the assumption is once we encounter a case, the remainder of the block will consist of cases diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala index fcee142932..9bc442467d 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala @@ -659,7 +659,7 @@ trait MatchTranslation { self: PatternMatching => object Bound { def unapply(t: Tree): Option[(Symbol, Tree)] = t match { - case t@Bind(n, p) if (t.symbol ne null) && (t.symbol ne NoSymbol) => // pos/t2429 does not satisfy these conditions + case t@Bind(n, p) if t.hasExistingSymbol => // pos/t2429 does not satisfy these conditions Some((t.symbol, p)) case _ => None } diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala index baccdcf544..b0a7749908 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala @@ -587,9 +587,8 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { t.symbol.owner = currentOwner case d : DefTree if (d.symbol != NoSymbol) && ((d.symbol.owner == NoSymbol) || (d.symbol.owner == origOwner)) => // don't indiscriminately change existing owners! (see e.g., pos/t3440, pos/t3534, pos/unapplyContexts2) debug.patmat("def: "+ ((d, d.symbol.ownerChain, currentOwner.ownerChain))) - if(d.symbol.moduleClass ne NoSymbol) - d.symbol.moduleClass.owner = currentOwner + d.symbol.moduleClass andAlso (_.owner = currentOwner) d.symbol.owner = currentOwner // case _ if (t.symbol != NoSymbol) && (t.symbol ne null) => debug.patmat("untouched "+ ((t, t.getClass, t.symbol.ownerChain, currentOwner.ownerChain))) diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index f3a22a2cee..86a0d33737 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -269,7 +269,7 @@ trait Contexts { self: Analyzer => /** The next enclosing context (potentially `this`) that is owned by a class or method */ def enclClassOrMethod: Context = - if ((owner eq NoSymbol) || (owner.isClass) || (owner.isMethod)) this + if (!owner.exists || owner.isClass || owner.isMethod) this else outer.enclClassOrMethod /** The next enclosing context (potentially `this`) that has a `CaseDef` as a tree */ @@ -653,13 +653,8 @@ trait Contexts { self: Analyzer => lastAccessCheckDetails = "" // Console.println("isAccessible(%s, %s, %s)".format(sym, pre, superAccess)) - def accessWithinLinked(ab: Symbol) = { - val linked = ab.linkedClassOfClass - // don't have access if there is no linked class - // (before adding the `ne NoSymbol` check, this was a no-op when linked eq NoSymbol, - // since `accessWithin(NoSymbol) == true` whatever the symbol) - (linked ne NoSymbol) && accessWithin(linked) - } + // don't have access if there is no linked class (so exclude linkedClass=NoSymbol) + def accessWithinLinked(ab: Symbol) = ab.linkedClassOfClass.fold(false)(accessWithin) /* Are we inside definition of `ab`? */ def accessWithin(ab: Symbol) = { @@ -957,7 +952,7 @@ trait Contexts { self: Analyzer => // 2) sym.owner is inherited by the correct package object class // We try to establish 1) by inspecting the owners directly, and then we try // to rule out 2), and only if both those fail do we resort to looking in the info. - !sym.isPackage && (sym.owner ne NoSymbol) && ( + !sym.isPackage && sym.owner.exists && ( if (sym.owner.isPackageObjectClass) sym.owner.owner == pkgClass else diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index 0a2628b482..396f3407f3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -74,22 +74,19 @@ abstract class Duplicators extends Analyzer { override def mapOver(tpe: Type): Type = tpe match { case TypeRef(NoPrefix, sym, args) if sym.isTypeParameterOrSkolem => - var sym1 = context.scope.lookup(sym.name) - if (sym1 eq NoSymbol) { - // try harder (look in outer scopes) - // with virtpatmat, this can happen when the sym is referenced in the scope of a LabelDef but is defined in the scope of an outer DefDef (e.g., in AbstractPartialFunction's andThen) - BodyDuplicator.super.silent(_.typedType(Ident(sym.name))) match { - case SilentResultValue(t) => - sym1 = t.symbol - debuglog("fixed by trying harder: "+((sym, sym1, context))) - case _ => - } - } -// assert(sym1 ne NoSymbol, tpe) - if ((sym1 ne NoSymbol) && (sym1 ne sym)) { - debuglog("fixing " + sym + " -> " + sym1) + val sym1 = ( + context.scope lookup sym.name orElse { + // try harder (look in outer scopes) + // with virtpatmat, this can happen when the sym is referenced in the scope of a LabelDef but + // is defined in the scope of an outer DefDef (e.g., in AbstractPartialFunction's andThen) + BodyDuplicator.super.silent(_ typedType Ident(sym.name)).fold(NoSymbol: Symbol)(_.symbol) + } filter (_ ne sym) + ) + if (sym1.exists) { + debuglog(s"fixing $sym -> $sym1") typeRef(NoPrefix, sym1, mapOverArgs(args, sym1.typeParams)) - } else super.mapOver(tpe) + } + else super.mapOver(tpe) case TypeRef(pre, sym, args) => val newsym = updateSym(sym) @@ -157,7 +154,7 @@ abstract class Duplicators extends Analyzer { case vdef @ ValDef(mods, name, _, rhs) if mods.hasFlag(Flags.LAZY) => debuglog("ValDef " + name + " sym.info: " + vdef.symbol.info) invalidSyms(vdef.symbol) = vdef - val newowner = if (owner != NoSymbol) owner else context.owner + val newowner = owner orElse context.owner val newsym = vdef.symbol.cloneSymbol(newowner) newsym.setInfo(fixType(vdef.symbol.info)) vdef.symbol = newsym @@ -362,12 +359,11 @@ abstract class Duplicators extends Analyzer { case _ => debuglog("Duplicators default case: " + tree.summaryString) debuglog(" ---> " + tree) - if (tree.hasSymbolField && tree.symbol != NoSymbol && (tree.symbol.owner == AnyClass)) { + if (tree.hasSymbolField && tree.symbol.safeOwner == AnyClass) tree.symbol = NoSymbol // maybe we can find a more specific member in a subclass of Any (see AnyVal members, like ==) - } + val ntree = castType(tree, pt) - val res = super.typed(ntree, mode, pt) - res + super.typed(ntree, mode, pt) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index cac6bd2ef2..2bb2cc1ab4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -390,9 +390,7 @@ trait Namers extends MethodSynthesis { * has been defined in a separate file. */ private def validateCompanionDefs(tree: ImplDef) { - val sym = tree.symbol - if (sym eq NoSymbol) return - + val sym = tree.symbol orElse { return } val ctx = if (context.owner.isPackageObjectClass) context.outer else context val module = if (sym.isModule) sym else ctx.scope lookupModule tree.name val clazz = if (sym.isClass) sym else ctx.scope lookupClass tree.name diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 30b923e2a1..66dff792b6 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -216,7 +216,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans val inherited = clazz.info.nonPrivateMemberAdmitting(member.name, VBRIDGE) // Delaying calling memberType as long as possible - if (inherited ne NoSymbol) { + if (inherited.exists) { val jtpe = toJavaRepeatedParam(self memberType member) // this is a bit tortuous: we look for non-private members or bridges // if we find a bridge everything is OK. If we find another member, @@ -1521,7 +1521,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans checkCompileTimeOnly(sym, tree.pos) checkDelayedInitSelect(qual, sym, tree.pos) - if (sym eq NoSymbol) + if (!sym.exists) devWarning("Select node has NoSymbol! " + tree + " / " + tree.tpe) else if (sym.hasLocalFlag) varianceValidator.checkForEscape(sym, currentClass) diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 6933b10a0a..12d6bb2e6a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -269,8 +269,8 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT && sym.enclClass != currentClass && !sym.owner.isPackageClass // SI-7091 no accessor needed package owned (ie, top level) symbols && !sym.owner.isTrait - && (sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass) - && (qual.symbol.info.member(sym.name) ne NoSymbol) + && sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass + && qual.symbol.info.member(sym.name).exists && !needsProtectedAccessor(sym, tree.pos) ) if (shouldEnsureAccessor) { diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index b4a37f9943..0c5f798c23 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -143,7 +143,7 @@ trait TypeDiagnostics { def defaultMessage = moduleMessage + preResultString + tree.tpe def applyMessage = defaultMessage + tree.symbol.locationString - if ((sym eq null) || (sym eq NoSymbol)) { + if (!tree.hasExistingSymbol) { if (isTyperInPattern) patternMessage else exprMessage } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index d2ff47626d..f0c0942e95 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -63,6 +63,10 @@ trait Typers extends Adaptations with Tags with TypersTracking { } sealed abstract class SilentResult[+T] { + @inline final def fold[U](none: => U)(f: T => U): U = this match { + case SilentResultValue(value) => f(value) + case _ => none + } @inline final def map[U](f: T => U): SilentResult[U] = this match { case SilentResultValue(value) => SilentResultValue(f(value)) case x: SilentTypeError => x diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 6b7aa2dddf..6715a5d1a6 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -227,10 +227,7 @@ trait Definitions extends api.StandardDefinitions { scope } /** Is this symbol a member of Object or Any? */ - def isUniversalMember(sym: Symbol) = ( - (sym ne NoSymbol) - && (ObjectClass isSubClass sym.owner) - ) + def isUniversalMember(sym: Symbol) = ObjectClass isSubClass sym.owner /** Is this symbol unimportable? Unimportable symbols include: * - constructors, because <init> is not a real name diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index c340670635..f0be0f7d05 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -60,6 +60,7 @@ abstract class SymbolTable extends macros.Universe def shouldLogAtThisPhase = false def isPastTyper = false + protected def isDeveloper: Boolean = settings.debug @deprecated("Give us a reason", "2.10.0") def abort(): Nothing = abort("unknown error") @@ -69,8 +70,12 @@ abstract class SymbolTable extends macros.Universe /** Override with final implementation for inlining. */ def debuglog(msg: => String): Unit = if (settings.debug) log(msg) - def devWarning(msg: => String): Unit = if (settings.debug) Console.err.println(msg) + def devWarning(msg: => String): Unit = if (isDeveloper) Console.err.println(msg) def throwableAsString(t: Throwable): String = "" + t + def throwableAsString(t: Throwable, maxFrames: Int): String = t.getStackTrace take maxFrames mkString "\n at " + + @inline final def devWarningDumpStack(msg: => String, maxFrames: Int): Unit = + devWarning(msg + "\n" + throwableAsString(new Throwable, maxFrames)) /** Prints a stack trace if -Ydebug or equivalent was given, otherwise does nothing. */ def debugStack(t: Throwable): Unit = devWarning(throwableAsString(t)) diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index e41038cafc..a8efa938c8 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -153,7 +153,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => } def asNameType(n: Name): NameType - private[this] var _rawowner = initOwner // Syncnote: need not be protected, as only assignment happens in owner_=, which is not exposed to api + // Syncnote: need not be protected, as only assignment happens in owner_=, which is not exposed to api + // The null check is for NoSymbol, which can't pass a reference to itself to the constructor and also + // can't call owner_= due to an assertion it contains. + private[this] var _rawowner = if (initOwner eq null) this else initOwner private[this] var _rawflags: Long = _ def rawowner = _rawowner @@ -610,7 +613,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } final def isLazyAccessor = isLazy && lazyAccessor != NoSymbol - final def isOverridableMember = !(isClass || isEffectivelyFinal) && (this ne NoSymbol) && owner.isClass + final def isOverridableMember = !(isClass || isEffectivelyFinal) && safeOwner.isClass /** Does this symbol denote a wrapper created by the repl? */ final def isInterpreterWrapper = ( @@ -999,13 +1002,20 @@ trait Symbols extends api.Symbols { self: SymbolTable => // ------ owner attribute -------------------------------------------------------------- + /** In general when seeking the owner of a symbol, one should call `owner`. + * The other possibilities include: + * - call `safeOwner` if it is expected that the target may be NoSymbol + * - call `assertOwner` if it is an unrecoverable error if the target is NoSymbol + * + * `owner` behaves like `safeOwner`, but logs NoSymbol.owner calls under -Xdev. + * `assertOwner` aborts compilation immediately if called on NoSymbol. + */ def owner: Symbol = { if (Statistics.hotEnabled) Statistics.incCounter(ownerCount) rawowner } - - // Like owner, but NoSymbol.owner == NoSymbol instead of throwing an exception. - final def safeOwner: Symbol = if (this eq NoSymbol) NoSymbol else owner + final def safeOwner: Symbol = if (this eq NoSymbol) NoSymbol else owner + final def assertOwner: Symbol = if (this eq NoSymbol) abort("no-symbol does not have an owner") else owner // TODO - don't allow the owner to be changed without checking invariants, at least // when under some flag. Define per-phase invariants for owner/owned relationships, @@ -1781,10 +1791,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => result } - @inline final def map(f: Symbol => Symbol): Symbol = if (this eq NoSymbol) this else f(this) - - final def toOption: Option[Symbol] = if (exists) Some(this) else None - // ------ cloneing ------------------------------------------------------------------- /** A clone of this symbol. */ @@ -2179,8 +2185,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => * the recursive knot. */ private def canMatchInheritedSymbols = ( - (this ne NoSymbol) - && owner.isClass + owner.isClass && !this.isClass && !this.isConstructor ) @@ -2352,6 +2357,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => @inline final def orElse(alt: => Symbol): Symbol = if (this ne NoSymbol) this else alt @inline final def andAlso(f: Symbol => Unit): Symbol = { if (this ne NoSymbol) f(this) ; this } + @inline final def fold[T](none: => T)(f: Symbol => T): T = if (this ne NoSymbol) f(this) else none + @inline final def map(f: Symbol => Symbol): Symbol = if (this eq NoSymbol) this else f(this) + + final def toOption: Option[Symbol] = if (exists) Some(this) else None + // ------ toString ------------------------------------------------------------------- @@ -3340,7 +3350,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def enclosingPackageClass: Symbol = this override def enclMethod: Symbol = this override def associatedFile = NoAbstractFile - override def ownerChain: List[Symbol] = List() + override def owner: Symbol = { + devWarningDumpStack("NoSymbol.owner", 15) + this + } + override def ownerChain: List[Symbol] = Nil override def ownersIterator: Iterator[Symbol] = Iterator.empty override def alternatives: List[Symbol] = List() override def reset(completer: Type): this.type = this @@ -3350,9 +3364,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def accessBoundary(base: Symbol): Symbol = enclosingRootClass def cloneSymbolImpl(owner: Symbol, newFlags: Long) = abort("NoSymbol.clone()") override def originalEnclosingMethod = this - - override def owner: Symbol = - abort("no-symbol does not have an owner") } protected def makeNoSymbol: NoSymbol = new NoSymbol diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 02bee5e369..a5a78cb3b8 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -185,8 +185,8 @@ trait Trees extends api.Trees { self: SymbolTable => def replace(from: Tree, to: Tree): Tree = new TreeReplacer(from, to, positionAware = false) transform this - def hasSymbolWhich(f: Symbol => Boolean) = - (symbol ne null) && (symbol ne NoSymbol) && f(symbol) + def hasExistingSymbol = (symbol ne null) && (symbol ne NoSymbol) + def hasSymbolWhich(f: Symbol => Boolean) = hasExistingSymbol && f(symbol) def isErroneous = (tpe ne null) && tpe.isErroneous def isTyped = (tpe ne null) && !tpe.isErroneous diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 71f46fedb7..cab2303dd0 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -3475,7 +3475,7 @@ trait Types def copyRefinedType(original: RefinedType, parents: List[Type], decls: Scope) = if ((parents eq original.parents) && (decls eq original.decls)) original else { - val owner = if (original.typeSymbol == NoSymbol) NoSymbol else original.typeSymbol.owner + val owner = original.typeSymbol.owner val result = refinedType(parents, owner) val syms1 = decls.toList for (sym <- syms1) diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala index bebc419c7c..6662ec522a 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala @@ -524,7 +524,7 @@ private[internal] trait TypeMaps { private def correspondingTypeArgument(lhs: Type, rhs: Type): Type = { val TypeRef(_, lhsSym, lhsArgs) = lhs val TypeRef(_, rhsSym, rhsArgs) = rhs - require(lhsSym.safeOwner == rhsSym, s"$lhsSym is not a type parameter of $rhsSym") + require(lhsSym.owner == rhsSym, s"$lhsSym is not a type parameter of $rhsSym") // Find the type parameter position; we'll use the corresponding argument. // Why are we checking by name rather than by equality? Because for @@ -539,7 +539,7 @@ private[internal] trait TypeMaps { else { // It's easy to get here when working on hardcore type machinery (not to // mention when not doing so, see above) so let's provide a standout error. - def own_s(s: Symbol) = s.nameString + " in " + s.safeOwner.nameString + def own_s(s: Symbol) = s.nameString + " in " + s.owner.nameString def explain = sm"""| sought ${own_s(lhsSym)} | classSym ${own_s(rhsSym)} diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index ae318697ec..1723344306 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -297,19 +297,9 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set def flatPath(sym: Symbol): String = flatOp shift sym.javaClassName def translatePath(path: String) = { val sym = if (path endsWith "$") symbolOfTerm(path.init) else symbolOfIdent(path) - sym match { - case NoSymbol => None - case _ => Some(flatPath(sym)) - } - } - def translateEnclosingClass(n: String) = { - def enclosingClass(s: Symbol): Symbol = - if (s == NoSymbol || s.isClass) s else enclosingClass(s.owner) - enclosingClass(symbolOfTerm(n)) match { - case NoSymbol => None - case c => Some(flatPath(c)) - } + sym.toOption map flatPath } + def translateEnclosingClass(n: String) = symbolOfTerm(n).enclClass.toOption map flatPath private class TranslatingClassLoader(parent: ClassLoader) extends util.AbstractFileClassLoader(replOutput.dir, parent) { /** Overridden here to try translating a simple name to the generated diff --git a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala index 085a7c6065..c1faf30385 100644 --- a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala +++ b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala @@ -71,7 +71,7 @@ trait MemberHandlers { override def definesImplicit = member.mods.isImplicit override def definesTerm: Option[TermName] = Some(name.toTermName) filter (_ => name.isTermName) override def definesType: Option[TypeName] = Some(name.toTypeName) filter (_ => name.isTypeName) - override def definedSymbols = if (symbol eq NoSymbol) Nil else List(symbol) + override def definedSymbols = if (symbol.exists) symbol :: Nil else Nil } /** Class to handle one member among all the members included |