diff options
Diffstat (limited to 'src')
31 files changed, 318 insertions, 203 deletions
diff --git a/src/compiler/scala/reflect/macros/util/Helpers.scala b/src/compiler/scala/reflect/macros/util/Helpers.scala index ada8efa833..9b7680717e 100644 --- a/src/compiler/scala/reflect/macros/util/Helpers.scala +++ b/src/compiler/scala/reflect/macros/util/Helpers.scala @@ -54,7 +54,7 @@ trait Helpers { * * @see Metalevels.scala for more information and examples about metalevels */ - def increaseMetalevel(pre: Type, tp: Type): Type = dealiasAndRewrap(tp) { + def increaseMetalevel(pre: Type, tp: Type): Type = transparentShallowTransform(RepeatedParamClass, tp) { case tp => typeRef(pre, MacroContextExprClass, List(tp)) } @@ -64,8 +64,8 @@ trait Helpers { * * @see Metalevels.scala for more information and examples about metalevels */ - def decreaseMetalevel(tp: Type): Type = dealiasAndRewrap(tp) { + def decreaseMetalevel(tp: Type): Type = transparentShallowTransform(RepeatedParamClass, tp) { case ExprClassOf(runtimeType) => runtimeType - case _ => AnyClass.tpe // so that macro impls with rhs = ??? don't screw up our inference + case _ => AnyTpe // so that macro impls with rhs = ??? don't screw up our inference } }
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index a08633ffc8..eafe03d5cd 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -1060,14 +1060,12 @@ class Global(var currentSettings: Settings, var reporter: Reporter) @inline final def enteringTyper[T](op: => T): T = enteringPhase(currentRun.typerPhase)(op) @inline final def enteringUncurry[T](op: => T): T = enteringPhase(currentRun.uncurryPhase)(op) - // Owners up to and including the first package class. + // Owners which aren't package classes. private def ownerChainString(sym: Symbol): String = ( if (sym == null) "" - else sym.ownerChain.span(!_.isPackageClass) match { - case (xs, pkg :: _) => (xs :+ pkg) mkString " -> " - case _ => sym.ownerChain mkString " -> " // unlikely - } + else sym.ownerChain takeWhile (!_.isPackageClass) mkString " -> " ) + private def formatExplain(pairs: (String, Any)*): String = ( pairs.toList collect { case (k, v) if v != null => "%20s: %s".format(k, v) } mkString "\n" ) @@ -1075,41 +1073,45 @@ class Global(var currentSettings: Settings, var reporter: Reporter) /** Don't want to introduce new errors trying to report errors, * so swallow exceptions. */ - override def supplementErrorMessage(errorMessage: String): String = + override def supplementErrorMessage(errorMessage: String): String = { if (currentRun.supplementedError) errorMessage else try { + currentRun.supplementedError = true val tree = analyzer.lastTreeToTyper val sym = tree.symbol val tpe = tree.tpe - val enclosing = lastSeenContext.enclClassOrMethod.tree + val site = lastSeenContext.enclClassOrMethod.owner + val pos_s = if (tree.pos.isDefined) s"line ${tree.pos.line} of ${tree.pos.source.file}" else "<unknown>" + val context_s = try { + // Taking 3 before, 3 after the fingered line. + val start = 0 max (tree.pos.line - 3) + val xs = scala.reflect.io.File(tree.pos.source.file.file).lines drop start take 7 + val strs = xs.zipWithIndex map { case (line, idx) => f"${start + idx}%6d $line" } + strs.mkString("== Source file context for tree position ==\n\n", "\n", "") + } + catch { case t: Exception => devWarning("" + t) ; "<Cannot read source file>" } val info1 = formatExplain( "while compiling" -> currentSource.path, - "during phase" -> ( if (globalPhase eq phase) phase else "global=%s, enteringPhase=%s".format(globalPhase, phase) ), + "during phase" -> ( if (globalPhase eq phase) phase else "globalPhase=%s, enteringPhase=%s".format(globalPhase, phase) ), "library version" -> scala.util.Properties.versionString, "compiler version" -> Properties.versionString, "reconstructed args" -> settings.recreateArgs.mkString(" ") ) val info2 = formatExplain( "last tree to typer" -> tree.summaryString, + "tree position" -> pos_s, + "tree tpe" -> tpe, "symbol" -> Option(sym).fold("null")(_.debugLocationString), - "symbol definition" -> Option(sym).fold("null")(_.defString), - "tpe" -> tpe, + "symbol definition" -> Option(sym).fold("null")(s => s.defString + s" (a ${s.shortSymbolClass})"), + "symbol package" -> sym.enclosingPackage.fullName, "symbol owners" -> ownerChainString(sym), - "context owners" -> ownerChainString(lastSeenContext.owner) + "call site" -> (site.fullLocationString + " in " + site.enclosingPackage) ) - val info3: List[String] = ( - ( List("== Enclosing template or block ==", nodePrinters.nodeToString(enclosing).trim) ) - ++ ( if (tpe eq null) Nil else List("== Expanded type of tree ==", typeDeconstruct.show(tpe)) ) - ++ ( if (!settings.debug) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) ) - ++ ( List(errorMessage) ) - ) - - currentRun.supplementedError = true - - ("\n" + info1) :: info2 :: info3 mkString "\n\n" + ("\n" + info1) :: info2 :: context_s :: Nil mkString "\n\n" } catch { case _: Exception | _: TypeError => errorMessage } + } /** The id of the currently active run */ @@ -1393,9 +1395,13 @@ class Global(var currentSettings: Settings, var reporter: Reporter) def registerPickle(sym: Symbol): Unit = () /** does this run compile given class, module, or case factory? */ + // NOTE: Early initialized members temporarily typechecked before the enclosing class, see typedPrimaryConstrBody! + // Here we work around that wrinkle by claiming that a top-level, early-initialized member is compiled in + // *every* run. This approximation works because this method is exclusively called with `this` == `currentRun`. def compiles(sym: Symbol): Boolean = if (sym == NoSymbol) false else if (symSource.isDefinedAt(sym)) true + else if (sym.isTopLevel && sym.isEarlyInitialized) true else if (!sym.isTopLevel) compiles(sym.enclosingTopLevelClass) else if (sym.isModuleClass) compiles(sym.sourceModule) else false @@ -1493,18 +1499,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) compileUnits(sources map (new CompilationUnit(_)), firstPhase) } - def compileUnits(units: List[CompilationUnit], fromPhase: Phase) { - try compileUnitsInternal(units, fromPhase) - catch { case ex: Throwable => - val shown = if (settings.verbose) - stackTraceString(ex) - else - stackTraceHeadString(ex) // note that error stacktraces do not print in fsc - - globalError(supplementErrorMessage("uncaught exception during compilation: " + shown)) - throw ex - } - } + def compileUnits(units: List[CompilationUnit], fromPhase: Phase): Unit = + compileUnitsInternal(units, fromPhase) private def compileUnitsInternal(units: List[CompilationUnit], fromPhase: Phase) { doInvalidation() diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 8391ebdafc..41d89aa3b4 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -221,7 +221,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => try unit.body = transform(unit.body) catch { case ex: Exception => - println(supplementErrorMessage("unhandled exception while transforming "+unit)) + log(supplementErrorMessage("unhandled exception while transforming "+unit)) throw ex } } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 7edcc944e1..19a6e11986 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -1270,9 +1270,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { private def getSuperInterfaces(c: IClass): Array[String] = { // Additional interface parents based on annotations and other cues - def newParentForAttr(attr: Symbol): Option[Symbol] = attr match { - case RemoteAttr => Some(RemoteInterfaceClass) - case _ => None + def newParentForAttr(ann: AnnotationInfo): Symbol = ann.symbol match { + case RemoteAttr => RemoteInterfaceClass + case _ => NoSymbol } /* Drop redundant interfaces (ones which are implemented by some other parent) from the immediate parents. @@ -1295,7 +1295,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { val ps = c.symbol.info.parents val superInterfaces0: List[Symbol] = if(ps.isEmpty) Nil else c.symbol.mixinClasses - val superInterfaces = (superInterfaces0 ++ c.symbol.annotations.flatMap(ann => newParentForAttr(ann.symbol))).distinct + val superInterfaces = existingSymbols(superInterfaces0 ++ c.symbol.annotations.map(newParentForAttr)).distinct if(superInterfaces.isEmpty) EMPTY_STRING_ARRAY else mkArray(minimizeInterfaces(superInterfaces) map javaName) diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index 250feb69bf..fd85bbb169 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -244,9 +244,9 @@ abstract class SymbolLoaders { } class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader with FlagAssigningCompleter { - private object classfileParser extends ClassfileParser { + private object classfileParser extends { val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global - } + } with ClassfileParser protected def description = "class file "+ classfile.toString diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index fb927d15d3..cbfe5460f6 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -39,7 +39,7 @@ abstract class ClassfileParser { protected var isScala: Boolean = _ // does class file describe a scala class? protected var isScalaAnnot: Boolean = _ // does class file describe a scala class with its pickled info in an annotation? protected var isScalaRaw: Boolean = _ // this class file is a scala class with no pickled info - protected var busy: Option[Symbol] = None // lock to detect recursive reads + protected var busy: Symbol = _ // lock to detect recursive reads protected var currentClass: Name = _ // JVM name of the current class protected var classTParams = Map[Name,Symbol]() protected var srcfile0 : Option[AbstractFile] = None @@ -90,16 +90,15 @@ abstract class ClassfileParser { case e: RuntimeException => handleError(e) } @inline private def pushBusy[T](sym: Symbol)(body: => T): T = { - busy match { - case Some(`sym`) => throw new IOException(s"unsatisfiable cyclic dependency in '$sym'") - case Some(sym1) => throw new IOException(s"illegal class file dependency between '$sym' and '$sym1'") - case _ => () - } + if (busy eq sym) + throw new IOException(s"unsatisfiable cyclic dependency in '$sym'") + else if ((busy ne null) && (busy ne NoSymbol)) + throw new IOException(s"illegal class file dependency between '$sym' and '$busy'") - busy = Some(sym) + busy = sym try body catch parseErrorHandler - finally busy = None + finally busy = NoSymbol } @inline private def raiseLoaderLevel[T](body: => T): T = { loaders.parentsLevel += 1 @@ -588,10 +587,14 @@ abstract class ClassfileParser { // sealed java enums if (jflags.isEnum) { val enumClass = sym.owner.linkedClassOfClass - if (!enumClass.isSealed) - enumClass setFlag (SEALED | ABSTRACT) - - enumClass addChild sym + enumClass match { + case NoSymbol => + devWarning(s"no linked class for java enum $sym in ${sym.owner}. A referencing class file might be missing an InnerClasses entry.") + case linked => + if (!linked.isSealed) + linked setFlag (SEALED | ABSTRACT) + linked addChild sym + } } } } diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 385bf2dade..75fb043070 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -533,7 +533,10 @@ abstract class Constructors extends Transform with ast.TreeDSL { /* Return a pair consisting of (all statements up to and including superclass and trait constr calls, rest) */ def splitAtSuper(stats: List[Tree]) = { - def isConstr(tree: Tree) = (tree.symbol ne null) && tree.symbol.isConstructor + def isConstr(tree: Tree): Boolean = tree match { + case Block(_, expr) => isConstr(expr) // SI-6481 account for named argument blocks + case _ => (tree.symbol ne null) && tree.symbol.isConstructor + } val (pre, rest0) = stats span (!isConstr(_)) val (supercalls, rest) = rest0 span (isConstr(_)) (pre ::: supercalls, rest) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index eca958fd8d..e0b1d9ea80 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -594,11 +594,10 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { sym.owner.info //todo: needed? sym.owner.owner.info //todo: needed? - assert( - sym.owner.sourceModule ne NoSymbol, - "" + sym.fullLocationString + " in " + sym.owner.owner + " " + sym.owner.owner.info.decls - ) - REF(sym.owner.sourceModule) DOT sym + if (sym.owner.sourceModule eq NoSymbol) + abort(s"Cannot create static reference to $sym because ${sym.safeOwner} has no source module") + else + REF(sym.owner.sourceModule) DOT sym } def needsInitAndHasOffset(sym: Symbol) = diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index cc4b2d544b..f43e42c027 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -1388,10 +1388,26 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { /* The specialized symbol of 'tree.symbol' for tree.tpe, if there is one */ def specSym(qual: Tree): Symbol = { val env = unify(symbol.tpe, tree.tpe, emptyEnv, false) - def isMatch(member: Symbol) = ( - doesConform(symbol, tree.tpe, qual.tpe memberType member, env) - && TypeEnv.includes(typeEnv(member), env) - ) + def isMatch(member: Symbol) = { + val memberType = qual.tpe memberType member + + val residualTreeType = tree match { + case TypeApply(fun, targs) if fun.symbol == symbol => + // SI-6308 Handle methods with only some type parameters specialized. + // drop the specialized type parameters from the PolyType, and + // substitute in the type environment. + val GenPolyType(tparams, tpe) = fun.tpe + val (from, to) = env.toList.unzip + val residualTParams = tparams.filterNot(env.contains) + GenPolyType(residualTParams, tpe).substituteTypes(from, to) + case _ => tree.tpe + } + + ( + doesConform(symbol, residualTreeType, memberType, env) + && TypeEnv.includes(typeEnv(member), env) + ) + } if (env.isEmpty) NoSymbol else qual.tpe member specializedName(symbol, env) suchThat isMatch } diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index fe1607c631..7fa199afaf 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -782,7 +782,7 @@ trait ContextErrors { } def MacroExpansionHasInvalidTypeError(expandee: Tree, expanded: Any) = { - val expected = "expr" + val expected = "expr or tree" val isPathMismatch = expanded != null && expanded.isInstanceOf[scala.reflect.api.Exprs#Expr[_]] macroExpansionError(expandee, s"macro must return a compiler-specific $expected; returned value is " + ( diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 6c4d1e20aa..86ba3d2164 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -92,11 +92,12 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { methName: String, // flattens the macro impl's parameter lists having symbols replaced with their fingerprints // currently fingerprints are calculated solely from types of the symbols: - // * c.Expr[T] => IMPLPARAM_EXPR - // * c.WeakTypeTag[T] => index of the type parameter corresponding to that type tag - // * everything else (e.g. scala.reflect.macros.Context) => IMPLPARAM_OTHER + // * c.Expr[T] => LiftedTyped + // * c.Tree => LiftedUntyped + // * c.WeakTypeTag[T] => Tagged(index of the type parameter corresponding to that type tag) + // * everything else (e.g. scala.reflect.macros.Context) => Other // f.ex. for: def impl[T: WeakTypeTag, U, V: WeakTypeTag](c: Context)(x: c.Expr[T], y: c.Tree): (U, V) = ??? - // `signature` will be equal to List(List(Other), List(Lifted, Other), List(Tagged(0), Tagged(2))) + // `signature` will be equal to List(List(Other), List(LiftedTyped, LiftedUntyped), List(Tagged(0), Tagged(2))) signature: List[List[Fingerprint]], // type arguments part of a macro impl ref (the right-hand side of a macro definition) // these trees don't refer to a macro impl, so we can pickle them as is @@ -124,7 +125,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { * "className" = "Macros$")) */ object MacroImplBinding { - val versionFormat = 4.0 + val versionFormat = 5.0 def pickleAtom(obj: Any): Tree = obj match { @@ -164,7 +165,8 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { def signature: List[List[Fingerprint]] = { def fingerprint(tpe: Type): Fingerprint = tpe.dealiasWiden match { case TypeRef(_, RepeatedParamClass, underlying :: Nil) => fingerprint(underlying) - case ExprClassOf(_) => Lifted + case ExprClassOf(_) => LiftedTyped + case TreeType() => LiftedUntyped case _ => Other } @@ -388,7 +390,8 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { val wrappedArgs = mapWithIndex(args)((arg, j) => { val fingerprint = implParams(min(j, implParams.length - 1)) fingerprint match { - case Lifted => context.Expr[Nothing](arg)(TypeTag.Nothing) // TODO: SI-5752 + case LiftedTyped => context.Expr[Nothing](arg)(TypeTag.Nothing) // TODO: SI-5752 + case LiftedUntyped => arg case _ => abort(s"unexpected fingerprint $fingerprint in $binding with paramss being $paramss " + s"corresponding to arg $arg in $argss") } @@ -690,6 +693,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { } expanded match { case expanded: Expr[_] if expandee.symbol.isTermMacro => validateResultingTree(expanded.tree) + case expanded: Tree if expandee.symbol.isTermMacro => validateResultingTree(expanded) case _ => MacroExpansionHasInvalidTypeError(expandee, expanded) } } catch { @@ -804,10 +808,12 @@ class Fingerprint(val value: Int) extends AnyVal { def paramPos = { assert(isTag, this); value } def isTag = value >= 0 def isOther = this == Other - def isExpr = this == Lifted + def isExpr = this == LiftedTyped + def isTree = this == LiftedUntyped override def toString = this match { case Other => "Other" - case Lifted => "Expr" + case LiftedTyped => "Expr" + case LiftedUntyped => "Tree" case _ => s"Tag($value)" } } @@ -815,5 +821,6 @@ class Fingerprint(val value: Int) extends AnyVal { object Fingerprint { def Tagged(tparamPos: Int) = new Fingerprint(tparamPos) val Other = new Fingerprint(-1) - val Lifted = new Fingerprint(-2) + val LiftedTyped = new Fingerprint(-2) + val LiftedUntyped = new Fingerprint(-3) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 4683fca192..0305aab844 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1686,8 +1686,13 @@ trait Namers extends MethodSynthesis { * call this method? */ def companionSymbolOf(original: Symbol, ctx: Context): Symbol = { + val owner = original.owner + // SI-7264 Force the info of owners from previous compilation runs. + // Doing this generally would trigger cycles; that's what we also + // use the lower-level scan through the current Context as a fall back. + if (!currentRun.compiles(owner)) owner.initialize original.companionSymbol orElse { - ctx.lookup(original.name.companionName, original.owner).suchThat(sym => + ctx.lookup(original.name.companionName, owner).suchThat(sym => (original.isTerm || sym.hasModuleFlag) && (sym isCoDefinedWith original) ) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index ec6b78f2de..8d422f415d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -831,8 +831,9 @@ trait Typers extends Adaptations with Tags { else tpr.typed(withImplicitArgs, mode, pt) } orElse { _ => - debuglog("fallback on implicits: " + tree + "/" + resetAllAttrs(original)) - val tree1 = typed(resetAllAttrs(original), mode) + val resetTree = resetLocalAttrs(original) + debuglog(s"fallback on implicits: ${tree}/$resetTree") + val tree1 = typed(resetTree, mode) // Q: `typed` already calls `pluginsTyped` and `adapt`. the only difference here is that // we pass `EmptyTree` as the `original`. intended? added in 2009 (53d98e7d42) by martin. tree1 setType pluginsTyped(tree1.tpe, this, tree1, mode, pt) @@ -3185,7 +3186,7 @@ trait Typers extends Adaptations with Tags { * to that. This is the last thing which is tried (after * default arguments) */ - def tryTupleApply: Option[Tree] = ( + def tryTupleApply: Tree = ( if (eligibleForTupleConversion(paramTypes, argslen) && !phase.erasedTypes) { val tupleArgs = List(atPos(tree.pos.makeTransparent)(gen.mkTuple(args))) // expected one argument, but got 0 or >1 ==> try applying to tuple @@ -3194,14 +3195,15 @@ trait Typers extends Adaptations with Tags { silent(_.doTypedApply(tree, fun, tupleArgs, mode, pt)) map { t => // Depending on user options, may warn or error here if // a Unit or tuple was inserted. - Some(t) filter (tupledTree => + val keepTree = ( !mode.typingExprNotFun - || tupledTree.symbol == null - || checkValidAdaptation(tupledTree, args) + || t.symbol == null + || checkValidAdaptation(t, args) ) - } orElse { _ => context.undetparams = savedUndetparams ; None } - } - else None + if (keepTree) t else EmptyTree + } orElse { _ => context.undetparams = savedUndetparams ; EmptyTree } + } + else EmptyTree ) /* Treats an application which uses named or default arguments. @@ -3214,7 +3216,7 @@ trait Typers extends Adaptations with Tags { def checkNotMacro() = { if (treeInfo.isMacroApplication(fun)) - tryTupleApply getOrElse duplErrorTree(NamedAndDefaultArgumentsNotSupportedForMacros(tree, fun)) + tryTupleApply orElse duplErrorTree(NamedAndDefaultArgumentsNotSupportedForMacros(tree, fun)) } if (mt.isErroneous) duplErrTree @@ -3222,7 +3224,7 @@ trait Typers extends Adaptations with Tags { // #2064 duplErrorTree(WrongNumberOfArgsError(tree, fun)) } else if (lencmp > 0) { - tryTupleApply getOrElse duplErrorTree(TooManyArgsNamesDefaultsError(tree, fun)) + tryTupleApply orElse duplErrorTree(TooManyArgsNamesDefaultsError(tree, fun)) } else if (lencmp == 0) { // we don't need defaults. names were used, so this application is transformed // into a block (@see transformNamedApplication in NamesDefaults) @@ -3275,7 +3277,7 @@ trait Typers extends Adaptations with Tags { if (!(context.diagnostic contains note)) context.diagnostic = note :: context.diagnostic doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt) } else { - tryTupleApply getOrElse duplErrorTree(NotEnoughArgsError(tree, fun, missing)) + tryTupleApply orElse duplErrorTree(NotEnoughArgsError(tree, fun, missing)) } } } @@ -3311,7 +3313,7 @@ trait Typers extends Adaptations with Tags { // instantiate dependent method types, must preserve singleton types where possible (stableTypeFor) -- example use case: // val foo = "foo"; def precise(x: String)(y: x.type): x.type = {...}; val bar : foo.type = precise(foo)(foo) // precise(foo) : foo.type => foo.type - val restpe = mt.resultType(args1 map (arg => gen.stableTypeFor(arg) getOrElse arg.tpe)) + val restpe = mt.resultType(args1 map (arg => gen stableTypeFor arg orElse arg.tpe)) def ifPatternSkipFormals(tp: Type) = tp match { case MethodType(_, rtp) if (mode.inPatternMode) => rtp case _ => tp @@ -3729,7 +3731,7 @@ trait Typers extends Adaptations with Tags { /** Compute an existential type from raw hidden symbols `syms` and type `tp` */ - def packSymbols(hidden: List[Symbol], tp: Type): Type = global.packSymbols(hidden, tp, Some(context0.owner)) + def packSymbols(hidden: List[Symbol], tp: Type): Type = global.packSymbols(hidden, tp, context0.owner) def isReferencedFrom(ctx: Context, sym: Symbol): Boolean = ( ctx.owner.isTerm && diff --git a/src/library/scala/collection/concurrent/TrieMap.scala b/src/library/scala/collection/concurrent/TrieMap.scala index 0b5ceeb1c7..6632f30e51 100644 --- a/src/library/scala/collection/concurrent/TrieMap.scala +++ b/src/library/scala/collection/concurrent/TrieMap.scala @@ -1012,8 +1012,11 @@ private[collection] class TrieMapIterator[K, V](var level: Int, private var ct: */ protected def subdivide(): Seq[Iterator[(K, V)]] = if (subiter ne null) { // the case where an LNode is being iterated - val it = subiter - subiter = null + val it = newIterator(level + 1, ct, _mustInit = false) + it.depth = -1 + it.subiter = this.subiter + it.current = null + this.subiter = null advance() this.level += 1 Seq(it, this) diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 09f8143b55..72c40e889f 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -65,6 +65,7 @@ extends scala.collection.AbstractSeq[Int] || (start < end && step < 0) || (start == end && !isInclusive) ) + @deprecated("This method will be made private, use `length` instead.", "2.11") final val numRangeElements: Int = { if (step == 0) throw new IllegalArgumentException("step cannot be 0.") else if (isEmpty) 0 @@ -74,7 +75,9 @@ extends scala.collection.AbstractSeq[Int] else len.toInt } } + @deprecated("This method will be made private, use `last` instead.", "2.11") final val lastElement = start + (numRangeElements - 1) * step + @deprecated("This method will be made private.", "2.11") final val terminalElement = start + numRangeElements * step override def last = if (isEmpty) Nil.last else lastElement diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala index 4768413e75..5a0d24ddd2 100644 --- a/src/library/scala/collection/immutable/StringLike.scala +++ b/src/library/scala/collection/immutable/StringLike.scala @@ -222,12 +222,33 @@ self => */ def r(groupNames: String*): Regex = new Regex(toString, groupNames: _*) + /** + * @throws `java.lang.IllegalArgumentException` - If the string does not contain a parsable boolean. + */ def toBoolean: Boolean = parseBoolean(toString) + /** + * @throws `java.lang.NumberFormatException` - If the string does not contain a parsable byte. + */ def toByte: Byte = java.lang.Byte.parseByte(toString) + /** + * @throws `java.lang.NumberFormatException` - If the string does not contain a parsable short. + */ def toShort: Short = java.lang.Short.parseShort(toString) + /** + * @throws `java.lang.NumberFormatException` - If the string does not contain a parsable int. + */ def toInt: Int = java.lang.Integer.parseInt(toString) + /** + * @throws `java.lang.NumberFormatException` - If the string does not contain a parsable long. + */ def toLong: Long = java.lang.Long.parseLong(toString) + /** + * @throws `java.lang.NumberFormatException` - If the string does not contain a parsable float. + */ def toFloat: Float = java.lang.Float.parseFloat(toString) + /** + * @throws `java.lang.NumberFormatException` - If the string does not contain a parsable double. + */ def toDouble: Double = java.lang.Double.parseDouble(toString) private def parseBoolean(s: String): Boolean = diff --git a/src/partest/scala/tools/partest/BytecodeTest.scala b/src/partest/scala/tools/partest/BytecodeTest.scala index 2699083069..172fa29189 100644 --- a/src/partest/scala/tools/partest/BytecodeTest.scala +++ b/src/partest/scala/tools/partest/BytecodeTest.scala @@ -2,10 +2,9 @@ package scala.tools.partest import scala.tools.nsc.util.JavaClassPath import scala.collection.JavaConverters._ -import scala.tools.asm -import asm.{ ClassReader } -import asm.tree.{ClassNode, MethodNode, InsnList} -import java.io.InputStream +import scala.tools.asm.{ClassWriter, ClassReader} +import scala.tools.asm.tree.{ClassNode, MethodNode, InsnList} +import java.io.{FileOutputStream, FileInputStream, File => JFile, InputStream} import AsmNode._ /** @@ -127,3 +126,31 @@ abstract class BytecodeTest extends ASMConverters { new JavaClassPath(containers, DefaultJavaContext) } } + +object BytecodeTest { + /** Parse `file` as a class file, transforms the ASM representation with `f`, + * and overwrites the orginal file. + */ + def modifyClassFile(file: JFile)(f: ClassNode => ClassNode) { + val rfile = new reflect.io.File(file) + def readClass: ClassNode = { + val cr = new ClassReader(rfile.toByteArray()) + val cn = new ClassNode() + cr.accept(cn, 0) + cn + } + + def writeClass(cn: ClassNode) { + val writer = new ClassWriter(0) + cn.accept(writer) + val os = rfile.bufferedOutput() + try { + os.write(writer.toByteArray) + } finally { + os.close() + } + } + + writeClass(f(readClass)) + } +} diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala index 7f9ca3a321..953b5e5535 100644 --- a/src/partest/scala/tools/partest/DirectTest.scala +++ b/src/partest/scala/tools/partest/DirectTest.scala @@ -6,6 +6,7 @@ package scala.tools.partest import scala.tools.nsc._ +import settings.ScalaVersion import util.{ SourceFile, BatchSourceFile, CommandLineParser } import reporters.{Reporter, ConsoleReporter} @@ -97,4 +98,30 @@ abstract class DirectTest extends App { final def log(msg: => Any) { if (isDebug) Console.err println msg } + + /** + * Run a test only if the current java version is at least the version specified. + */ + def testUnderJavaAtLeast[A](version: String)(yesRun: =>A) = new TestUnderJavaAtLeast(version, { yesRun }) + + class TestUnderJavaAtLeast[A](version: String, yesRun: => A) { + val javaVersion = System.getProperty("java.specification.version") + + // the "ScalaVersion" class parses Java specification versions just fine + val requiredJavaVersion = ScalaVersion(version) + val executingJavaVersion = ScalaVersion(javaVersion) + val shouldRun = executingJavaVersion >= requiredJavaVersion + val preamble = if (shouldRun) "Attempting" else "Doing fallback for" + + def logInfo() = log(s"$preamble java $version specific test under java version $javaVersion") + + /* + * If the current java version is at least 'version' then 'yesRun' is evaluated + * otherwise 'fallback' is + */ + def otherwise(fallback: =>A): A = { + logInfo() + if (shouldRun) yesRun else fallback + } + } } diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala index 368e1cde30..e3498a95a6 100644 --- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala +++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala @@ -66,15 +66,14 @@ trait BaseTypeSeqs { pending += i try { mergePrefixAndArgs(variants, Variance.Contravariant, lubDepth(variants)) match { - case Some(tp0) => + case NoType => typeError("no common type instance of base types "+(variants mkString ", and ")+" exists.") + case tp0 => pending(i) = false elems(i) = tp0 tp0 - case None => - typeError( - "no common type instance of base types "+(variants mkString ", and ")+" exists.") } - } catch { + } + catch { case CyclicInheritance => typeError( "computing the common type instance of base types "+(variants mkString ", and ")+" leads to a cycle.") diff --git a/src/reflect/scala/reflect/internal/CapturedVariables.scala b/src/reflect/scala/reflect/internal/CapturedVariables.scala index 2c5e87b95d..ef9646b80f 100644 --- a/src/reflect/scala/reflect/internal/CapturedVariables.scala +++ b/src/reflect/scala/reflect/internal/CapturedVariables.scala @@ -30,7 +30,7 @@ trait CapturedVariables { self: SymbolTable => def refType(valueRef: Map[Symbol, Symbol], objectRefClass: Symbol) = if (isPrimitiveValueClass(symClass) && symClass != UnitClass) valueRef(symClass).tpe else if (erasedTypes) objectRefClass.tpe - else appliedType(objectRefClass, tpe) + else appliedType(objectRefClass, tpe1) if (vble.hasAnnotation(VolatileAttr)) refType(volatileRefClass, VolatileObjectRefClass) else refType(refClass, ObjectRefClass) } diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 851fc98a32..4f2b7e2642 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -409,10 +409,6 @@ trait Definitions extends api.StandardDefinitions { lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => arrayType(tparam.tpe)) lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => seqType(tparam.tpe)) - def dropByName(tp: Type): Type = tp match { - case TypeRef(_, ByNameParamClass, arg :: Nil) => arg - case _ => tp - } def isByNameParamType(tp: Type) = tp.typeSymbol == ByNameParamClass def isScalaRepeatedParamType(tp: Type) = tp.typeSymbol == RepeatedParamClass def isJavaRepeatedParamType(tp: Type) = tp.typeSymbol == JavaRepeatedParamClass @@ -433,29 +429,15 @@ trait Definitions extends api.StandardDefinitions { case _ => false } - def repeatedToSingle(tp: Type): Type = tp match { - case TypeRef(_, RepeatedParamClass, arg :: Nil) => arg - case _ => tp - } - - def repeatedToSeq(tp: Type): Type = (tp baseType RepeatedParamClass) match { - case TypeRef(_, RepeatedParamClass, arg :: Nil) => seqType(arg) - case _ => tp - } - - def seqToRepeated(tp: Type): Type = (tp baseType SeqClass) match { - case TypeRef(_, SeqClass, arg :: Nil) => scalaRepeatedType(arg) - case _ => tp - } - - def isReferenceArray(tp: Type) = tp match { - case TypeRef(_, ArrayClass, arg :: Nil) => arg <:< AnyRefTpe - case _ => false - } - def isArrayOfSymbol(tp: Type, elem: Symbol) = tp match { - case TypeRef(_, ArrayClass, arg :: Nil) => arg.typeSymbol == elem - case _ => false - } + // wrapping and unwrapping + def dropByName(tp: Type): Type = elementExtract(ByNameParamClass, tp) orElse tp + def repeatedToSingle(tp: Type): Type = elementExtract(RepeatedParamClass, tp) orElse tp + def repeatedToSeq(tp: Type): Type = elementTransform(RepeatedParamClass, tp)(seqType) orElse tp + def seqToRepeated(tp: Type): Type = elementTransform(SeqClass, tp)(scalaRepeatedType) orElse tp + def isReferenceArray(tp: Type) = elementTest(ArrayClass, tp)(_ <:< AnyRefTpe) + def isArrayOfSymbol(tp: Type, elem: Symbol) = elementTest(ArrayClass, tp)(_.typeSymbol == elem) + def elementType(container: Symbol, tp: Type): Type = elementExtract(container, tp) + object ExprClassOf { def unapply(tp: Type): Option[Type] = elementExtractOption(ExprClass, tp) } // collections classes lazy val ConsClass = requiredClass[scala.collection.immutable.::[_]] @@ -514,13 +496,6 @@ trait Definitions extends api.StandardDefinitions { lazy val ExprClass = ExprsClass.map(sym => getMemberClass(sym, tpnme.Expr)) def ExprSplice = ExprClass.map(sym => getMemberMethod(sym, nme.splice)) def ExprValue = ExprClass.map(sym => getMemberMethod(sym, nme.value)) - object ExprClassOf { - def unapply(tpe: Type): Option[Type] = tpe.dealias match { - case ExistentialType(_, underlying) => unapply(underlying) - case TypeRef(_, ExprClass, t :: Nil) => Some(t) - case _ => None - } - } lazy val ClassTagModule = requiredModule[scala.reflect.ClassTag[_]] lazy val ClassTagClass = requiredClass[scala.reflect.ClassTag[_]] @@ -709,11 +684,6 @@ trait Definitions extends api.StandardDefinitions { (sym eq PartialFunctionClass) || (sym eq AbstractPartialFunctionClass) } - def elementType(container: Symbol, tp: Type): Type = tp match { - case TypeRef(_, `container`, arg :: Nil) => arg - case _ => NoType - } - def arrayType(arg: Type) = appliedType(ArrayClass, arg) def byNameType(arg: Type) = appliedType(ByNameParamClass, arg) def iteratorOfType(tp: Type) = appliedType(IteratorClass, tp) diff --git a/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala index 6251849182..073f124630 100644 --- a/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala +++ b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala @@ -77,14 +77,14 @@ trait ExistentialsAndSkolems { * also replaced, except for term symbols of an Ident tree, where * only the type of the Ident is changed. */ - final def existentialTransform[T](rawSyms: List[Symbol], tp: Type, rawOwner: Option[Symbol] = None)(creator: (List[Symbol], Type) => T): T = { + final def existentialTransform[T](rawSyms: List[Symbol], tp: Type, rawOwner: Symbol = NoSymbol)(creator: (List[Symbol], Type) => T): T = { val allBounds = existentialBoundsExcludingHidden(rawSyms) val typeParams: List[Symbol] = rawSyms map { sym => val name = sym.name match { case x: TypeName => x case x => tpnme.singletonName(x) } - def rawOwner0 = rawOwner.getOrElse(abort(s"no owner provided for existential transform over raw parameter: $sym")) + def rawOwner0 = rawOwner orElse abort(s"no owner provided for existential transform over raw parameter: $sym") val bound = allBounds(sym) val sowner = if (isRawParameter(sym)) rawOwner0 else sym.owner val quantified = sowner.newExistential(name, sym.pos) @@ -106,7 +106,7 @@ trait ExistentialsAndSkolems { * @param hidden The original type * @param rawOwner The owner for Java raw types. */ - final def packSymbols(hidden: List[Symbol], tp: Type, rawOwner: Option[Symbol] = None): Type = + final def packSymbols(hidden: List[Symbol], tp: Type, rawOwner: Symbol = NoSymbol): Type = if (hidden.isEmpty) tp else existentialTransform(hidden, tp, rawOwner)(existentialAbstraction) } diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index f3cea1fd00..2da9fa1cca 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -3413,6 +3413,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def mapParamss[T](sym: Symbol)(f: Symbol => T): List[List[T]] = mmap(sym.info.paramss)(f) + def existingSymbols(syms: List[Symbol]): List[Symbol] = + syms filter (s => (s ne null) && (s ne NoSymbol)) + /** Return closest enclosing method, unless shadowed by an enclosing class. */ // TODO Move back to ExplicitOuter when the other call site is removed. // no use of closures here in the interest of speed. diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index 6abf344adb..b75fd72526 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -137,20 +137,20 @@ abstract class TreeGen extends macros.TreeBuilder { /** Replaces tree type with a stable type if possible */ def stabilize(tree: Tree): Tree = stableTypeFor(tree) match { - case Some(tp) => tree setType tp - case _ => tree + case NoType => tree + case tp => tree setType tp } /** Computes stable type for a tree if possible */ - def stableTypeFor(tree: Tree): Option[Type] = - if (treeInfo.admitsTypeSelection(tree)) - tree match { - case This(_) => Some(ThisType(tree.symbol)) - case Ident(_) => Some(singleType(tree.symbol.owner.thisType, tree.symbol)) - case Select(qual, _) => Some(singleType(qual.tpe, tree.symbol)) - case _ => None - } - else None + def stableTypeFor(tree: Tree): Type = ( + if (!treeInfo.admitsTypeSelection(tree)) NoType + else tree match { + case This(_) => ThisType(tree.symbol) + case Ident(_) => singleType(tree.symbol.owner.thisType, tree.symbol) + case Select(qual, _) => singleType(qual.tpe, tree.symbol) + case _ => NoType + } + ) /** Builds a reference with stable type to given symbol */ def mkAttributedStableRef(pre: Type, sym: Symbol): Tree = diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index d1e8a04553..3a8d3fd460 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -837,11 +837,12 @@ abstract class TreeInfo { def unapply(tree: Tree) = refPart(tree) match { case ref: RefTree => { - val isBundle = definitions.isMacroBundleType(ref.qualifier.tpe) + val qual = ref.qualifier + val isBundle = definitions.isMacroBundleType(qual.tpe) val owner = - if (isBundle) ref.qualifier.tpe.typeSymbol + if (isBundle) qual.tpe.typeSymbol else { - val sym = ref.qualifier.symbol + val sym = if (qual.hasSymbolField) qual.symbol else NoSymbol if (sym.isModule) sym.moduleClass else sym } Some((isBundle, owner, ref.symbol, dissectApplied(tree).targs)) diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 5c9665cdc7..967146a130 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -2455,6 +2455,7 @@ trait Types else super.prefixString ) + def copy(pre: Type = this.pre, sym: Symbol = this.sym, args: List[Type] = this.args) = TypeRef(pre, sym, args) override def kind = "TypeRef" } @@ -3718,6 +3719,43 @@ trait Types object unwrapToStableClass extends ClassUnwrapper(existential = false) { } object unwrapWrapperTypes extends TypeUnwrapper(true, true, true, true) { } + def elementExtract(container: Symbol, tp: Type): Type = { + assert(!container.isAliasType, container) + unwrapWrapperTypes(tp baseType container).dealiasWiden match { + case TypeRef(_, `container`, arg :: Nil) => arg + case _ => NoType + } + } + def elementExtractOption(container: Symbol, tp: Type): Option[Type] = { + elementExtract(container, tp) match { + case NoType => None + case tp => Some(tp) + } + } + def elementTest(container: Symbol, tp: Type)(f: Type => Boolean): Boolean = { + elementExtract(container, tp) match { + case NoType => false + case tp => f(tp) + } + } + def elementTransform(container: Symbol, tp: Type)(f: Type => Type): Type = { + elementExtract(container, tp) match { + case NoType => NoType + case tp => f(tp) + } + } + + def transparentShallowTransform(container: Symbol, tp: Type)(f: Type => Type): Type = { + def loop(tp: Type): Type = tp match { + case tp @ AnnotatedType(_, underlying, _) => tp.copy(underlying = loop(underlying)) + case tp @ ExistentialType(_, underlying) => tp.copy(underlying = loop(underlying)) + case tp @ PolyType(_, resultType) => tp.copy(resultType = loop(resultType)) + case tp @ NullaryMethodType(resultType) => tp.copy(resultType = loop(resultType)) + case tp => elementTransform(container, tp)(el => appliedType(container, f(el))).orElse(f(tp)) + } + loop(tp) + } + /** Repack existential types, otherwise they sometimes get unpacked in the * wrong location (type inference comes up with an unexpected skolem) */ @@ -4342,12 +4380,11 @@ trait Types /** Compute lub (if `variance == Covariant`) or glb (if `variance == Contravariant`) of given list * of types `tps`. All types in `tps` are typerefs or singletypes * with the same symbol. - * Return `Some(x)` if the computation succeeds with result `x`. - * Return `None` if the computation fails. + * Return `x` if the computation succeeds with result `x`. + * Return `NoType` if the computation fails. */ - def mergePrefixAndArgs(tps: List[Type], variance: Variance, depth: Int): Option[Type] = tps match { - case List(tp) => - Some(tp) + def mergePrefixAndArgs(tps: List[Type], variance: Variance, depth: Int): Type = tps match { + case tp :: Nil => tp case TypeRef(_, sym, _) :: rest => val pres = tps map (_.prefix) // prefix normalizes automatically val pre = if (variance.isPositive) lub(pres, depth) else glb(pres, depth) @@ -4359,12 +4396,13 @@ trait Types // if argss contain one value type and some other type, the lub is Object // if argss contain several reference types, the lub is an array over lub of argtypes if (argss exists typeListIsEmpty) { - None // something is wrong: an array without a type arg. - } else { + NoType // something is wrong: an array without a type arg. + } + else { val args = argss map (_.head) - if (args.tail forall (_ =:= args.head)) Some(typeRef(pre, sym, List(args.head))) - else if (args exists (arg => isPrimitiveValueClass(arg.typeSymbol))) Some(ObjectTpe) - else Some(typeRef(pre, sym, List(lub(args)))) + if (args.tail forall (_ =:= args.head)) typeRef(pre, sym, List(args.head)) + else if (args exists (arg => isPrimitiveValueClass(arg.typeSymbol))) ObjectTpe + else typeRef(pre, sym, List(lub(args))) } } else transposeSafe(argss) match { @@ -4373,7 +4411,7 @@ trait Types // catching just in case (shouldn't happen, but also doesn't cost us) // [JZ] It happens: see SI-5683. debuglog(s"transposed irregular matrix!? tps=$tps argss=$argss") - None + NoType case Some(argsst) => val args = map2(sym.typeParams, argsst) { (tparam, as0) => val as = as0.distinct @@ -4404,22 +4442,22 @@ trait Types } } } - if (args contains NoType) None - else Some(existentialAbstraction(capturedParams.toList, typeRef(pre, sym, args))) + if (args contains NoType) NoType + else existentialAbstraction(capturedParams.toList, typeRef(pre, sym, args)) } } catch { - case ex: MalformedType => None + case ex: MalformedType => NoType } case SingleType(_, sym) :: rest => val pres = tps map (_.prefix) val pre = if (variance.isPositive) lub(pres, depth) else glb(pres, depth) - try { - Some(singleType(pre, sym)) - } catch { - case ex: MalformedType => None - } + try singleType(pre, sym) + catch { case ex: MalformedType => NoType } case ExistentialType(tparams, quantified) :: rest => - mergePrefixAndArgs(quantified :: rest, variance, depth) map (existentialAbstraction(tparams, _)) + mergePrefixAndArgs(quantified :: rest, variance, depth) match { + case NoType => NoType + case tpe => existentialAbstraction(tparams, tpe) + } case _ => abort(s"mergePrefixAndArgs($tps, $variance, $depth): unsupported tps") } diff --git a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala index 0a7a2a127c..1d3c6b0f23 100644 --- a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala +++ b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala @@ -125,8 +125,8 @@ private[internal] trait GlbLubs { } val tails = tsBts map (_.tail) mergePrefixAndArgs(elimSub(ts1, depth) map elimHigherOrderTypeParam, Covariant, depth) match { - case Some(tp) => loop(tp :: pretypes, tails) - case _ => loop(pretypes, tails) + case NoType => loop(pretypes, tails) + case tp => loop(tp :: pretypes, tails) } } else { diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index a3684f602f..16405a88b4 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -581,15 +581,10 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni loadBytes[Array[String]]("scala.reflect.ScalaLongSignature") match { case Some(slsig) => info(s"unpickling Scala $clazz and $module with long Scala signature") - val byteSegments = slsig map (_.getBytes) - val lens = byteSegments map ByteCodecs.decode - val bytes = Array.ofDim[Byte](lens.sum) - var len = 0 - for ((bs, l) <- byteSegments zip lens) { - bs.copyToArray(bytes, len, l) - len += l - } - unpickler.unpickle(bytes, 0, clazz, module, jclazz.getName) + val encoded = slsig flatMap (_.getBytes) + val len = ByteCodecs.decode(encoded) + val decoded = encoded.take(len) + unpickler.unpickle(decoded, 0, clazz, module, jclazz.getName) case None => // class does not have a Scala signature; it's a Java class info("translating reflection info for Java " + jclazz) //debug diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index 9f841f2c44..8ec8b2ed5f 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -642,10 +642,6 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } private def loopPostInit() { - in match { - case x: JLineReader => x.consoleReader.postInit - case _ => - } // Bind intp somewhere out of the regular namespace where // we can get at it in generated code. intp.quietBind(NamedParam[IMain]("$intp", intp)(tagOfIMain, classTag[IMain])) @@ -661,6 +657,11 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) unleashAndSetPhase() asyncMessage(power.banner) } + // SI-7418 Now, and only now, can we enable TAB completion. + in match { + case x: JLineReader => x.consoleReader.postInit + case _ => + } } def process(settings: Settings): Boolean = savingContextLoader { this.settings = settings diff --git a/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala b/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala index 159e16375c..f6373e9e97 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala @@ -42,8 +42,7 @@ abstract class HtmlPage extends Page { thisPage => def body: NodeSeq def writeFor(site: HtmlFactory) { - val doctype = - DocType("html", PublicID("-//W3C//DTD XHTML 1.1//EN", "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"), Nil) + val doctype = DocType("html") val html = <html> <head> @@ -57,7 +56,6 @@ abstract class HtmlPage extends Page { thisPage => </html> writeFile(site) { (w: Writer) => - w.write("<?xml version='1.0' encoding='" + site.encoding + "'?>\n") w.write(doctype.toString + "\n") w.write(xml.Xhtml.toXhtml(html)) } @@ -67,8 +65,6 @@ abstract class HtmlPage extends Page { thisPage => // we're only interested in the body, as this will go into the diff _.write(body.text) } - - //XML.save(pageFile.getPath, html, site.encoding, xmlDecl = false, doctype = doctype) } /** Transforms an optional comment into an styled HTML tree representing its body if it is defined, or into an empty diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala index c034647320..ce3a5eb1fc 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala @@ -35,10 +35,10 @@ class Index(universe: doc.Universe, val index: doc.Index) extends HtmlPage { val body = <body> <div id="library"> - <img class='class icon' src={ relativeLinkTo{List("class.png", "lib")} }/> - <img class='trait icon' src={ relativeLinkTo{List("trait.png", "lib")} }/> - <img class='object icon' src={ relativeLinkTo{List("object.png", "lib")} }/> - <img class='package icon' src={ relativeLinkTo{List("package.png", "lib")} }/> + <img class='class icon' alt='class icon' src={ relativeLinkTo{List("class.png", "lib")} }/> + <img class='trait icon' alt='trait icon' src={ relativeLinkTo{List("trait.png", "lib")} }/> + <img class='object icon' alt='trait icon' src={ relativeLinkTo{List("object.png", "lib")} }/> + <img class='package icon' alt='trait icon' src={ relativeLinkTo{List("package.png", "lib")} }/> </div> { browser } <div id="content" class="ui-layout-center"> |