diff options
43 files changed, 480 insertions, 221 deletions
diff --git a/src/compiler/scala/tools/cmd/CommandLine.scala b/src/compiler/scala/tools/cmd/CommandLine.scala index e8ac882ee6..e44752eb6e 100644 --- a/src/compiler/scala/tools/cmd/CommandLine.scala +++ b/src/compiler/scala/tools/cmd/CommandLine.scala @@ -16,7 +16,7 @@ trait CommandLineConfig { /** An instance of a command line, parsed according to a Spec. */ class CommandLine(val spec: Reference, val originalArgs: List[String]) extends CommandLineConfig { - def this(spec: Reference, line: String) = this(spec, Parser tokenize line) + def this(spec: Reference, line: String) = this(spec, CommandLineParser tokenize line) def this(spec: Reference, args: Array[String]) = this(spec, args.toList) import spec.{ isUnaryOption, isBinaryOption, isExpandOption } diff --git a/src/compiler/scala/tools/cmd/CommandLineParser.scala b/src/compiler/scala/tools/cmd/CommandLineParser.scala new file mode 100644 index 0000000000..ef55178594 --- /dev/null +++ b/src/compiler/scala/tools/cmd/CommandLineParser.scala @@ -0,0 +1,72 @@ +/* NEST (New Scala Test) + * Copyright 2007-2013 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools +package cmd + +import scala.annotation.tailrec + +/** A simple (overly so) command line parser. + * !!! This needs a thorough test suite to make sure quoting is + * done correctly and portably. + */ +object CommandLineParser { + // splits a string into a quoted prefix and the rest of the string, + // taking escaping into account (using \) + // `"abc"def` will match as `DoubleQuoted(abc, def)` + private class QuotedExtractor(quote: Char) { + def unapply(in: String): Option[(String, String)] = { + val del = quote.toString + if (in startsWith del) { + var escaped = false + val (quoted, next) = (in substring 1) span { + case `quote` if !escaped => false + case '\\' if !escaped => escaped = true; true + case _ => escaped = false; true + } + // the only way to get out of the above loop is with an empty next or !escaped + // require(next.isEmpty || !escaped) + if (next startsWith del) Some((quoted, next substring 1)) + else None + } else None + } + } + private object DoubleQuoted extends QuotedExtractor('"') + private object SingleQuoted extends QuotedExtractor('\'') + private val Word = """(\S+)(.*)""".r + + // parse `in` for an argument, return it and the remainder of the input (or an error message) + // (argument may be in single/double quotes, taking escaping into account, quotes are stripped) + private def argument(in: String): Either[String, (String, String)] = in match { + case DoubleQuoted(arg, rest) => Right(arg, rest) + case SingleQuoted(arg, rest) => Right(arg, rest) + case Word(arg, rest) => Right(arg, rest) + case _ => Left("Illegal argument: "+ in) + } + + // parse a list of whitespace-separated arguments (ignoring whitespace in quoted arguments) + @tailrec private def commandLine(in: String, accum: List[String] = Nil): Either[String, (List[String], String)] = { + val trimmed = in.trim + if (trimmed.isEmpty) Right(accum.reverse, "") + else argument(trimmed) match { + case Right((arg, next)) => + (next span Character.isWhitespace) match { + case("", rest) if rest.nonEmpty => Left("Arguments should be separated by whitespace.") // TODO: can this happen? + case(ws, rest) => commandLine(rest, arg :: accum) + } + case Left(msg) => Left(msg) + } + } + + class ParseException(msg: String) extends RuntimeException(msg) + + def tokenize(line: String): List[String] = tokenize(line, x => throw new ParseException(x)) + def tokenize(line: String, errorFn: String => Unit): List[String] = { + commandLine(line) match { + case Right((args, _)) => args + case Left(msg) => errorFn(msg) ; Nil + } + } +} diff --git a/src/compiler/scala/tools/cmd/Parser.scala b/src/compiler/scala/tools/cmd/Parser.scala deleted file mode 100644 index 6e2afa41c4..0000000000 --- a/src/compiler/scala/tools/cmd/Parser.scala +++ /dev/null @@ -1,52 +0,0 @@ -/* NEST (New Scala Test) - * Copyright 2007-2013 LAMP/EPFL - * @author Paul Phillips - */ - -package scala.tools -package cmd - -import scala.util.parsing.combinator._ -import scala.util.parsing.input.CharArrayReader.EofCh - -/** A simple (overly so) command line parser. - * !!! This needs a thorough test suite to make sure quoting is - * done correctly and portably. - */ -trait ParserUtil extends Parsers { - class ParserPlus[+T](underlying: Parser[T]) { - def !~>[U](p: => Parser[U]): Parser[U] = (underlying ~! p) ^^ { case a~b => b } - def <~![U](p: => Parser[U]): Parser[T] = (underlying ~! p) ^^ { case a~b => a } - } - protected implicit def parser2parserPlus[T](p: Parser[T]): ParserPlus[T] = new ParserPlus(p) -} - -object Parser extends RegexParsers with ParserUtil { - override def skipWhitespace = false - - def elemExcept(xs: Elem*): Parser[Elem] = elem("elemExcept", x => x != EofCh && !(xs contains x)) - def elemOf(xs: Elem*): Parser[Elem] = elem("elemOf", xs contains _) - def escaped(ch: Char): Parser[String] = "\\" + ch - def mkQuoted(ch: Char): Parser[String] = ( - elem(ch) !~> rep(escaped(ch) | elemExcept(ch)) <~ ch ^^ (_.mkString) - | failure("Unmatched %s in input." format ch) - ) - - /** Apparently windows can't deal with the quotes sticking around. */ - lazy val squoted: Parser[String] = mkQuoted('\'') // ^^ (x => "'%s'" format x) - lazy val dquoted: Parser[String] = mkQuoted('"') // ^^ (x => "\"" + x + "\"") - lazy val token: Parser[String] = """\S+""".r - - lazy val argument: Parser[String] = squoted | dquoted | token - lazy val commandLine: Parser[List[String]] = phrase(repsep(argument, whiteSpace)) - - class ParseException(msg: String) extends RuntimeException(msg) - - def tokenize(line: String): List[String] = tokenize(line, x => throw new ParseException(x)) - def tokenize(line: String, errorFn: String => Unit): List[String] = { - parse(commandLine, line.trim) match { - case Success(args, _) => args - case NoSuccess(msg, rest) => errorFn(msg) ; Nil - } - } -} diff --git a/src/compiler/scala/tools/cmd/package.scala b/src/compiler/scala/tools/cmd/package.scala index c62a977950..7d67fa738b 100644 --- a/src/compiler/scala/tools/cmd/package.scala +++ b/src/compiler/scala/tools/cmd/package.scala @@ -22,7 +22,7 @@ package object cmd { def toOpt(s: String) = if (s startsWith "--") s else "--" + s def fromOpt(s: String) = s stripPrefix "--" - def toArgs(line: String) = Parser tokenize line + def toArgs(line: String) = CommandLineParser tokenize line def fromArgs(args: List[String]) = args mkString " " def stripQuotes(s: String) = { diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index cd23ad74e4..b5cc89c0c8 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -107,7 +107,7 @@ class MutableSettings(val errorFn: String => Unit) /** Split the given line into parameters. */ - def splitParams(line: String) = cmd.Parser.tokenize(line, errorFn) + def splitParams(line: String) = cmd.CommandLineParser.tokenize(line, errorFn) /** Returns any unprocessed arguments. */ diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index f43e42c027..d14fcb3eb1 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -852,7 +852,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { debuglog("%s expands to %s in %s".format(sym, specMember.name.decode, pp(env))) info(specMember) = NormalizedMember(sym) newOverload(sym, specMember, env) - owner.info.decls.enter(specMember) + // if this is a class, we insert the normalized member in scope, + // if this is a method, there's no attached scope for it (EmptyScope) + val decls = owner.info.decls + if (decls != EmptyScope) + decls.enter(specMember) specMember } } @@ -1445,6 +1449,32 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } } + /** Computes residual type parameters after rewiring, like "String" in the following example: + * ``` + * def specMe[@specialized T, U](t: T, u: U) = ??? + * specMe[Int, String](1, "2") => specMe$mIc$sp[String](1, "2") + * ``` + */ + def computeResidualTypeVars(baseTree: Tree, specMember: Symbol, specTree: Tree, baseTargs: List[Tree], env: TypeEnv): Tree = { + val residualTargs = symbol.info.typeParams zip baseTargs collect { + case (tvar, targ) if !env.contains(tvar) || !isPrimitiveValueClass(env(tvar).typeSymbol) => targ + } + // See SI-5583. Don't know why it happens now if it didn't before. + if (specMember.info.typeParams.isEmpty && residualTargs.nonEmpty) { + devWarning("Type args to be applied, but symbol says no parameters: " + ((specMember.defString, residualTargs))) + baseTree + } + else { + ifDebug(assert(residualTargs.length == specMember.info.typeParams.length, + "residual: %s, tparams: %s, env: %s".format(residualTargs, specMember.info.typeParams, env)) + ) + + val tree1 = gen.mkTypeApply(specTree, residualTargs) + debuglog("rewrote " + tree + " to " + tree1) + localTyper.typedOperator(atPos(tree.pos)(tree1)) // being polymorphic, it must be a method + } + } + curTree = tree tree match { case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => @@ -1470,12 +1500,16 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } transformSuperApply + // This rewires calls to specialized methods defined in a class (which have a receiver) + // class C { + // def foo[@specialized T](t: T): T = t + // C.this.foo(3) // TypeApply(Select(This(C), foo), List(Int)) => C.this.foo$mIc$sp(3) + // } case TypeApply(sel @ Select(qual, name), targs) - if (!specializedTypeVars(symbol.info).isEmpty && name != nme.CONSTRUCTOR) => - def transformTypeApply = { + if (specializedTypeVars(symbol.info).nonEmpty && name != nme.CONSTRUCTOR) => debuglog("checking typeapp for rerouting: " + tree + " with sym.tpe: " + symbol.tpe + " tree.tpe: " + tree.tpe) val qual1 = transform(qual) - // log(">>> TypeApply: " + tree + ", qual1: " + qual1) + log(">>> TypeApply: " + tree + ", qual1: " + qual1) specSym(qual1) match { case NoSymbol => // See pos/exponential-spec.scala - can't call transform on the whole tree again. @@ -1485,26 +1519,23 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { ifDebug(assert(symbol.info.typeParams.length == targs.length, symbol.info.typeParams + " / " + targs)) val env = typeEnv(specMember) - val residualTargs = symbol.info.typeParams zip targs collect { - case (tvar, targ) if !env.contains(tvar) || !isPrimitiveValueClass(env(tvar).typeSymbol) => targ - } - // See SI-5583. Don't know why it happens now if it didn't before. - if (specMember.info.typeParams.isEmpty && residualTargs.nonEmpty) { - devWarning("Type args to be applied, but symbol says no parameters: " + ((specMember.defString, residualTargs))) - localTyper.typed(sel) - } - else { - ifDebug(assert(residualTargs.length == specMember.info.typeParams.length, - "residual: %s, tparams: %s, env: %s".format(residualTargs, specMember.info.typeParams, env)) - ) - - val tree1 = gen.mkTypeApply(Select(qual1, specMember), residualTargs) - debuglog("rewrote " + tree + " to " + tree1) - localTyper.typedOperator(atPos(tree.pos)(tree1)) // being polymorphic, it must be a method - } + computeResidualTypeVars(tree, specMember, gen.mkAttributedSelect(qual1, specMember), targs, env) } + + // This rewires calls to specialized methods defined in the local scope. For example: + // def outerMethod = { + // def foo[@specialized T](t: T): T = t + // foo(3) // TypeApply(Ident(foo), List(Int)) => foo$mIc$sp(3) + // } + case TypeApply(sel @ Ident(name), targs) if name != nme.CONSTRUCTOR => + val env = unify(symbol.tpe, tree.tpe, emptyEnv, false) + if (env.isEmpty) super.transform(tree) + else { + overloads(symbol) find (_ matchesEnv env) match { + case Some(Overload(specMember, _)) => computeResidualTypeVars(tree, specMember, Ident(specMember), targs, env) + case _ => super.transform(tree) + } } - transformTypeApply case Select(Super(_, _), _) if illegalSpecializedInheritance(currentClass) => val pos = tree.pos @@ -1621,7 +1652,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { localTyper.typed(deriveDefDef(tree)(rhs => rhs)) } } - transformDefDef + expandInnerNormalizedMembers(transformDefDef) + + case ddef @ DefDef(_, _, _, _, _, _) => + val tree1 = expandInnerNormalizedMembers(tree) + super.transform(tree1) case ValDef(_, _, _, _) if symbol.hasFlag(SPECIALIZED) && !symbol.isParamAccessor => def transformValDef = { @@ -1645,6 +1680,39 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } } + /** + * This performs method specialization inside a scope other than a {class, trait, object}: could be another method + * or a value. This specialization is much simpler, since there is no need to record the new members in the class + * signature, their signatures are only visible locally. It works according to the usual logic: + * - we use normalizeMember to create the specialized symbols + * - we leave DefDef stubs in the tree that are later filled in by tree duplication and adaptation + * @see duplicateBody + */ + private def expandInnerNormalizedMembers(tree: Tree) = tree match { + case ddef @ DefDef(_, _, _, vparams :: Nil, _, rhs) + if ddef.symbol.owner.isMethod && + specializedTypeVars(ddef.symbol.info).nonEmpty && + !ddef.symbol.hasFlag(SPECIALIZED) => + + val sym = ddef.symbol + val owner = sym.owner + val norm = normalizeMember(owner, sym, emptyEnv) + + if (norm.length > 1) { + // record the body for duplication + body(sym) = rhs + parameters(sym) = vparams.map(_.symbol) + // to avoid revisiting the member, we can set the SPECIALIZED + // flag. nobody has to see this anyway :) + sym.setFlag(SPECIALIZED) + // create empty bodies for specializations + localTyper.typed(Block(norm.tail.map(sym => DefDef(sym, { vparamss => EmptyTree })), ddef)) + } else + tree + case _ => + tree + } + /** Duplicate the body of the given method `tree` to the new symbol `source`. * * Knowing that the method can be invoked only in the `castmap` type environment, diff --git a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala b/src/compiler/scala/tools/nsc/util/CommandLine.scala index e8f962a9e2..ef28f6dc53 100644 --- a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala +++ b/src/compiler/scala/tools/nsc/util/CommandLine.scala @@ -3,27 +3,16 @@ * @author Paul Phillips */ -package scala.tools.nsc -package util +package scala.tools +package nsc.util -import scala.util.parsing.combinator._ -import scala.util.parsing.input.CharArrayReader.EofCh import scala.collection.mutable.ListBuffer -/** A simple command line parser to replace the several different - * simple ones spread around trunk. - * +/** * XXX Note this has been completely obsolesced by scala.tools.cmd. * I checked it back in as part of rolling partest back a month * rather than go down the rabbit hole of unravelling dependencies. */ - -trait ParserUtil extends Parsers { - protected implicit class ParserPlus[+T](underlying: Parser[T]) { - def !~>[U](p: => Parser[U]): Parser[U] = (underlying ~! p) ^^ { case a~b => b } - } -} - case class CommandLine( args: List[String], unaryArguments: List[String], @@ -31,7 +20,7 @@ case class CommandLine( ) { def this(args: List[String]) = this(args, Nil, Nil) def this(args: Array[String]) = this(args.toList, Nil, Nil) - def this(line: String) = this(CommandLineParser tokenize line, Nil, Nil) + def this(line: String) = this(cmd.CommandLineParser tokenize line, Nil, Nil) def withUnaryArgs(xs: List[String]) = copy(unaryArguments = xs) def withBinaryArgs(xs: List[String]) = copy(binaryArguments = xs) @@ -107,33 +96,3 @@ case class CommandLine( override def toString() = "CommandLine(\n%s)\n" format (args map (" " + _ + "\n") mkString) } - -object CommandLineParser extends RegexParsers with ParserUtil { - override def skipWhitespace = false - - def elemExcept(xs: Elem*): Parser[Elem] = elem("elemExcept", x => x != EofCh && !(xs contains x)) - def escaped(ch: Char): Parser[String] = "\\" + ch - def mkQuoted(ch: Char): Parser[String] = ( - elem(ch) !~> rep(escaped(ch) | elemExcept(ch)) <~ ch ^^ (_.mkString) - | failure("Unmatched %s in input." format ch) - ) - - /** Apparently windows can't deal with the quotes sticking around. */ - lazy val squoted: Parser[String] = mkQuoted('\'') // ^^ (x => "'%s'" format x) - lazy val dquoted: Parser[String] = mkQuoted('"') // ^^ (x => "\"" + x + "\"") - lazy val token: Parser[String] = """\S+""".r - - lazy val argument: Parser[String] = squoted | dquoted | token - lazy val commandLine: Parser[List[String]] = phrase(repsep(argument, whiteSpace)) - - class ParseException(msg: String) extends RuntimeException(msg) - - def tokenize(line: String): List[String] = tokenize(line, x => throw new ParseException(x)) - def tokenize(line: String, errorFn: String => Unit): List[String] = { - parse(commandLine, line.trim) match { - case Success(args, _) => args - case NoSuccess(msg, rest) => errorFn(msg) ; Nil - } - } - def apply(line: String) = new CommandLine(tokenize(line)) -} diff --git a/src/library/scala/collection/GenTraversableLike.scala b/src/library/scala/collection/GenTraversableLike.scala index f4aa063d8a..a0c519884c 100644 --- a/src/library/scala/collection/GenTraversableLike.scala +++ b/src/library/scala/collection/GenTraversableLike.scala @@ -324,7 +324,7 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with * @tparam K the type of keys returned by the discriminator function. * @return A map from keys to ${coll}s such that the following invariant holds: * {{{ - * (xs partition f)(k) = xs filter (x => f(x) == k) + * (xs groupBy f)(k) = xs filter (x => f(x) == k) * }}} * That is, every key `k` is bound to a $coll of those elements `x` * for which `f(x)` equals `k`. diff --git a/src/library/scala/math/ScalaNumericConversions.scala b/src/library/scala/math/ScalaNumericConversions.scala index 336991781e..0006133b13 100644 --- a/src/library/scala/math/ScalaNumericConversions.scala +++ b/src/library/scala/math/ScalaNumericConversions.scala @@ -20,6 +20,7 @@ trait ScalaNumericConversions extends ScalaNumber with ScalaNumericAnyConversion * across all the numeric types, suitable for use in value classes. */ trait ScalaNumericAnyConversions extends Any { + /** @return `'''true'''` if this number has no decimal component, `'''false'''` otherwise. */ def isWhole(): Boolean def underlying(): Any diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java index 3504c57b48..82a3b00ac4 100644 --- a/src/library/scala/runtime/BoxesRunTime.java +++ b/src/library/scala/runtime/BoxesRunTime.java @@ -10,7 +10,6 @@ package scala.runtime; -import java.io.*; import scala.math.ScalaNumber; /** An object (static class) that defines methods used for creating, diff --git a/src/library/scala/runtime/ObjectRef.java b/src/library/scala/runtime/ObjectRef.java index c553c780a8..b34f81c9c8 100644 --- a/src/library/scala/runtime/ObjectRef.java +++ b/src/library/scala/runtime/ObjectRef.java @@ -16,8 +16,9 @@ public class ObjectRef<T> implements java.io.Serializable { public T elem; public ObjectRef(T elem) { this.elem = elem; } + @Override public String toString() { return String.valueOf(elem); } - public static <U> ObjectRef create(U e) { return new ObjectRef(e); } - public static ObjectRef zero() { return new ObjectRef(null); } + public static <U> ObjectRef<U> create(U e) { return new ObjectRef<U>(e); } + public static ObjectRef<Object> zero() { return new ObjectRef<Object>(null); } } diff --git a/src/library/scala/runtime/RichByte.scala b/src/library/scala/runtime/RichByte.scala index ea23cb8867..ce658d2277 100644 --- a/src/library/scala/runtime/RichByte.scala +++ b/src/library/scala/runtime/RichByte.scala @@ -13,4 +13,18 @@ package runtime final class RichByte(val self: Byte) extends AnyVal with ScalaWholeNumberProxy[Byte] { protected def num = scala.math.Numeric.ByteIsIntegral protected def ord = scala.math.Ordering.Byte + + override def doubleValue() = self.toDouble + override def floatValue() = self.toFloat + override def longValue() = self.toLong + override def intValue() = self.toInt + override def byteValue() = self + override def shortValue() = self.toShort + + override def isValidByte = true + + override def abs: Byte = math.abs(self).toByte + override def max(that: Byte): Byte = math.max(self, that).toByte + override def min(that: Byte): Byte = math.min(self, that).toByte + override def signum: Int = math.signum(self.toInt) } diff --git a/src/library/scala/runtime/RichChar.scala b/src/library/scala/runtime/RichChar.scala index c069fd1fef..71ea3a21e1 100644 --- a/src/library/scala/runtime/RichChar.scala +++ b/src/library/scala/runtime/RichChar.scala @@ -16,6 +16,20 @@ final class RichChar(val self: Char) extends AnyVal with IntegralProxy[Char] { protected def num = scala.math.Numeric.CharIsIntegral protected def ord = scala.math.Ordering.Char + override def doubleValue() = self.toDouble + override def floatValue() = self.toFloat + override def longValue() = self.toLong + override def intValue() = self.toInt + override def byteValue() = self.toByte + override def shortValue() = self.toShort + + override def isValidChar = true + + override def abs: Char = self + override def max(that: Char): Char = math.max(self.toInt, that.toInt).toChar + override def min(that: Char): Char = math.min(self.toInt, that.toInt).toChar + override def signum: Int = math.signum(self.toInt) + def asDigit: Int = Character.digit(self, Character.MAX_RADIX) def isControl: Boolean = Character.isISOControl(self) diff --git a/src/library/scala/runtime/RichDouble.scala b/src/library/scala/runtime/RichDouble.scala index 2f16a296b3..9d7a55d5cd 100644 --- a/src/library/scala/runtime/RichDouble.scala +++ b/src/library/scala/runtime/RichDouble.scala @@ -14,6 +14,35 @@ final class RichDouble(val self: Double) extends AnyVal with FractionalProxy[Dou protected def ord = scala.math.Ordering.Double protected def integralNum = scala.math.Numeric.DoubleAsIfIntegral + override def doubleValue() = self + override def floatValue() = self.toFloat + override def longValue() = self.toLong + override def intValue() = self.toInt + override def byteValue() = self.toByte + override def shortValue() = self.toShort + + override def isWhole = { + val l = self.toLong + l.toDouble == self || l == Long.MaxValue && self < Double.PositiveInfinity || l == Long.MinValue && self > Double.NegativeInfinity + } + override def isValidByte = self.toByte.toDouble == self + override def isValidShort = self.toShort.toDouble == self + override def isValidChar = self.toChar.toDouble == self + override def isValidInt = self.toInt.toDouble == self + // override def isValidLong = { val l = self.toLong; l.toDouble == self && l != Long.MaxValue } + // override def isValidFloat = self.toFloat.toDouble == self + // override def isValidDouble = !java.lang.Double.isNaN(self) + + def isNaN: Boolean = java.lang.Double.isNaN(self) + def isInfinity: Boolean = java.lang.Double.isInfinite(self) + def isPosInfinity: Boolean = Double.PositiveInfinity == self + def isNegInfinity: Boolean = Double.NegativeInfinity == self + + override def abs: Double = math.abs(self) + override def max(that: Double): Double = math.max(self, that) + override def min(that: Double): Double = math.min(self, that) + override def signum: Int = math.signum(self).toInt // !!! NaN + def round: Long = math.round(self) def ceil: Double = math.ceil(self) def floor: Double = math.floor(self) @@ -30,22 +59,4 @@ final class RichDouble(val self: Double) extends AnyVal with FractionalProxy[Dou * @return the measurement of the angle x in degrees. */ def toDegrees: Double = math.toDegrees(self) - - // isNaN is provided by the implicit conversion to java.lang.Double - // def isNaN: Boolean = java.lang.Double.isNaN(self) - def isInfinity: Boolean = java.lang.Double.isInfinite(self) - def isPosInfinity: Boolean = isInfinity && self > 0.0 - def isNegInfinity: Boolean = isInfinity && self < 0.0 - - override def isValidByte = self.toByte.toDouble == self - override def isValidShort = self.toShort.toDouble == self - override def isValidChar = self.toChar.toDouble == self - override def isValidInt = self.toInt.toDouble == self - // override def isValidLong = { val l = self.toLong; l.toDouble == self && l != Long.MaxValue } - // override def isValidFloat = self.toFloat.toDouble == self - // override def isValidDouble = !java.lang.Double.isNaN(self) - override def isWhole = { - val l = self.toLong - l.toDouble == self || l == Long.MaxValue && self < Double.PositiveInfinity || l == Long.MinValue && self > Double.NegativeInfinity - } } diff --git a/src/library/scala/runtime/RichFloat.scala b/src/library/scala/runtime/RichFloat.scala index 0bca033b7b..93777f2405 100644 --- a/src/library/scala/runtime/RichFloat.scala +++ b/src/library/scala/runtime/RichFloat.scala @@ -14,6 +14,35 @@ final class RichFloat(val self: Float) extends AnyVal with FractionalProxy[Float protected def ord = scala.math.Ordering.Float protected def integralNum = scala.math.Numeric.FloatAsIfIntegral + override def doubleValue() = self.toDouble + override def floatValue() = self + override def longValue() = self.toLong + override def intValue() = self.toInt + override def byteValue() = self.toByte + override def shortValue() = self.toShort + + override def isWhole = { + val l = self.toLong + l.toFloat == self || l == Long.MaxValue && self < Float.PositiveInfinity || l == Long.MinValue && self > Float.NegativeInfinity + } + override def isValidByte = self.toByte.toFloat == self + override def isValidShort = self.toShort.toFloat == self + override def isValidChar = self.toChar.toFloat == self + override def isValidInt = { val i = self.toInt; i.toFloat == self && i != Int.MaxValue } + // override def isValidLong = { val l = self.toLong; l.toFloat == self && l != Long.MaxValue } + // override def isValidFloat = !java.lang.Float.isNaN(self) + // override def isValidDouble = !java.lang.Float.isNaN(self) + + def isNaN: Boolean = java.lang.Float.isNaN(self) + def isInfinity: Boolean = java.lang.Float.isInfinite(self) + def isPosInfinity: Boolean = Float.PositiveInfinity == self + def isNegInfinity: Boolean = Float.NegativeInfinity == self + + override def abs: Float = math.abs(self) + override def max(that: Float): Float = math.max(self, that) + override def min(that: Float): Float = math.min(self, that) + override def signum: Int = math.signum(self).toInt // !!! NaN + def round: Int = math.round(self) def ceil: Float = math.ceil(self.toDouble).toFloat def floor: Float = math.floor(self.toDouble).toFloat @@ -31,22 +60,4 @@ final class RichFloat(val self: Float) extends AnyVal with FractionalProxy[Float * @return the measurement of the angle `x` in degrees. */ def toDegrees: Float = math.toDegrees(self.toDouble).toFloat - - // isNaN is provided by the implicit conversion to java.lang.Float - // def isNaN: Boolean = java.lang.Float.isNaN(self) - def isInfinity: Boolean = java.lang.Float.isInfinite(self) - def isPosInfinity: Boolean = isInfinity && self > 0.0f - def isNegInfinity: Boolean = isInfinity && self < 0.0f - - override def isValidByte = self.toByte.toFloat == self - override def isValidShort = self.toShort.toFloat == self - override def isValidChar = self.toChar.toFloat == self - override def isValidInt = { val i = self.toInt; i.toFloat == self && i != Int.MaxValue } - // override def isValidLong = { val l = self.toLong; l.toFloat == self && l != Long.MaxValue } - // override def isValidFloat = !java.lang.Float.isNaN(self) - // override def isValidDouble = !java.lang.Float.isNaN(self) - override def isWhole = { - val l = self.toLong - l.toFloat == self || l == Long.MaxValue && self < Float.PositiveInfinity || l == Long.MinValue && self > Float.NegativeInfinity - } } diff --git a/src/library/scala/runtime/RichInt.scala b/src/library/scala/runtime/RichInt.scala index a39710b146..cc4e92dfa3 100644 --- a/src/library/scala/runtime/RichInt.scala +++ b/src/library/scala/runtime/RichInt.scala @@ -9,7 +9,6 @@ package scala package runtime - import scala.collection.immutable.Range // Note that this does not implement IntegralProxy[Int] so that it can return @@ -17,14 +16,33 @@ import scala.collection.immutable.Range final class RichInt(val self: Int) extends AnyVal with ScalaNumberProxy[Int] with RangedProxy[Int] { protected def num = scala.math.Numeric.IntIsIntegral protected def ord = scala.math.Ordering.Int - type ResultWithoutStep = Range - /** - * @return `'''true'''` if this number has no decimal component. - * Always returns `'''true'''` for `RichInt`. + override def doubleValue() = self.toDouble + override def floatValue() = self.toFloat + override def longValue() = self.toLong + override def intValue() = self + override def byteValue() = self.toByte + override def shortValue() = self.toShort + + /** Returns `'''true'''` if this number has no decimal component. + * Always `'''true'''` for `RichInt`. */ def isWhole() = true + override def isValidInt = true + def isValidLong = true + + override def abs: Int = math.abs(self) + override def max(that: Int): Int = math.max(self, that) + override def min(that: Int): Int = math.min(self, that) + override def signum: Int = math.signum(self) + + def toBinaryString: String = java.lang.Integer.toBinaryString(self) + def toHexString: String = java.lang.Integer.toHexString(self) + def toOctalString: String = java.lang.Integer.toOctalString(self) + + type ResultWithoutStep = Range + /** * @param end The final bound of the range to make. * @return A [[scala.collection.immutable.Range]] from `this` up to but @@ -55,23 +73,4 @@ final class RichInt(val self: Int) extends AnyVal with ScalaNumberProxy[Int] wit * and including `end`. */ def to(end: Int, step: Int): Range.Inclusive = Range.inclusive(self, end, step) - - /** - * @return `'''this'''` if `'''this''' < that` or `that` otherwise - */ - override def min(that: Int): Int = if (self < that) self else that - - /** - * @return `'''this'''` if `'''this''' > that` or `that` otherwise - */ - override def max(that: Int): Int = if (self > that) self else that - - /** - * Computes the absolute value of `'''this'''`. - */ - override def abs: Int = if (self < 0) -self else self - - def toBinaryString: String = java.lang.Integer.toBinaryString(self) - def toHexString: String = java.lang.Integer.toHexString(self) - def toOctalString: String = java.lang.Integer.toOctalString(self) } diff --git a/src/library/scala/runtime/RichLong.scala b/src/library/scala/runtime/RichLong.scala index e5b39b1c09..df0bbec047 100644 --- a/src/library/scala/runtime/RichLong.scala +++ b/src/library/scala/runtime/RichLong.scala @@ -9,20 +9,31 @@ package scala package runtime - final class RichLong(val self: Long) extends AnyVal with IntegralProxy[Long] { protected def num = scala.math.Numeric.LongIsIntegral protected def ord = scala.math.Ordering.Long - def toBinaryString: String = java.lang.Long.toBinaryString(self) - def toHexString: String = java.lang.Long.toHexString(self) - def toOctalString: String = java.lang.Long.toOctalString(self) + override def doubleValue() = self.toDouble + override def floatValue() = self.toFloat + override def longValue() = self + override def intValue() = self.toInt + override def byteValue() = self.toByte + override def shortValue() = self.toShort - override def isValidByte = self.toByte.toLong == self + override def isValidByte = self.toByte.toLong == self override def isValidShort = self.toShort.toLong == self - override def isValidChar = self.toChar.toLong == self - override def isValidInt = self.toInt.toLong == self - // override def isValidLong = true + override def isValidChar = self.toChar.toLong == self + override def isValidInt = self.toInt.toLong == self + def isValidLong = true // override def isValidFloat = self.toFloat.toLong == self && self != Long.MaxValue // override def isValidDouble = self.toDouble.toLong == self && self != Long.MaxValue + + override def abs: Long = math.abs(self) + override def max(that: Long): Long = math.max(self, that) + override def min(that: Long): Long = math.min(self, that) + override def signum: Int = math.signum(self).toInt + + def toBinaryString: String = java.lang.Long.toBinaryString(self) + def toHexString: String = java.lang.Long.toHexString(self) + def toOctalString: String = java.lang.Long.toOctalString(self) } diff --git a/src/library/scala/runtime/RichShort.scala b/src/library/scala/runtime/RichShort.scala index 3e5d8781ff..b35beff7eb 100644 --- a/src/library/scala/runtime/RichShort.scala +++ b/src/library/scala/runtime/RichShort.scala @@ -13,4 +13,18 @@ package runtime final class RichShort(val self: Short) extends AnyVal with ScalaWholeNumberProxy[Short] { protected def num = scala.math.Numeric.ShortIsIntegral protected def ord = scala.math.Ordering.Short + + override def doubleValue() = self.toDouble + override def floatValue() = self.toFloat + override def longValue() = self.toLong + override def intValue() = self.toInt + override def byteValue() = self.toByte + override def shortValue() = self + + override def isValidShort = true + + override def abs: Short = math.abs(self.toInt).toShort + override def max(that: Short): Short = math.max(self.toInt, that.toInt).toShort + override def min(that: Short): Short = math.min(self.toInt, that.toInt).toShort + override def signum: Int = math.signum(self.toInt) } diff --git a/src/library/scala/runtime/ScalaNumberProxy.scala b/src/library/scala/runtime/ScalaNumberProxy.scala index 6ea6448b1a..5e4da24c0d 100644 --- a/src/library/scala/runtime/ScalaNumberProxy.scala +++ b/src/library/scala/runtime/ScalaNumberProxy.scala @@ -32,9 +32,13 @@ trait ScalaNumberProxy[T] extends Any with ScalaNumericAnyConversions with Typed def byteValue() = intValue().toByte def shortValue() = intValue().toShort + /** Returns `'''this'''` if `'''this''' < that` or `that` otherwise. */ def min(that: T): T = num.min(self, that) + /** Returns `'''this'''` if `'''this''' > that` or `that` otherwise. */ def max(that: T): T = num.max(self, that) + /** Returns the absolute value of `'''this'''`. */ def abs = num.abs(self) + /** Returns the signum of `'''this'''`. */ def signum = num.signum(self) } trait ScalaWholeNumberProxy[T] extends Any with ScalaNumberProxy[T] { diff --git a/src/library/scala/runtime/VolatileObjectRef.java b/src/library/scala/runtime/VolatileObjectRef.java index 9f1f3ac0cf..6063501ffb 100755 --- a/src/library/scala/runtime/VolatileObjectRef.java +++ b/src/library/scala/runtime/VolatileObjectRef.java @@ -16,8 +16,9 @@ public class VolatileObjectRef<T> implements java.io.Serializable { volatile public T elem; public VolatileObjectRef(T elem) { this.elem = elem; } + @Override public String toString() { return String.valueOf(elem); } - public static <U> VolatileObjectRef create(U e) { return new VolatileObjectRef(e); } - public static VolatileObjectRef zero() { return new VolatileObjectRef(null); } + public static <U> VolatileObjectRef<U> create(U e) { return new VolatileObjectRef<U>(e); } + public static VolatileObjectRef<Object> zero() { return new VolatileObjectRef<Object>(null); } } diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala index 953b5e5535..2e6c3baa02 100644 --- a/src/partest/scala/tools/partest/DirectTest.scala +++ b/src/partest/scala/tools/partest/DirectTest.scala @@ -7,8 +7,9 @@ package scala.tools.partest import scala.tools.nsc._ import settings.ScalaVersion -import util.{ SourceFile, BatchSourceFile, CommandLineParser } +import util.{ SourceFile, BatchSourceFile } import reporters.{Reporter, ConsoleReporter} +import scala.tools.cmd.CommandLineParser /** A class for testing code which is embedded as a string. * It allows for more complete control over settings, compiler diff --git a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala index 8161e53bf9..33bf836a7b 100644 --- a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala +++ b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala @@ -9,7 +9,7 @@ package nest import utils.Properties._ import scala.tools.nsc.Properties.{ versionMsg, setProp } -import scala.tools.nsc.util.CommandLineParser +import scala.tools.nsc.util.CommandLine import scala.collection.{ mutable, immutable } import PathSettings.srcDir import TestKinds._ @@ -97,7 +97,7 @@ class ConsoleRunner extends DirectRunner { ) def main(argstr: String) { - val parsed = CommandLineParser(argstr) withUnaryArgs unaryArgs withBinaryArgs binaryArgs + val parsed = (new CommandLine(argstr)) withUnaryArgs unaryArgs withBinaryArgs binaryArgs if (parsed isSet "--debug") NestUI.setDebug() if (parsed isSet "--verbose") NestUI.setVerbose() diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index 30ec555bc5..5c92512193 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -98,7 +98,7 @@ abstract class TreeInfo { */ def isStableIdentifier(tree: Tree, allowVolatile: Boolean): Boolean = tree match { - case Ident(_) => symOk(tree.symbol) && tree.symbol.isStable && !tree.symbol.hasVolatileType // TODO SPEC: not required by spec + case i @ Ident(_) => isStableIdent(i) case Select(qual, _) => isStableMemberOf(tree.symbol, qual, allowVolatile) && isPath(qual, allowVolatile) case Apply(Select(free @ Ident(_), nme.apply), _) if free.symbol.name endsWith nme.REIFY_FREE_VALUE_SUFFIX => // see a detailed explanation of this trick in `GenSymbols.reifyFreeTerm` @@ -119,6 +119,13 @@ abstract class TreeInfo { typeOk(tree.tpe) && (allowVolatile || !hasVolatileType(tree)) && !definitions.isByNameParamType(tree.tpe) ) + private def isStableIdent(tree: Ident): Boolean = ( + symOk(tree.symbol) + && tree.symbol.isStable + && !definitions.isByNameParamType(tree.tpe) + && !tree.symbol.hasVolatileType // TODO SPEC: not required by spec + ) + /** Is `tree`'s type volatile? (Ignored if its symbol has the @uncheckedStable annotation.) */ def hasVolatileType(tree: Tree): Boolean = @@ -201,7 +208,7 @@ abstract class TreeInfo { } def isWarnableSymbol = { val sym = tree.symbol - (sym == null) || !(sym.isModule || sym.isLazy) || { + (sym == null) || !(sym.isModule || sym.isLazy || definitions.isByNameParamType(sym.tpe_*)) || { debuglog("'Pure' but side-effecting expression in statement position: " + tree) false } diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index 8ec8b2ed5f..a84d076e76 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -22,6 +22,7 @@ import scala.reflect.classTag import StdReplTags._ import scala.concurrent.{ ExecutionContext, Await, Future, future } import ExecutionContext.Implicits._ +import scala.reflect.internal.util.BatchSourceFile /** The Scala interactive shell. It provides a read-eval-print loop * around the Interpreter class. @@ -530,8 +531,19 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) def pasteCommand(): Result = { echo("// Entering paste mode (ctrl-D to finish)\n") val code = readWhile(_ => true) mkString "\n" - echo("\n// Exiting paste mode, now interpreting.\n") - intp interpret code + if (code.trim.isEmpty) { + echo("\n// Nothing pasted, nothing gained.\n") + } else { + echo("\n// Exiting paste mode, now interpreting.\n") + val res = intp interpret code + // if input is incomplete, let the compiler try to say why + if (res == IR.Incomplete) { + echo("The pasted code is incomplete!\n") + // Remembrance of Things Pasted in an object + val errless = intp compileSources new BatchSourceFile("<pastie>", s"object pastel {\n$code\n}") + if (errless) echo("...but compilation found no error? Good luck with that.") + } + } () } diff --git a/src/scaladoc/scala/tools/partest/ScaladocModelTest.scala b/src/scaladoc/scala/tools/partest/ScaladocModelTest.scala index f0a9caac15..70423cc7dc 100644 --- a/src/scaladoc/scala/tools/partest/ScaladocModelTest.scala +++ b/src/scaladoc/scala/tools/partest/ScaladocModelTest.scala @@ -7,7 +7,7 @@ package scala.tools.partest import scala.tools.nsc import scala.tools.nsc._ -import scala.tools.nsc.util.CommandLineParser +import scala.tools.cmd.CommandLineParser import scala.tools.nsc.doc.{ DocFactory, Universe } import scala.tools.nsc.doc.model._ import scala.tools.nsc.doc.model.diagram._ diff --git a/test/files/pos/t3936/BlockingQueue.java b/test/files/pos/t3936/BlockingQueue.java new file mode 100644 index 0000000000..b902d4528d --- /dev/null +++ b/test/files/pos/t3936/BlockingQueue.java @@ -0,0 +1,3 @@ +package pack; +import java.util.Queue; +public interface BlockingQueue<E> extends Queue<E> { } diff --git a/test/files/pos/t3936/Queue.java b/test/files/pos/t3936/Queue.java new file mode 100644 index 0000000000..25c9087601 --- /dev/null +++ b/test/files/pos/t3936/Queue.java @@ -0,0 +1,2 @@ +package pack; +public interface Queue { } diff --git a/test/files/pos/t3936/Test.scala b/test/files/pos/t3936/Test.scala new file mode 100644 index 0000000000..c867a05ec9 --- /dev/null +++ b/test/files/pos/t3936/Test.scala @@ -0,0 +1,4 @@ +package pack +trait Test { + val b: BlockingQueue[Nothing] +} diff --git a/test/files/pos/t7584.scala b/test/files/pos/t7584.scala new file mode 100644 index 0000000000..52d127ecb9 --- /dev/null +++ b/test/files/pos/t7584.scala @@ -0,0 +1,11 @@ +object Test { + def fold[A, B](f: (A, => B) => B) = ??? + def f[A, B](x: A, y: B): B = ??? + def bip[A, B] = fold[A, B]((x, y) => f(x, y)) + def bop[A, B] = fold[A, B](f) + + // these work: + fold[Int, Int]((x, y) => f(x, y)) + fold[Int, Int](f) +} + diff --git a/test/files/run/stream_length.check b/test/files/run/stream_length.check index 9906de773c..d1068f3247 100644 --- a/test/files/run/stream_length.check +++ b/test/files/run/stream_length.check @@ -1 +1,6 @@ +#partest !avian Length: 970299 + +#partest avian +!!!TEST SKIPPED!!! +See SI-7600 for further information. diff --git a/test/files/run/stream_length.scala b/test/files/run/stream_length.scala index 2808fbc495..33929f4b57 100644 --- a/test/files/run/stream_length.scala +++ b/test/files/run/stream_length.scala @@ -10,6 +10,10 @@ object Test { } def main(args: Array[String]) { - println("Length: " + walk(3, "---").length) + if (scala.tools.partest.utils.Properties.isAvian) { + println("!!!TEST SKIPPED!!!") + println("See SI-7600 for further information.") + } else + println("Length: " + walk(3, "---").length) } } diff --git a/test/files/run/t4294.scala b/test/files/run/t4294.scala index fafaf1d8ef..e15c716047 100644 --- a/test/files/run/t4294.scala +++ b/test/files/run/t4294.scala @@ -1,7 +1,12 @@ object Test { def main(args: Array[String]) { + // Skip test on Avian, see SI-7600 for further information + if (!scala.tools.partest.utils.Properties.isAvian) + run() + } + + def run(): Unit = { (Stream.from(1).collect{case x if x > 5000000 => x}: Stream[Int]) - assert((Stream from 1 take 10 collect { case x if x <= 3 => x*x }).sum == 14) } } diff --git a/test/files/run/t5603.scala b/test/files/run/t5603.scala index 8c8038a602..77c2775cc3 100644 --- a/test/files/run/t5603.scala +++ b/test/files/run/t5603.scala @@ -1,7 +1,7 @@ import scala.tools.partest._ import java.io._ import scala.tools.nsc._ -import scala.tools.nsc.util.CommandLineParser +import scala.tools.cmd.CommandLineParser import scala.tools.nsc.{Global, Settings, CompilerCommand} import scala.tools.nsc.reporters.ConsoleReporter diff --git a/test/files/run/t6308.scala b/test/files/run/t6308.scala index bcd89359b0..d23cd6e13e 100644 --- a/test/files/run/t6308.scala +++ b/test/files/run/t6308.scala @@ -1,21 +1,25 @@ import scala.{specialized => sp} +// NOTE: `{ val c = caller; print(""); c }` is used instead of a simple `caller`, +// because we want to prevent tail-call optimization from eliding the stack- +// frames we want to inspect. + object Test { def caller = new Exception().getStackTrace()(1).getMethodName - def f1[@sp(Int) A](a: A, b: Any) = caller - def f2[@sp(Int) A, B](a: A, b: String) = caller - def f3[B, @sp(Int) A](a: A, b: List[B]) = caller - def f4[B, @sp(Int) A](a: A, b: List[(A, B)]) = caller + def f1[@sp(Int) A](a: A, b: Any) = { val c = caller; print(""); c } + def f2[@sp(Int) A, B](a: A, b: String) = { val c = caller; print(""); c } + def f3[B, @sp(Int) A](a: A, b: List[B]) = { val c = caller; print(""); c } + def f4[B, @sp(Int) A](a: A, b: List[(A, B)]) = { val c = caller; print(""); c } - def f5[@sp(Int) A, B <: Object](a: A, b: B) = caller + def f5[@sp(Int) A, B <: Object](a: A, b: B) = { val c = caller; print(""); c } // `uncurryTreeType` calls a TypeMap on the call to this method and we end up with new // type parameter symbols, which are not found in `TypeEnv.includes(typeEnv(member), env)` // in `specSym`. (One of `uncurry`'s tasks is to expand type aliases in signatures.) type T = Object - def todo1[@sp(Int) A, B <: T](a: A, b: String) = caller - def todo2[@sp(Int) A, B <: AnyRef](a: A, b: String) = caller - def todo3[B <: List[A], @specialized(Int) A](a: A, b: B) = caller + def todo1[@sp(Int) A, B <: T](a: A, b: String) = { val c = caller; print(""); c } + def todo2[@sp(Int) A, B <: AnyRef](a: A, b: String) = { val c = caller; print(""); c } + def todo3[B <: List[A], @specialized(Int) A](a: A, b: B) = { val c = caller; print(""); c } def main(args: Array[String]) { val s = "" diff --git a/test/files/run/t6331.scala b/test/files/run/t6331.scala index 4e43a7686e..5ac627a8ea 100644 --- a/test/files/run/t6331.scala +++ b/test/files/run/t6331.scala @@ -1,7 +1,7 @@ import scala.tools.partest._ import java.io._ import scala.tools.nsc._ -import scala.tools.nsc.util.CommandLineParser +import scala.tools.cmd.CommandLineParser import scala.tools.nsc.{Global, Settings, CompilerCommand} import scala.tools.nsc.reporters.ConsoleReporter diff --git a/test/files/run/t6331b.scala b/test/files/run/t6331b.scala index f966abea51..c567455c5c 100644 --- a/test/files/run/t6331b.scala +++ b/test/files/run/t6331b.scala @@ -1,7 +1,7 @@ import scala.tools.partest._ import java.io._ import scala.tools.nsc._ -import scala.tools.nsc.util.CommandLineParser +import scala.tools.cmd.CommandLineParser import scala.tools.nsc.{Global, Settings, CompilerCommand} import scala.tools.nsc.reporters.ConsoleReporter diff --git a/test/files/run/t7271.scala b/test/files/run/t7271.scala index cb43331a29..55c388b7f5 100644 --- a/test/files/run/t7271.scala +++ b/test/files/run/t7271.scala @@ -1,7 +1,7 @@ import scala.tools.partest._ import java.io._ import scala.tools.nsc._ -import scala.tools.nsc.util.CommandLineParser +import scala.tools.cmd.CommandLineParser import scala.tools.nsc.{Global, Settings, CompilerCommand} import scala.tools.nsc.reporters.ConsoleReporter import scala.reflect.internal.Positions diff --git a/test/files/run/t7337.scala b/test/files/run/t7337.scala index d878182ed0..9913f8ae45 100644 --- a/test/files/run/t7337.scala +++ b/test/files/run/t7337.scala @@ -1,6 +1,6 @@ import scala.tools.partest._ import scala.tools.nsc._ -import util.{CommandLineParser} +import scala.tools.cmd.CommandLineParser object Test extends DirectTest { override def code = "class C" diff --git a/test/files/run/t7584.check b/test/files/run/t7584.check new file mode 100644 index 0000000000..9f53e5dde5 --- /dev/null +++ b/test/files/run/t7584.check @@ -0,0 +1,6 @@ +no calls +call A +a +call B twice +b +b diff --git a/test/files/run/t7584.flags b/test/files/run/t7584.flags new file mode 100644 index 0000000000..e8fb65d50c --- /dev/null +++ b/test/files/run/t7584.flags @@ -0,0 +1 @@ +-Xfatal-warnings
\ No newline at end of file diff --git a/test/files/run/t7584.scala b/test/files/run/t7584.scala new file mode 100644 index 0000000000..6d7f4f7ebb --- /dev/null +++ b/test/files/run/t7584.scala @@ -0,0 +1,14 @@ +// Test case added to show the behaviour of functions with +// by-name parameters. The evaluation behaviour was already correct. +// +// We did flush out a spurious "pure expression does nothing in statement position" +// warning, hence -Xfatal-warnings in the flags file. +object Test extends App { + def foo(f: (=> Int, => Int) => Unit) = f({println("a"); 0}, {println("b"); 1}) + println("no calls") + foo((a, b) => ()) + println("call A") + foo((a, b) => a) + println("call B twice") + foo((a, b) => {b; b}) +} diff --git a/test/files/specialized/SI-7344.scala b/test/files/specialized/SI-7344.scala new file mode 100644 index 0000000000..1040460bd1 --- /dev/null +++ b/test/files/specialized/SI-7344.scala @@ -0,0 +1,53 @@ +/* Test for SI-7344, where specialized methods inside the bodies of other + * methods are not specialized, although they might as well be. The name + * for the specialized method should not be different depending on the + * outside method/class' specialization. */ + +class Test[@specialized(Int, Double) X](val x: X) { + + def checkSpecialization[Y](@specialized(Int, Double) y: Y): X = { + + // checking the specialization using the method name, which we can + // extract from an exception's stack trace. We can match just the + // prefix, since the compiler will add a suffix to the method name + // during lambdalift, when it lifts the local methods outside. + def specMe[@specialized(Int, Double) T, N](t: T, n: N): Unit = checkNameStartsWith(n.toString) + + // expected to specialize: + specMe("x", "specMe") + specMe(123, "specMe$mIc$sp") + specMe(1.3, new { override def toString = "specMe$mDc$sp" }) + + x + } + + // name matching: + private[this] def checkNameStartsWith(prefix: String): Unit = { + val method = (new Exception).getStackTrace()(1).getMethodName() + assert(method.startsWith(prefix), method + ".startsWith(" + prefix + ") should be true") + } +} + +object Test extends App { + val t1 = new Test("x") + val t2 = new Test(123) + val t3 = new Test(1.3) + + // we want specialization to rewire these, + // that's why they're not in a for loop: + t1.checkSpecialization("x") + + // Prevented by SI-7579: + // The duplicator loses the @specialized annotation, + // so our tree transformation doesn't know it needs to + // specialize specMe inside the duplicated (and specialized) + // variants of the `checkSpecialization` method + // t1.checkSpecialization(123) + // t1.checkSpecialization(1.3) + // t2.checkSpecialization("x") + // t2.checkSpecialization(123) + // t2.checkSpecialization(1.3) + // t3.checkSpecialization("x") + // t3.checkSpecialization(123) + // t3.checkSpecialization(1.3) +} diff --git a/test/scaladoc/run/t5527.scala b/test/scaladoc/run/t5527.scala index 60ae23c1a7..770d4ad13f 100644 --- a/test/scaladoc/run/t5527.scala +++ b/test/scaladoc/run/t5527.scala @@ -1,7 +1,7 @@ import scala.tools.partest._ import java.io._ import scala.tools.nsc._ -import scala.tools.nsc.util.CommandLineParser +import scala.tools.cmd.CommandLineParser import scala.tools.nsc.doc.{Settings, DocFactory} import scala.tools.nsc.reporters.ConsoleReporter |