summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala22
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala13
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeGlue.scala8
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala10
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala31
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala79
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala4
-rw-r--r--src/library/scala/collection/immutable/HashSet.scala525
-rw-r--r--src/library/scala/collection/immutable/NumericRange.scala91
-rw-r--r--src/reflect/scala/reflect/macros/Aliases.scala10
-rw-r--r--src/reflect/scala/reflect/macros/Enclosures.scala34
-rw-r--r--src/reflect/scala/reflect/macros/Universe.scala12
-rw-r--r--test/files/neg/dotless-targs.check4
-rw-r--r--test/files/neg/dotless-targs.scala5
-rw-r--r--test/files/neg/t8157.check4
-rw-r--r--test/files/neg/t8157.scala4
-rw-r--r--test/files/pos/bcode_throw_null/TN.scala7
-rw-r--r--test/files/pos/dotless-targs.scala9
-rw-r--r--test/files/pos/overzealous-assert-genbcode.scala10
-rw-r--r--test/files/run/t6253a.scala64
-rw-r--r--test/files/run/t6253b.scala62
-rw-r--r--test/files/run/t6253c.scala63
-rw-r--r--test/files/scalacheck/quasiquotes/TermConstructionProps.scala5
-rw-r--r--test/junit/scala/collection/NumericRangeTest.scala123
31 files changed, 1114 insertions, 114 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index d122a1a207..38a6170637 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -133,7 +133,7 @@ self =>
val global: Global
import global._
- case class OpInfo(lhs: Tree, operator: TermName, offset: Offset) {
+ case class OpInfo(lhs: Tree, operator: TermName, targs: List[Tree], offset: Offset) {
def precedence = Precedence(operator.toString)
}
@@ -787,10 +787,13 @@ self =>
private def opHead = opstack.head
private def headPrecedence = opHead.precedence
private def popOpInfo(): OpInfo = try opHead finally opstack = opstack.tail
- private def pushOpInfo(top: Tree) {
- val opinfo = OpInfo(top, in.name, in.offset)
- opstack ::= opinfo
+ private def pushOpInfo(top: Tree): Unit = {
+ val name = in.name
+ val offset = in.offset
ident()
+ val targs = if (in.token == LBRACKET) exprTypeArgs() else Nil
+ val opinfo = OpInfo(top, name, targs, offset)
+ opstack ::= opinfo
}
def checkHeadAssoc(leftAssoc: Boolean) = checkAssoc(opHead.offset, opHead.operator, leftAssoc)
@@ -800,6 +803,9 @@ self =>
)
def finishPostfixOp(start: Int, base: List[OpInfo], opinfo: OpInfo): Tree = {
+ if (opinfo.targs.nonEmpty)
+ syntaxError(opinfo.offset, "type application is not allowed for postfix operators")
+
val od = stripParens(reduceExprStack(base, opinfo.lhs))
makePostfixSelect(start, opinfo.offset, od, opinfo.operator)
}
@@ -809,7 +815,7 @@ self =>
val operatorPos: Position = Position.range(rhs.pos.source, offset, offset, offset + operator.length)
val pos = lhs.pos union rhs.pos union operatorPos withPoint offset
- atPos(pos)(makeBinop(isExpr, lhs, operator, rhs, operatorPos))
+ atPos(pos)(makeBinop(isExpr, lhs, operator, rhs, operatorPos, opinfo.targs))
}
def reduceExprStack(base: List[OpInfo], top: Tree): Tree = reduceStack(isExpr = true, base, top)
@@ -1892,9 +1898,9 @@ self =>
def isDelimiter = in.token == RPAREN || in.token == RBRACE
def isCommaOrDelimiter = isComma || isDelimiter
val (isUnderscore, isStar) = opstack match {
- case OpInfo(Ident(nme.WILDCARD), nme.STAR, _) :: _ => (true, true)
- case OpInfo(_, nme.STAR, _) :: _ => (false, true)
- case _ => (false, false)
+ case OpInfo(Ident(nme.WILDCARD), nme.STAR, _, _) :: _ => (true, true)
+ case OpInfo(_, nme.STAR, _, _) :: _ => (false, true)
+ case _ => (false, false)
}
def isSeqPatternClose = isUnderscore && isStar && isSequenceOK && isDelimiter
val preamble = "bad simple pattern:"
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index d88470bd5e..cfee988efc 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -55,7 +55,13 @@ abstract class TreeBuilder {
ValDef(Modifiers(PRIVATE), name, tpt, EmptyTree)
/** Create tree representing (unencoded) binary operation expression or pattern. */
- def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position): Tree = {
+ def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position, targs: List[Tree] = Nil): Tree = {
+ require(isExpr || targs.isEmpty, s"Incompatible args to makeBinop: !isExpr but targs=$targs")
+
+ def mkSelection(t: Tree) = {
+ def sel = atPos(opPos union t.pos)(Select(stripParens(t), op.encode))
+ if (targs.isEmpty) sel else atPos(left.pos)(TypeApply(sel, targs))
+ }
def mkNamed(args: List[Tree]) = if (isExpr) args map treeInfo.assignmentToMaybeNamedArg else args
val arguments = right match {
case Parens(args) => mkNamed(args)
@@ -63,12 +69,12 @@ abstract class TreeBuilder {
}
if (isExpr) {
if (treeInfo.isLeftAssoc(op)) {
- Apply(atPos(opPos union left.pos) { Select(stripParens(left), op.encode) }, arguments)
+ Apply(mkSelection(left), arguments)
} else {
val x = freshTermName()
Block(
List(ValDef(Modifiers(SYNTHETIC | ARTIFACT), x, TypeTree(), stripParens(left))),
- Apply(atPos(opPos union right.pos) { Select(stripParens(right), op.encode) }, List(Ident(x))))
+ Apply(mkSelection(right), List(Ident(x))))
}
} else {
Apply(Ident(op.encode), stripParens(left) :: arguments)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
index 4f9f4c9e31..c8845344e9 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
@@ -88,7 +88,9 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
def genThrow(expr: Tree): BType = {
val thrownKind = tpeTK(expr)
- assert(exemplars.get(thrownKind).isSubtypeOf(ThrowableReference))
+ // `throw null` is valid although scala.Null (as defined in src/libray-aux) isn't a subtype of Throwable.
+ // Similarly for scala.Nothing (again, as defined in src/libray-aux).
+ assert(thrownKind.isNullType || thrownKind.isNothingType || exemplars.get(thrownKind).isSubtypeOf(ThrowableReference))
genLoad(expr, thrownKind)
lineNumber(expr)
emit(asm.Opcodes.ATHROW) // ICode enters here into enterIgnoreMode, we'll rely instead on DCE at ClassNode level.
@@ -824,7 +826,6 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
/* Generate code that loads args into label parameters. */
def genLoadLabelArguments(args: List[Tree], lblDef: LabelDef, gotoPos: Position) {
- assert(args forall { a => !a.hasSymbolField || a.hasSymbolWhich( s => !s.isLabel) }, s"SI-6089 at: $gotoPos") // SI-6089
val aps = {
val params: List[Symbol] = lblDef.params.map(_.symbol)
@@ -857,12 +858,11 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
}
def genLoadModule(tree: Tree): BType = {
- // Working around SI-5604. Rather than failing the compile when we see a package here, check if there's a package object.
val module = (
if (!tree.symbol.isPackageClass) tree.symbol
else tree.symbol.info.member(nme.PACKAGE) match {
- case NoSymbol => abort(s"Cannot use package as value: $tree") ; NoSymbol
- case s => devWarning("Bug: found package class where package object expected. Converting.") ; s.moduleClass
+ case NoSymbol => abort(s"SI-5604: Cannot use package as value: $tree")
+ case s => abort(s"SI-5604: found package class where package object expected: $tree")
}
)
lineNumber(tree)
@@ -871,7 +871,8 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
}
def genLoadModule(module: Symbol) {
- if (claszSymbol == module.moduleClass && jMethodName != "readResolve") {
+ def inStaticMethod = methSymbol != null && methSymbol.isStaticMember
+ if (claszSymbol == module.moduleClass && jMethodName != "readResolve" && !inStaticMethod) {
mnode.visitVarInsn(asm.Opcodes.ALOAD, 0)
} else {
val mbt = symInfoTK(module)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeGlue.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeGlue.scala
index 9dcf263f4f..cc3265c5f9 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeGlue.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeGlue.scala
@@ -661,6 +661,14 @@ abstract class BCodeGlue extends SubComponent {
val CT_NOTHING = brefType("scala/Nothing") // TODO needed?
val CT_NULL = brefType("scala/Null") // TODO needed?
+ val srBooleanRef = brefType("scala/runtime/BooleanRef")
+ val srByteRef = brefType("scala/runtime/ByteRef")
+ val srCharRef = brefType("scala/runtime/CharRef")
+ val srIntRef = brefType("scala/runtime/IntRef")
+ val srLongRef = brefType("scala/runtime/LongRef")
+ val srFloatRef = brefType("scala/runtime/FloatRef")
+ val srDoubleRef = brefType("scala/runtime/DoubleRef")
+
/* Map from type kinds to the Java reference types.
* Useful when pushing class literals onto the operand stack (ldc instruction taking a class literal).
* @see Predef.classOf
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
index 64ed094a47..6b1bb5b220 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
@@ -440,13 +440,11 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
if (sym0 == definitions.NullClass) return RT_NULL;
if (sym0 == definitions.NothingClass) return RT_NOTHING;
- // Working around SI-5604. Rather than failing the compile when we see
- // a package here, check if there's a package object.
val sym = (
if (!sym0.isPackageClass) sym0
else sym0.info.member(nme.PACKAGE) match {
- case NoSymbol => abort(s"Cannot use package as value: ${sym0.fullName}")
- case s => devWarning("Bug: found package class where package object expected. Converting.") ; s.moduleClass
+ case NoSymbol => abort(s"SI-5604: Cannot use package as value: ${sym0.fullName}")
+ case s => abort(s"SI-5604: found package class where package object expected: $s")
}
)
@@ -561,7 +559,9 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters {
memberCTK
}
- exemplar(csym) // side effect city
+
+ exemplar(csym).directMemberClasses = result
+
result
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
index 529295389c..c3492b79a9 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
@@ -46,6 +46,7 @@ abstract class BCodeIdiomatic extends BCodeGlue {
val ObjectReference = brefType("java/lang/Object")
val AnyRefReference = ObjectReference
+ val objArrayReference = arrayOf(ObjectReference)
val JAVA_LANG_OBJECT = ObjectReference
val JAVA_LANG_STRING = brefType("java/lang/String")
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
index c921d11d00..360ce58ecc 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
@@ -460,7 +460,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
}
def lineNumber(tree: Tree) {
if (!emitLines || !tree.pos.isDefined) return;
- val nr = tree.pos.line
+ val nr = tree.pos.finalPosition.line
if (nr != lastEmittedLineNr) {
lastEmittedLineNr = nr
lastInsn match {
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala
index 27bcbb82d4..9ddb7a3ce8 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala
@@ -386,10 +386,6 @@ abstract class BCodeSyncAndTry extends BCodeBodyBuilder {
/* Does this tree have a try-catch block? */
def mayCleanStack(tree: Tree): Boolean = tree exists { t => t.isInstanceOf[Try] }
- abstract class Cleanup(val value: AnyRef) { }
- case class MonitorRelease(v: Symbol) extends Cleanup(v) { }
- case class Finalizer(f: Tree) extends Cleanup (f) { }
-
trait EHClause
case class NamelessEH(typeToDrop: BType, caseBody: Tree) extends EHClause
case class BoundEH (patSymbol: Symbol, caseBody: Tree) extends EHClause
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala
index dd2d63ad17..1eca69936a 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala
@@ -24,11 +24,15 @@ abstract class BCodeTypes extends BCodeIdiomatic {
// when compiling the Scala library, some assertions don't hold (e.g., scala.Boolean has null superClass although it's not an interface)
val isCompilingStdLib = !(settings.sourcepath.isDefault)
+ val srBoxedUnit = brefType("scala/runtime/BoxedUnit")
+
// special names
var StringReference : BType = null
var ThrowableReference : BType = null
var jlCloneableReference : BType = null // java/lang/Cloneable
+ var jlNPEReference : BType = null // java/lang/NullPointerException
var jioSerializableReference : BType = null // java/io/Serializable
+ var scalaSerializableReference : BType = null // scala/Serializable
var classCastExceptionReference : BType = null // java/lang/ClassCastException
/* A map from scala primitive type-symbols to BTypes */
@@ -52,6 +56,8 @@ abstract class BCodeTypes extends BCodeIdiomatic {
/* The Object => String overload. */
var String_valueOf: Symbol = null
+ var ArrayInterfaces: Set[Tracked] = null
+
// scala.FunctionX and scala.runtim.AbstractFunctionX
val FunctionReference = new Array[Tracked](definitions.MaxFunctionArity + 1)
val AbstractFunctionReference = new Array[Tracked](definitions.MaxFunctionArity + 1)
@@ -128,15 +134,17 @@ abstract class BCodeTypes extends BCodeIdiomatic {
)
}
- exemplar(JavaCloneableClass).c
- exemplar(JavaSerializableClass).c
- exemplar(SerializableClass).c
+ exemplar(JavaCloneableClass)
+ exemplar(JavaSerializableClass)
+ exemplar(SerializableClass)
StringReference = exemplar(StringClass).c
StringBuilderReference = exemplar(StringBuilderClass).c
ThrowableReference = exemplar(ThrowableClass).c
jlCloneableReference = exemplar(JavaCloneableClass).c
+ jlNPEReference = exemplar(NullPointerExceptionClass).c
jioSerializableReference = exemplar(JavaSerializableClass).c
+ scalaSerializableReference = exemplar(SerializableClass).c
classCastExceptionReference = exemplar(ClassCastExceptionClass).c
/*
@@ -203,6 +211,23 @@ abstract class BCodeTypes extends BCodeIdiomatic {
* All methods of this class can-multi-thread
*/
case class Tracked(c: BType, flags: Int, sc: Tracked, ifaces: Array[Tracked], innersChain: Array[InnerClassEntry]) {
+
+ // not a case-field because we initialize it only for JVM classes we emit.
+ private var _directMemberClasses: List[BType] = null
+
+ def directMemberClasses: List[BType] = {
+ assert(_directMemberClasses != null, s"getter directMemberClasses() invoked too early for $c")
+ _directMemberClasses
+ }
+
+ def directMemberClasses_=(bs: List[BType]) {
+ if (_directMemberClasses != null) {
+ // TODO we enter here when both mirror class and plain class are emitted for the same ModuleClassSymbol.
+ assert(_directMemberClasses == bs.sortBy(_.off))
+ }
+ _directMemberClasses = bs.sortBy(_.off)
+ }
+
/* `isCompilingStdLib` saves the day when compiling:
* (1) scala.Nothing (the test `c.isNonSpecial` fails for it)
* (2) scala.Boolean (it has null superClass and is not an interface)
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 6ec364bcb6..307f42c0bc 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -73,48 +73,55 @@ trait ScalaSettings extends AbsScalaSettings
val nospecialization = BooleanSetting ("-no-specialization", "Ignore @specialize annotations.")
val language = MultiStringSetting("-language", "feature", "Enable one or more language features.")
+ /*
+ * The previous "-source" option is intended to be used mainly
+ * though this helper.
+ */
+ lazy val isScala211: Boolean = (source.value >= ScalaVersion("2.11.0"))
+
/**
* -X "Advanced" settings
*/
- val Xhelp = BooleanSetting ("-X", "Print a synopsis of advanced options.")
- val checkInit = BooleanSetting ("-Xcheckinit", "Wrap field accessors to throw an exception on uninitialized access.")
- val developer = BooleanSetting ("-Xdev", "Indicates user is a developer - issue warnings about anything which seems amiss")
- val noassertions = BooleanSetting ("-Xdisable-assertions", "Generate no assertions or assumptions.")
- val elidebelow = IntSetting ("-Xelide-below", "Calls to @elidable methods are omitted if method priority is lower than argument",
+ val Xhelp = BooleanSetting ("-X", "Print a synopsis of advanced options.")
+ val checkInit = BooleanSetting ("-Xcheckinit", "Wrap field accessors to throw an exception on uninitialized access.")
+ val developer = BooleanSetting ("-Xdev", "Indicates user is a developer - issue warnings about anything which seems amiss")
+ val noassertions = BooleanSetting ("-Xdisable-assertions", "Generate no assertions or assumptions.")
+ val elidebelow = IntSetting ("-Xelide-below", "Calls to @elidable methods are omitted if method priority is lower than argument",
elidable.MINIMUM, None, elidable.byName get _)
- val noForwarders = BooleanSetting ("-Xno-forwarders", "Do not generate static forwarders in mirror classes.")
- val genPhaseGraph = StringSetting ("-Xgenerate-phase-graph", "file", "Generate the phase graphs (outputs .dot files) to fileX.dot.", "")
- val XlogImplicits = BooleanSetting ("-Xlog-implicits", "Show more detail on why some implicits are not applicable.")
- val logImplicitConv = BooleanSetting ("-Xlog-implicit-conversions", "Print a message whenever an implicit conversion is inserted.")
- val logReflectiveCalls = BooleanSetting("-Xlog-reflective-calls", "Print a message when a reflective method call is generated")
- val logFreeTerms = BooleanSetting ("-Xlog-free-terms", "Print a message when reification creates a free term.")
- val logFreeTypes = BooleanSetting ("-Xlog-free-types", "Print a message when reification resorts to generating a free type.")
- val maxClassfileName = IntSetting ("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, Some((72, 255)), _ => None)
- val Xmigration = ScalaVersionSetting("-Xmigration", "version", "Warn about constructs whose behavior may have changed since version.", AnyScalaVersion)
- val nouescape = BooleanSetting ("-Xno-uescape", "Disable handling of \\u unicode escapes.")
- val Xnojline = BooleanSetting ("-Xnojline", "Do not use JLine for editing.")
- val Xverify = BooleanSetting ("-Xverify", "Verify generic signatures in generated bytecode (asm backend only.)")
- val plugin = MultiStringSetting("-Xplugin", "paths", "Load a plugin from each classpath.")
- val disable = MultiStringSetting("-Xplugin-disable", "plugin", "Disable plugins by name.")
- val showPlugins = BooleanSetting ("-Xplugin-list", "Print a synopsis of loaded plugins.")
- val require = MultiStringSetting("-Xplugin-require", "plugin", "Abort if a named plugin is not loaded.")
- val pluginsDir = StringSetting ("-Xpluginsdir", "path", "Path to search for plugin archives.", Defaults.scalaPluginPath)
- val Xprint = PhasesSetting ("-Xprint", "Print out program after")
- val writeICode = PhasesSetting ("-Xprint-icode", "Log internal icode to *.icode files after", "icode")
- val Xprintpos = BooleanSetting ("-Xprint-pos", "Print tree positions, as offsets.")
- val printtypes = BooleanSetting ("-Xprint-types", "Print tree types (debugging option).")
- val prompt = BooleanSetting ("-Xprompt", "Display a prompt after each error (debugging option).")
- val resident = BooleanSetting ("-Xresident", "Compiler stays resident: read source filenames from standard input.")
- val script = StringSetting ("-Xscript", "object", "Treat the source file as a script and wrap it in a main method.", "")
- val mainClass = StringSetting ("-Xmain-class", "path", "Class for manifest's Main-Class entry (only useful with -d <jar>)", "")
- val Xshowcls = StringSetting ("-Xshow-class", "class", "Show internal representation of class.", "")
- val Xshowobj = StringSetting ("-Xshow-object", "object", "Show internal representation of object.", "")
- val showPhases = BooleanSetting ("-Xshow-phases", "Print a synopsis of compiler phases.")
- val sourceReader = StringSetting ("-Xsource-reader", "classname", "Specify a custom method for reading source files.", "")
- val strictInference = BooleanSetting ("-Xstrict-inference", "Don't infer known-unsound types")
+ val noForwarders = BooleanSetting ("-Xno-forwarders", "Do not generate static forwarders in mirror classes.")
+ val genPhaseGraph = StringSetting ("-Xgenerate-phase-graph", "file", "Generate the phase graphs (outputs .dot files) to fileX.dot.", "")
+ val XlogImplicits = BooleanSetting ("-Xlog-implicits", "Show more detail on why some implicits are not applicable.")
+ val logImplicitConv = BooleanSetting ("-Xlog-implicit-conversions", "Print a message whenever an implicit conversion is inserted.")
+ val logReflectiveCalls = BooleanSetting ("-Xlog-reflective-calls", "Print a message when a reflective method call is generated")
+ val logFreeTerms = BooleanSetting ("-Xlog-free-terms", "Print a message when reification creates a free term.")
+ val logFreeTypes = BooleanSetting ("-Xlog-free-types", "Print a message when reification resorts to generating a free type.")
+ val maxClassfileName = IntSetting ("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, Some((72, 255)), _ => None)
+ val Xmigration = ScalaVersionSetting ("-Xmigration", "version", "Warn about constructs whose behavior may have changed since version.", AnyScalaVersion)
+ val nouescape = BooleanSetting ("-Xno-uescape", "Disable handling of \\u unicode escapes.")
+ val Xnojline = BooleanSetting ("-Xnojline", "Do not use JLine for editing.")
+ val Xverify = BooleanSetting ("-Xverify", "Verify generic signatures in generated bytecode (asm backend only.)")
+ val plugin = MultiStringSetting ("-Xplugin", "paths", "Load a plugin from each classpath.")
+ val disable = MultiStringSetting ("-Xplugin-disable", "plugin", "Disable plugins by name.")
+ val showPlugins = BooleanSetting ("-Xplugin-list", "Print a synopsis of loaded plugins.")
+ val require = MultiStringSetting ("-Xplugin-require", "plugin", "Abort if a named plugin is not loaded.")
+ val pluginsDir = StringSetting ("-Xpluginsdir", "path", "Path to search for plugin archives.", Defaults.scalaPluginPath)
+ val Xprint = PhasesSetting ("-Xprint", "Print out program after")
+ val writeICode = PhasesSetting ("-Xprint-icode", "Log internal icode to *.icode files after", "icode")
+ val Xprintpos = BooleanSetting ("-Xprint-pos", "Print tree positions, as offsets.")
+ val printtypes = BooleanSetting ("-Xprint-types", "Print tree types (debugging option).")
+ val prompt = BooleanSetting ("-Xprompt", "Display a prompt after each error (debugging option).")
+ val resident = BooleanSetting ("-Xresident", "Compiler stays resident: read source filenames from standard input.")
+ val script = StringSetting ("-Xscript", "object", "Treat the source file as a script and wrap it in a main method.", "")
+ val mainClass = StringSetting ("-Xmain-class", "path", "Class for manifest's Main-Class entry (only useful with -d <jar>)", "")
+ val Xshowcls = StringSetting ("-Xshow-class", "class", "Show internal representation of class.", "")
+ val Xshowobj = StringSetting ("-Xshow-object", "object", "Show internal representation of object.", "")
+ val showPhases = BooleanSetting ("-Xshow-phases", "Print a synopsis of compiler phases.")
+ val sourceReader = StringSetting ("-Xsource-reader", "classname", "Specify a custom method for reading source files.", "")
+ val strictInference = BooleanSetting ("-Xstrict-inference", "Don't infer known-unsound types")
+ val source = ScalaVersionSetting ("-Xsource", "version", "Treat compiler input as Scala source for the specified version, see SI-8126.", ScalaVersion("2.11")) withPostSetHook ( _ => isScala211)
val XnoPatmatAnalysis = BooleanSetting ("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.")
- val XfullLubs = BooleanSetting ("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.")
+ val XfullLubs = BooleanSetting ("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.")
/** Compatibility stubs for options whose value name did
* not previously match the option name.
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 19fba639e3..06a1e21e8b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -1365,7 +1365,7 @@ trait Implicits {
maybeInvalidConversionError("the result type of an implicit conversion must be more specific than AnyRef")
result = SearchFailure
}
- else if (isInvalidConversionSource(pt)) {
+ else if (settings.isScala211 && isInvalidConversionSource(pt)) {
maybeInvalidConversionError("an expression of type Null is ineligible for implicit conversion")
result = SearchFailure
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 95f2620061..4ba8d56da0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -132,11 +132,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
defaultMethodNames.toList.distinct foreach { name =>
val methods = clazz.info.findMember(name, 0L, requiredFlags = METHOD, stableOnly = false).alternatives
- def hasDefaultParam(tpe: Type): Boolean = tpe match {
- case MethodType(params, restpe) => (params exists (_.hasDefault)) || hasDefaultParam(restpe)
- case _ => false
- }
- val haveDefaults = methods filter (sym => hasDefaultParam(sym.info) && !nme.isProtectedAccessorName(sym.name))
+ val haveDefaults = methods filter (sym => mexists(sym.info.paramss)(_.hasDefault) && !nme.isProtectedAccessorName(sym.name))
if (haveDefaults.lengthCompare(1) > 0) {
val owners = haveDefaults map (_.owner)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 6b5afce993..5d0d5392dd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1793,7 +1793,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val impl2 = finishMethodSynthesis(impl1, clazz, context)
- if (mdef.symbol == PredefModule)
+ if (settings.isScala211 && mdef.symbol == PredefModule)
ensurePredefParentsAreInSameSourceFile(impl2)
// SI-5954. On second compile of a companion class contained in a package object we end up
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
index 6e6b617e5c..1bd9323752 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
@@ -55,7 +55,7 @@ trait Parsers { self: Quasiquotes =>
def isHole(name: Name): Boolean = holeMap.contains(name)
- override implicit def fresh: FreshNameCreator = new FreshNameCreator(nme.QUASIQUOTE_PREFIX)
+ override implicit lazy val fresh: FreshNameCreator = new FreshNameCreator(nme.QUASIQUOTE_PREFIX)
override val treeBuilder = new ParserTreeBuilder {
override implicit def fresh: FreshNameCreator = parser.fresh
@@ -193,4 +193,4 @@ trait Parsers { self: Quasiquotes =>
}
object FreshName extends FreshNameExtractor(nme.QUASIQUOTE_PREFIX)
-} \ No newline at end of file
+}
diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala
index 127b22185a..67e9d18da7 100644
--- a/src/library/scala/collection/immutable/HashSet.scala
+++ b/src/library/scala/collection/immutable/HashSet.scala
@@ -15,6 +15,7 @@ package immutable
import generic._
import scala.collection.parallel.immutable.ParHashSet
import scala.collection.GenSet
+import scala.annotation.tailrec
/** This class implements immutable sets using a hash trie.
*
@@ -38,7 +39,7 @@ class HashSet[A] extends AbstractSet[A]
with CustomParallelizable[A, ParHashSet[A]]
with Serializable
{
- import HashSet.{nullToEmpty, bufferSize}
+ import HashSet.{nullToEmpty, bufferSize, LeafHashSet}
override def companion: GenericCompanion[HashSet] = HashSet
@@ -85,8 +86,81 @@ class HashSet[A] extends AbstractSet[A]
override def + (elem1: A, elem2: A, elems: A*): HashSet[A] =
this + elem1 + elem2 ++ elems
+ override def union(that: GenSet[A]): HashSet[A] = that match {
+ case that: HashSet[A] =>
+ val buffer = new Array[HashSet[A]](bufferSize(this.size + that.size))
+ nullToEmpty(union0(that, 0, buffer, 0))
+ case _ => super.union(that)
+ }
+
+ override def intersect(that: GenSet[A]): HashSet[A] = that match {
+ case that: HashSet[A] =>
+ val buffer = new Array[HashSet[A]](bufferSize(this.size min that.size))
+ nullToEmpty(intersect0(that, 0, buffer, 0))
+ case _ => super.intersect(that)
+ }
+
+ override def diff(that: GenSet[A]): HashSet[A] = that match {
+ case that: HashSet[A] =>
+ val buffer = new Array[HashSet[A]](bufferSize(this.size))
+ nullToEmpty(diff0(that, 0, buffer, 0))
+ case _ => super.diff(that)
+ }
+
+ /**
+ * Union with a leaf HashSet at a given level.
+ * @param that a leaf HashSet
+ * @param level the depth in the tree. We need this when we have to create a branch node on top of this and that
+ * @return The union of this and that at the given level. Unless level is zero, the result is not a self-contained
+ * HashSet but needs to be stored at the correct depth
+ */
+ private[immutable] def union0(that: LeafHashSet[A], level: Int): HashSet[A] = {
+ // the default implementation is for the empty set, so we just return that
+ that
+ }
+
+ /**
+ * Union with a HashSet at a given level
+ * @param that a HashSet
+ * @param level the depth in the tree. We need to keep track of the level to know how deep we are in the tree
+ * @param buffer a temporary buffer that is used for temporarily storing elements when creating new branch nodes
+ * @param offset0 the first offset into the buffer in which we are allowed to write
+ * @return The union of this and that at the given level. Unless level is zero, the result is not a self-contained
+ * HashSet but needs to be stored at the correct depth
+ */
+ private[immutable] def union0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = {
+ // the default implementation is for the empty set, so we just return that
+ that
+ }
+
+ /**
+ * Intersection with another hash set at a given level
+ * @param level the depth in the tree. We need to keep track of the level to know how deep we are in the tree
+ * @param buffer a temporary buffer that is used for temporarily storing elements when creating new branch nodes
+ * @param offset0 the first offset into the buffer in which we are allowed to write
+ * @return The intersection of this and that at the given level. Unless level is zero, the result is not a
+ * self-contained HashSet but needs to be stored at the correct depth
+ */
+ private[immutable] def intersect0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = {
+ // the default implementation is for the empty set, so we just return the empty set
+ null
+ }
+
+ /**
+ * Diff with another hash set at a given level
+ * @param level the depth in the tree. We need to keep track of the level to know how deep we are in the tree
+ * @param buffer a temporary buffer that is used for temporarily storing elements when creating new branch nodes
+ * @param offset0 the first offset into the buffer in which we are allowed to write
+ * @return The diff of this and that at the given level. Unless level is zero, the result is not a
+ * self-contained HashSet but needs to be stored at the correct depth
+ */
+ private[immutable] def diff0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = {
+ // the default implementation is for the empty set, so we just return the empty set
+ null
+ }
+
def - (e: A): HashSet[A] =
- removed0(e, computeHash(e), 0)
+ nullToEmpty(removed0(e, computeHash(e), 0))
override def filter(p: A => Boolean) = {
val buffer = new Array[HashSet[A]](bufferSize(size))
@@ -165,7 +239,14 @@ object HashSet extends ImmutableSetFactory[HashSet] {
}
}
- class HashSet1[A](private[HashSet] val key: A, private[HashSet] val hash: Int) extends HashSet[A] {
+ /**
+ * Common superclass of HashSet1 and HashSetCollision1, which are the two possible leaves of the Trie
+ */
+ private[HashSet] sealed abstract class LeafHashSet[A] extends HashSet[A] {
+ private[HashSet] def hash:Int
+ }
+
+ class HashSet1[A](private[HashSet] val key: A, private[HashSet] val hash: Int) extends LeafHashSet[A] {
override def size = 1
override def get0(key: A, hash: Int, level: Int): Boolean =
@@ -190,8 +271,42 @@ object HashSet extends ImmutableSetFactory[HashSet] {
}
}
+ override private[immutable] def union0(that: LeafHashSet[A], level: Int): HashSet[A] = that match {
+ case that if that.hash != this.hash =>
+ // different hash code, so there is no need to investigate further.
+ // Just create a branch node containing the two.
+ makeHashTrieSet(this.hash, this, that.hash, that, level)
+ case that: HashSet1[A] =>
+ if (this.key == that.key) {
+ this
+ } else {
+ // 32-bit hash collision (rare, but not impossible)
+ new HashSetCollision1[A](hash, ListSet.empty + this.key + that.key)
+ }
+ case that: HashSetCollision1[A] =>
+ val ks1 = that.ks + key
+ // Could use eq check (faster) if ListSet was guaranteed to return itself
+ if (ks1.size == that.ks.size) {
+ that
+ } else {
+ new HashSetCollision1[A](hash, ks1)
+ }
+ }
+
+ override private[immutable] def union0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int) = {
+ // switch to the Leaf version of union
+ // we can exchange the arguments because union is symmetrical
+ that.union0(this, level)
+ }
+
+ override private[immutable] def intersect0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] =
+ if (that.get0(key, hash, level)) this else null
+
+ override private[immutable] def diff0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] =
+ if (that.get0(key, hash, level)) null else this
+
override def removed0(key: A, hash: Int, level: Int): HashSet[A] =
- if (hash == this.hash && key == this.key) HashSet.empty[A] else this
+ if (hash == this.hash && key == this.key) null else this
override protected def filter0(p: A => Boolean, negate: Boolean, level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] =
if (negate ^ p(key)) this else null
@@ -200,8 +315,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
override def foreach[U](f: A => U): Unit = f(key)
}
- private[immutable] class HashSetCollision1[A](private[HashSet] val hash: Int, val ks: ListSet[A])
- extends HashSet[A] {
+ private[immutable] class HashSetCollision1[A](private[HashSet] val hash: Int, val ks: ListSet[A]) extends LeafHashSet[A] {
override def size = ks.size
@@ -220,15 +334,116 @@ object HashSet extends ImmutableSetFactory[HashSet] {
if (hash == this.hash) new HashSetCollision1(hash, ks + key)
else makeHashTrieSet(this.hash, this, hash, new HashSet1(key, hash), level)
+ override def union0(that: LeafHashSet[A], level: Int): HashSet[A] = that match {
+ case that if that.hash != this.hash =>
+ // different hash code, so there is no need to investigate further.
+ // Just create a branch node containing the two.
+ makeHashTrieSet(this.hash, this, that.hash, that, level)
+ case that: HashSet1[A] =>
+ val ks1 = ks + that.key
+ // Could use eq check (faster) if ListSet was guaranteed to return itself
+ if (ks1.size == ks.size) {
+ this
+ } else {
+ // create a new HashSetCollision with the existing hash
+ // we don't have to check for size=1 because union is never going to remove elements
+ new HashSetCollision1[A](hash, ks1)
+ }
+ case that: HashSetCollision1[A] =>
+ val ks1 = this.ks ++ that.ks
+ ks1.size match {
+ case size if size == this.ks.size =>
+ // could this check be made faster by doing an eq check?
+ // I am not sure we can rely on ListSet returning itself when all elements are already in the set,
+ // so it seems unwise to rely on it.
+ this
+ case size if size == that.ks.size =>
+ // we have to check this as well, since we don't want to create a new instance if this is a subset of that
+ that
+ case _ =>
+ // create a new HashSetCollision with the existing hash
+ // we don't have to check for size=1 because union is never going to remove elements
+ new HashSetCollision1[A](hash, ks1)
+ }
+ }
+
+ override def union0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = that match {
+ case that: LeafHashSet[A] =>
+ // switch to the simpler Tree/Leaf implementation
+ this.union0(that, level)
+ case that: HashTrieSet[A] =>
+ // switch to the simpler Tree/Leaf implementation
+ // we can swap this and that because union is symmetrical
+ that.union0(this, level)
+ case _ => this
+ }
+
+ override private[immutable] def intersect0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = {
+ // filter the keys, taking advantage of the fact that we know their hash code
+ val ks1 = ks.filter(that.get0(_, hash, level))
+ ks1.size match {
+ case 0 =>
+ // the empty set
+ null
+ case size if size == this.size =>
+ // unchanged
+ // We do this check first since even if the result is of size 1 since
+ // it is preferable to return the existing set for better structural sharing
+ this
+ case size if size == that.size =>
+ // the other set
+ // We do this check first since even if the result is of size 1 since
+ // it is preferable to return the existing set for better structural sharing
+ that
+ case 1 =>
+ // create a new HashSet1 with the hash we already know
+ new HashSet1(ks1.head, hash)
+ case _ =>
+ // create a new HashSetCollison with the hash we already know and the new keys
+ new HashSetCollision1(hash, ks1)
+ }
+ }
+
+ override private[immutable] def diff0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = {
+ val ks1 = ks.filterNot(that.get0(_, hash, level))
+ ks1.size match {
+ case 0 =>
+ // the empty set
+ null
+ case size if size == this.size =>
+ // unchanged
+ // We do this check first since even if the result is of size 1 since
+ // it is preferable to return the existing set for better structural sharing
+ this
+ case 1 =>
+ // create a new HashSet1 with the hash we already know
+ new HashSet1(ks1.head, hash)
+ case _ =>
+ // create a new HashSetCollison with the hash we already know and the new keys
+ new HashSetCollision1(hash, ks1)
+ }
+ }
+
override def removed0(key: A, hash: Int, level: Int): HashSet[A] =
if (hash == this.hash) {
val ks1 = ks - key
- if(ks1.isEmpty)
- HashSet.empty[A]
- else if(ks1.tail.isEmpty)
- new HashSet1(ks1.head, hash)
- else
- new HashSetCollision1(hash, ks1)
+ ks1.size match {
+ case 0 =>
+ // the empty set
+ null
+ case size if size == ks.size =>
+ // We do this check first since even if the result is of size 1 since
+ // it is preferable to return the existing set for better structural sharing
+ // we can not rely on ks.- returning the same instance if we subtract an element that is not in it
+ // so we need to do the size check
+ this
+ case 1 =>
+ // create a new HashSet1 with the hash we already know
+ new HashSet1(ks1.head, hash)
+ case _ =>
+ // create a new HashSetCollison with the hash we already know and the new keys
+ new HashSetCollision1(hash, ks1)
+ }
} else this
override protected def filter0(p: A => Boolean, negate: Boolean, level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = {
@@ -345,6 +560,284 @@ object HashSet extends ImmutableSetFactory[HashSet] {
}
}
+ override private[immutable] def union0(that: LeafHashSet[A], level: Int): HashSet[A] = {
+ val index = (that.hash >>> level) & 0x1f
+ val mask = (1 << index)
+ val offset = Integer.bitCount(bitmap & (mask - 1))
+ if ((bitmap & mask) != 0) {
+ val sub = elems(offset)
+ val sub1 = sub.union0(that, level + 5)
+ if (sub eq sub1) this
+ else {
+ val elems1 = new Array[HashSet[A]](elems.length)
+ Array.copy(elems, 0, elems1, 0, elems.length)
+ elems1(offset) = sub1
+ new HashTrieSet(bitmap, elems1, size + (sub1.size - sub.size))
+ }
+ } else {
+ val elems1 = new Array[HashSet[A]](elems.length + 1)
+ Array.copy(elems, 0, elems1, 0, offset)
+ elems1(offset) = that
+ Array.copy(elems, offset, elems1, offset + 1, elems.length - offset)
+ val bitmap1 = bitmap | mask
+ new HashTrieSet(bitmap1, elems1, size + that.size)
+ }
+ }
+
+ override private[immutable] def union0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = that match {
+ case that if that eq this =>
+ // shortcut for when that is this
+ // this happens often for nodes deeper in the tree, especially when that and this share a common "heritage"
+ // e.g. you have a large set A and do some small operations (adding and removing elements) to it to create B
+ // then A and B will have the vast majority of nodes in common, and this eq check will allow not even looking
+ // at these nodes.
+ this
+ case that: LeafHashSet[A] =>
+ // when that is a leaf, we can switch to the simpler Tree/Leaf implementation
+ this.union0(that, level)
+ case that: HashTrieSet[A] =>
+ val a = this.elems
+ var abm = this.bitmap
+ var ai = 0
+
+ val b = that.elems
+ var bbm = that.bitmap
+ var bi = 0
+
+ // fetch a new temporary array that is guaranteed to be big enough (32 elements)
+ var offset = offset0
+ var rs = 0
+
+ // loop as long as there are bits left in either abm or bbm
+ while ((abm | bbm) != 0) {
+ // lowest remaining bit in abm
+ val alsb = abm ^ (abm & (abm - 1))
+ // lowest remaining bit in bbm
+ val blsb = bbm ^ (bbm & (bbm - 1))
+ if (alsb == blsb) {
+ val sub1 = a(ai).union0(b(bi), level + 5, buffer, offset)
+ rs += sub1.size
+ buffer(offset) = sub1
+ offset += 1
+ // clear lowest remaining one bit in abm and increase the a index
+ abm &= ~alsb
+ ai += 1
+ // clear lowest remaining one bit in bbm and increase the b index
+ bbm &= ~blsb
+ bi += 1
+ } else if (unsignedCompare(alsb - 1, blsb - 1)) {
+ // alsb is smaller than blsb, or alsb is set and blsb is 0
+ // in any case, alsb is guaranteed to be set here!
+ val sub1 = a(ai)
+ rs += sub1.size
+ buffer(offset) = sub1
+ offset += 1
+ // clear lowest remaining one bit in abm and increase the a index
+ abm &= ~alsb
+ ai += 1
+ } else {
+ // blsb is smaller than alsb, or blsb is set and alsb is 0
+ // in any case, blsb is guaranteed to be set here!
+ val sub1 = b(bi)
+ rs += sub1.size
+ buffer(offset) = sub1
+ offset += 1
+ // clear lowest remaining one bit in bbm and increase the b index
+ bbm &= ~blsb
+ bi += 1
+ }
+ }
+ if (rs == this.size) {
+ // if the result would be identical to this, we might as well return this
+ this
+ } else if (rs == that.size) {
+ // if the result would be identical to that, we might as well return that
+ that
+ } else {
+ // we don't have to check whether the result is a leaf, since union will only make the set larger
+ // and this is not a leaf to begin with.
+ val length = offset - offset0
+ val elems = new Array[HashSet[A]](length)
+ System.arraycopy(buffer, offset0, elems, 0, length)
+ new HashTrieSet(this.bitmap | that.bitmap, elems, rs)
+ }
+ case _ => this
+ }
+
+ override private[immutable] def intersect0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = that match {
+ case that if that eq this =>
+ // shortcut for when that is this
+ // this happens often for nodes deeper in the tree, especially when that and this share a common "heritage"
+ // e.g. you have a large set A and do some small operations (adding and removing elements) to it to create B
+ // then A and B will have the vast majority of nodes in common, and this eq check will allow not even looking
+ // at these nodes!
+ this
+ case that: LeafHashSet[A] =>
+ // when that is a leaf, we can switch to the simpler Tree/Leaf implementation
+ // it is OK to swap the arguments because intersect is symmetric
+ // (we can't do this in case of diff, which is not symmetric)
+ that.intersect0(this, level, buffer, offset0)
+ case that: HashTrieSet[A] =>
+ val a = this.elems
+ var abm = this.bitmap
+ var ai = 0
+
+ val b = that.elems
+ var bbm = that.bitmap
+ var bi = 0
+
+ // if the bitmasks do not overlap, the result is definitely empty so we can abort here
+ if ((abm & bbm) == 0)
+ return null
+
+ // fetch a new temporary array that is guaranteed to be big enough (32 elements)
+ var offset = offset0
+ var rs = 0
+ var rbm = 0
+
+ // loop as long as there are bits left that are set in both abm and bbm
+ while ((abm & bbm) != 0) {
+ // highest remaining bit in abm
+ val alsb = abm ^ (abm & (abm - 1))
+ // highest remaining bit in bbm
+ val blsb = bbm ^ (bbm & (bbm - 1))
+ if (alsb == blsb) {
+ val sub1 = a(ai).intersect0(b(bi), level + 5, buffer, offset)
+ if (sub1 ne null) {
+ rs += sub1.size
+ rbm |= alsb
+ buffer(offset) = sub1
+ offset += 1
+ }
+ // clear lowest remaining one bit in abm and increase the a index
+ abm &= ~alsb;
+ ai += 1
+ // clear lowest remaining one bit in bbm and increase the b index
+ bbm &= ~blsb;
+ bi += 1
+ } else if (unsignedCompare(alsb - 1, blsb - 1)) {
+ // alsb is smaller than blsb, or alsb is set and blsb is 0
+ // in any case, alsb is guaranteed to be set here!
+ // clear lowest remaining one bit in abm and increase the a index
+ abm &= ~alsb;
+ ai += 1
+ } else {
+ // blsb is smaller than alsb, or blsb is set and alsb is 0
+ // in any case, blsb is guaranteed to be set here!
+ // clear lowest remaining one bit in bbm and increase the b index
+ bbm &= ~blsb;
+ bi += 1
+ }
+ }
+
+ if (rbm == 0) {
+ // if the result bitmap is empty, the result is the empty set
+ null
+ } else if (rs == size0) {
+ // if the result has the same number of elements as this, it must be identical to this,
+ // so we might as well return this
+ this
+ } else if (rs == that.size0) {
+ // if the result has the same number of elements as that, it must be identical to that,
+ // so we might as well return that
+ that
+ } else {
+ val length = offset - offset0
+ if (length == 1 && !buffer(offset0).isInstanceOf[HashTrieSet[A]])
+ buffer(offset0)
+ else {
+ val elems = new Array[HashSet[A]](length)
+ System.arraycopy(buffer, offset0, elems, 0, length)
+ new HashTrieSet[A](rbm, elems, rs)
+ }
+ }
+ case _ => null
+ }
+
+ override private[immutable] def diff0(that: HashSet[A], level: Int, buffer: Array[HashSet[A]], offset0: Int): HashSet[A] = that match {
+ case that if that eq this =>
+ // shortcut for when that is this
+ // this happens often for nodes deeper in the tree, especially when that and this share a common "heritage"
+ // e.g. you have a large set A and do some small operations (adding and removing elements) to it to create B
+ // then A and B will have the vast majority of nodes in common, and this eq check will allow not even looking
+ // at these nodes!
+ null
+ case that: HashSet1[A] =>
+ removed0(that.key, that.hash, level)
+ case that: HashTrieSet[A] =>
+ val a = this.elems
+ var abm = this.bitmap
+ var ai = 0
+
+ val b = that.elems
+ var bbm = that.bitmap
+ var bi = 0
+
+ // fetch a new temporary array that is guaranteed to be big enough (32 elements)
+ var offset = offset0
+ var rs = 0
+ var rbm = 0
+
+ // loop until there are no more bits in abm
+ while(abm!=0) {
+ // highest remaining bit in abm
+ val alsb = abm ^ (abm & (abm - 1))
+ // highest remaining bit in bbm
+ val blsb = bbm ^ (bbm & (bbm - 1))
+ if (alsb == blsb) {
+ val sub1 = a(ai).diff0(b(bi), level + 5, buffer, offset)
+ if (sub1 ne null) {
+ rs += sub1.size
+ rbm |= alsb
+ buffer(offset) = sub1
+ offset += 1
+ }
+ // clear lowest remaining one bit in abm and increase the a index
+ abm &= ~alsb; ai += 1
+ // clear lowest remaining one bit in bbm and increase the b index
+ bbm &= ~blsb; bi += 1
+ } else if (unsignedCompare(alsb - 1, blsb - 1)) {
+ // alsb is smaller than blsb, or alsb is set and blsb is 0
+ // in any case, alsb is guaranteed to be set here!
+ val sub1 = a(ai)
+ rs += sub1.size
+ rbm |= alsb
+ buffer(offset) = sub1; offset += 1
+ // clear lowest remaining one bit in abm and increase the a index
+ abm &= ~alsb; ai += 1
+ } else {
+ // blsb is smaller than alsb, or blsb is set and alsb is 0
+ // in any case, blsb is guaranteed to be set here!
+ // clear lowest remaining one bit in bbm and increase the b index
+ bbm &= ~blsb; bi += 1
+ }
+ }
+ if (rbm == 0) {
+ null
+ } else if (rs == this.size0) {
+ // if the result has the same number of elements as this, it must be identical to this,
+ // so we might as well return this
+ this
+ } else {
+ val length = offset - offset0
+ if (length == 1 && !buffer(offset0).isInstanceOf[HashTrieSet[A]])
+ buffer(offset0)
+ else {
+ val elems = new Array[HashSet[A]](length)
+ System.arraycopy(buffer, offset0, elems, 0, length)
+ new HashTrieSet[A](rbm, elems, rs)
+ }
+ }
+ case that: HashSetCollision1[A] =>
+ // we remove the elements using removed0 so we can use the fact that we know the hash of all elements
+ // to be removed
+ @tailrec def removeAll(s:HashSet[A], r:ListSet[A]) : HashSet[A] =
+ if(r.isEmpty || (s eq null)) s
+ else removeAll(s.removed0(r.head, that.hash, level), r.tail)
+ removeAll(this, that.ks)
+ case _ => this
+ }
+
override def removed0(key: A, hash: Int, level: Int): HashSet[A] = {
val index = (hash >>> level) & 0x1f
val mask = (1 << index)
@@ -353,7 +846,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
val sub = elems(offset)
val subNew = sub.removed0(key, hash, level + 5)
if (sub eq subNew) this
- else if (subNew.isEmpty) {
+ else if (subNew eq null) {
val bitmapNew = bitmap ^ mask
if (bitmapNew != 0) {
val elemsNew = new Array[HashSet[A]](elems.length - 1)
@@ -367,7 +860,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
else
new HashTrieSet(bitmapNew, elemsNew, sizeNew)
} else
- HashSet.empty[A]
+ null
} else {
val elemsNew = new Array[HashSet[A]](elems.length)
Array.copy(elems, 0, elemsNew, 0, elems.length)
@@ -526,6 +1019,10 @@ object HashSet extends ImmutableSetFactory[HashSet] {
result
}
+ // unsigned comparison
+ @inline private[this] def unsignedCompare(i: Int, j: Int) =
+ (i < j) ^ (i < 0) ^ (j < 0)
+
@SerialVersionUID(2L) private class SerializationProxy[A,B](@transient private var orig: HashSet[A]) extends Serializable {
private def writeObject(out: java.io.ObjectOutputStream) {
val s = orig.size
diff --git a/src/library/scala/collection/immutable/NumericRange.scala b/src/library/scala/collection/immutable/NumericRange.scala
index 249d76584d..f1ac161e9a 100644
--- a/src/library/scala/collection/immutable/NumericRange.scala
+++ b/src/library/scala/collection/immutable/NumericRange.scala
@@ -241,28 +241,79 @@ object NumericRange {
else if (start == end) if (isInclusive) 1 else 0
else if (upward != posStep) 0
else {
- val diff = num.minus(end, start)
- val jumps = num.toLong(num.quot(diff, step))
- val remainder = num.rem(diff, step)
- val longCount = jumps + (
- if (!isInclusive && zero == remainder) 0 else 1
- )
-
- /* The edge cases keep coming. Since e.g.
- * Long.MaxValue + 1 == Long.MinValue
- * we do some more improbable seeming checks lest
- * overflow turn up as an empty range.
+ /* We have to be frightfully paranoid about running out of range.
+ * We also can't assume that the numbers will fit in a Long.
+ * We will assume that if a > 0, -a can be represented, and if
+ * a < 0, -a+1 can be represented. We also assume that if we
+ * can't fit in Int, we can represent 2*Int.MaxValue+3 (at least).
+ * And we assume that numbers wrap rather than cap when they overflow.
*/
- // The second condition contradicts an empty result.
- val isOverflow = longCount == 0 && num.lt(num.plus(start, step), end) == upward
-
- if (longCount > scala.Int.MaxValue || longCount < 0L || isOverflow) {
- val word = if (isInclusive) "to" else "until"
- val descr = List(start, word, end, "by", step) mkString " "
-
- throw new IllegalArgumentException(descr + ": seqs cannot contain more than Int.MaxValue elements.")
+ // Check whether we can short-circuit by deferring to Int range.
+ val startint = num.toInt(start)
+ if (start == num.fromInt(startint)) {
+ val endint = num.toInt(end)
+ if (end == num.fromInt(endint)) {
+ val stepint = num.toInt(step)
+ if (step == num.fromInt(stepint)) {
+ return {
+ if (isInclusive) Range.inclusive(startint, endint, stepint).length
+ else Range (startint, endint, stepint).length
+ }
+ }
+ }
+ }
+ // If we reach this point, deferring to Int failed.
+ // Numbers may be big.
+ val one = num.one
+ val limit = num.fromInt(Int.MaxValue)
+ def check(t: T): T =
+ if (num.gt(t, limit)) throw new IllegalArgumentException("More than Int.MaxValue elements.")
+ else t
+ // If the range crosses zero, it might overflow when subtracted
+ val startside = num.signum(start)
+ val endside = num.signum(end)
+ num.toInt{
+ if (startside*endside >= 0) {
+ // We're sure we can subtract these numbers.
+ // Note that we do not use .rem because of different conventions for Long and BigInt
+ val diff = num.minus(end, start)
+ val quotient = check(num.quot(diff, step))
+ val remainder = num.minus(diff, num.times(quotient, step))
+ if (!isInclusive && zero == remainder) quotient else check(num.plus(quotient, one))
+ }
+ else {
+ // We might not even be able to subtract these numbers.
+ // Jump in three pieces:
+ // * start to -1 or 1, whichever is closer (waypointA)
+ // * one step, which will take us at least to 0 (ends at waypointB)
+ // * there to the end
+ val negone = num.fromInt(-1)
+ val startlim = if (posStep) negone else one
+ val startdiff = num.minus(startlim, start)
+ val startq = check(num.quot(startdiff, step))
+ val waypointA = if (startq == zero) start else num.plus(start, num.times(startq, step))
+ val waypointB = num.plus(waypointA, step)
+ check {
+ if (num.lt(waypointB, end) != upward) {
+ // No last piece
+ if (isInclusive && waypointB == end) num.plus(startq, num.fromInt(2))
+ else num.plus(startq, one)
+ }
+ else {
+ // There is a last piece
+ val enddiff = num.minus(end,waypointB)
+ val endq = check(num.quot(enddiff, step))
+ val last = if (endq == zero) waypointB else num.plus(waypointB, num.times(endq, step))
+ // Now we have to tally up all the pieces
+ // 1 for the initial value
+ // startq steps to waypointA
+ // 1 step to waypointB
+ // endq steps to the end (one less if !isInclusive and last==end)
+ num.plus(startq, num.plus(endq, if (!isInclusive && last==end) one else num.fromInt(2)))
+ }
+ }
+ }
}
- longCount.toInt
}
}
diff --git a/src/reflect/scala/reflect/macros/Aliases.scala b/src/reflect/scala/reflect/macros/Aliases.scala
index cc92cd10c7..d2b878d081 100644
--- a/src/reflect/scala/reflect/macros/Aliases.scala
+++ b/src/reflect/scala/reflect/macros/Aliases.scala
@@ -40,10 +40,16 @@ trait Aliases {
/** The type of tree modifiers. */
type Modifiers = universe.Modifiers
- /** The type of compilation runs. */
+ /** The type of compilation runs.
+ * @see [[scala.reflect.macros.Enclosures]]
+ */
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
type Run = universe.Run
- /** The type of compilation units. */
+ /** The type of compilation units.
+ * @see [[scala.reflect.macros.Enclosures]]
+ */
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
type CompilationUnit = universe.CompilationUnit
/** Expr wraps an abstract syntax tree and tags it with its type. */
diff --git a/src/reflect/scala/reflect/macros/Enclosures.scala b/src/reflect/scala/reflect/macros/Enclosures.scala
index 5f248d25d3..1ced2e54c6 100644
--- a/src/reflect/scala/reflect/macros/Enclosures.scala
+++ b/src/reflect/scala/reflect/macros/Enclosures.scala
@@ -8,9 +8,21 @@ import scala.language.existentials // SI-6541
* <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span>
*
* A slice of [[scala.reflect.macros.blackbox.Context the Scala macros context]] that exposes
- * enclosing trees (method, class, compilation unit and currently compiled application),
+ * enclosing trees (method, class, compilation unit and currently compiled macro application),
* the enclosing position of the macro expansion, as well as macros and implicits
* that are currently in-flight.
+ *
+ * Starting from Scala 2.11.0, the APIs to get the trees enclosing by the current macro application are deprecated,
+ * and the reasons for that are two-fold. Firstly, we would like to move towards the philosophy of locally-expanded macros,
+ * as it has proven to be important for understanding of code. Secondly, within the current architecture of scalac,
+ * we are unable to have c.enclosingTree-style APIs working robustly. Required changes to the typechecker would greatly
+ * exceed the effort that we would like to expend on this feature given the existence of more pressing concerns at the moment.
+ * This is somewhat aligned with the overall evolution of macros during the 2.11 development cycle, where we played with
+ * `c.introduceTopLevel` and `c.introduceMember`, but at the end of the day decided to reject them.
+ *
+ * If you're relying on the now deprecated APIs, consider reformulating your macros in terms of completely local expansion
+ * and/or joining a discussion of a somewhat related potential language feature at [[https://groups.google.com/forum/#!topic/scala-debate/f4CLmYShX6Q]].
+ * We also welcome questions and suggestions on our mailing lists, where we would be happy to further discuss this matter.
*/
trait Enclosures {
self: blackbox.Context =>
@@ -40,46 +52,62 @@ trait Enclosures {
def enclosingPosition: Position
/** Tree that corresponds to the enclosing method, or EmptyTree if not applicable.
+ * @see [[scala.reflect.macros.Enclosures]]
*/
- @deprecated("Use enclosingDef instead, but be wary of changes in semantics", "2.10.1")
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
def enclosingMethod: Tree
/** Tree that corresponds to the enclosing class, or EmptyTree if not applicable.
+ * @see [[scala.reflect.macros.Enclosures]]
*/
- @deprecated("Use enclosingImpl instead, but be wary of changes in semantics", "2.10.1")
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
def enclosingClass: Tree
/** Tree that corresponds to the enclosing DefDef tree.
* Throws `EnclosureException` if there's no such enclosing tree.
+ * @see [[scala.reflect.macros.Enclosures]]
*/
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
def enclosingDef: universe.DefDef
/** Tree that corresponds to the enclosing Template tree.
* Throws `EnclosureException` if there's no such enclosing tree.
+ * @see [[scala.reflect.macros.Enclosures]]
*/
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
def enclosingTemplate: universe.Template
/** Tree that corresponds to the enclosing ImplDef tree (i.e. either ClassDef or ModuleDef).
* Throws `EnclosureException` if there's no such enclosing tree.
+ * @see [[scala.reflect.macros.Enclosures]]
*/
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
def enclosingImpl: universe.ImplDef
/** Tree that corresponds to the enclosing PackageDef tree.
* Throws `EnclosureException` if there's no such enclosing tree.
+ * @see [[scala.reflect.macros.Enclosures]]
*/
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
def enclosingPackage: universe.PackageDef
/** Compilation unit that contains this macro application.
+ * @see [[scala.reflect.macros.Enclosures]]
*/
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
def enclosingUnit: CompilationUnit
/** Compilation run that contains this macro application.
+ * @see [[scala.reflect.macros.Enclosures]]
*/
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
def enclosingRun: Run
/** Indicates than one of the enclosure methods failed to find a tree
* of required type among enclosing trees.
+ * @see [[scala.reflect.macros.Enclosures]]
*/
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
case class EnclosureException(expected: Class[_], enclosingTrees: List[Tree])
extends Exception(s"Couldn't find a tree of type $expected among enclosing trees $enclosingTrees")
}
diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala
index 297bac2999..d84e6aa737 100644
--- a/src/reflect/scala/reflect/macros/Universe.scala
+++ b/src/reflect/scala/reflect/macros/Universe.scala
@@ -197,34 +197,44 @@ abstract class Universe extends scala.reflect.api.Universe {
def capturedVariableType(vble: Symbol): Type
/** The type of compilation runs.
+ * @see [[scala.reflect.macros.Enclosures]]
* @template
* @group Macros
*/
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
type Run <: RunContextApi
/** Compilation run uniquely identifies current invocation of the compiler
* (e.g. can be used to implement per-run caches for macros) and provides access to units of work
* of the invocation (currently processed unit of work and the list of all units).
+ * @see [[scala.reflect.macros.Enclosures]]
* @group API
*/
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
trait RunContextApi {
/** Currently processed unit of work (a real or a virtual file). */
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
def currentUnit: CompilationUnit
/** All units of work comprising this compilation run. */
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
def units: Iterator[CompilationUnit]
}
/** The type of compilation units.
+ * @see [[scala.reflect.macros.Enclosures]]
* @template
* @group Macros
*/
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
type CompilationUnit <: CompilationUnitContextApi
/** Compilation unit describes a unit of work of the compilation run.
* It provides such information as file name, textual representation of the unit and the underlying AST.
+ * @see [[scala.reflect.macros.Enclosures]]
* @group API
*/
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
trait CompilationUnitContextApi {
/** Source file corresponding to this compilation unit.
*
@@ -235,9 +245,11 @@ abstract class Universe extends scala.reflect.api.Universe {
* It should not be used unless you know what you are doing. In subsequent releases, this API will be refined
* and exposed as a part of scala.reflect.api.
*/
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
def source: scala.reflect.internal.util.SourceFile
/** The AST that corresponds to this compilation unit. */
+ @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0")
def body: Tree
}
}
diff --git a/test/files/neg/dotless-targs.check b/test/files/neg/dotless-targs.check
new file mode 100644
index 0000000000..4aab939f61
--- /dev/null
+++ b/test/files/neg/dotless-targs.check
@@ -0,0 +1,4 @@
+dotless-targs.scala:2: error: type application is not allowed for postfix operators
+ def f1 = "f1" isInstanceOf[String] // not ok
+ ^
+one error found
diff --git a/test/files/neg/dotless-targs.scala b/test/files/neg/dotless-targs.scala
new file mode 100644
index 0000000000..eff63cbec4
--- /dev/null
+++ b/test/files/neg/dotless-targs.scala
@@ -0,0 +1,5 @@
+class A {
+ def f1 = "f1" isInstanceOf[String] // not ok
+ def f2 = "f2".isInstanceOf[String] // ok
+ def f3 = "f3" toList // ok
+}
diff --git a/test/files/neg/t8157.check b/test/files/neg/t8157.check
new file mode 100644
index 0000000000..9a21a49a07
--- /dev/null
+++ b/test/files/neg/t8157.check
@@ -0,0 +1,4 @@
+t8157.scala:1: error: in object Test, multiple overloaded alternatives of method foo define default arguments.
+object Test {
+ ^
+one error found
diff --git a/test/files/neg/t8157.scala b/test/files/neg/t8157.scala
new file mode 100644
index 0000000000..462d4fa3f1
--- /dev/null
+++ b/test/files/neg/t8157.scala
@@ -0,0 +1,4 @@
+object Test {
+ def foo(printer: Any, question: => String, show: Boolean = false)(op: => Any): Any = ???
+ def foo[T](question: => String, show: Boolean)(op: => Any = ()): Any = ???
+}
diff --git a/test/files/pos/bcode_throw_null/TN.scala b/test/files/pos/bcode_throw_null/TN.scala
new file mode 100644
index 0000000000..ed38b59bae
--- /dev/null
+++ b/test/files/pos/bcode_throw_null/TN.scala
@@ -0,0 +1,7 @@
+object TN {
+
+ def pre1(b: Boolean) {
+ println(if (b) 1 else throw null)
+ }
+
+}
diff --git a/test/files/pos/dotless-targs.scala b/test/files/pos/dotless-targs.scala
new file mode 100644
index 0000000000..8c0e244e4e
--- /dev/null
+++ b/test/files/pos/dotless-targs.scala
@@ -0,0 +1,9 @@
+class A {
+ def fn1 = List apply 1
+ def fn2 = List apply[Int] 2
+
+ def g1: Char = "g1" toList 0
+ def g2: Char = "g2" apply 1
+
+ def h1 = List apply[List[Int]] (List(1), List(2)) mapConserve[List[Any]] (x => x)
+}
diff --git a/test/files/pos/overzealous-assert-genbcode.scala b/test/files/pos/overzealous-assert-genbcode.scala
new file mode 100644
index 0000000000..ddd70b0c44
--- /dev/null
+++ b/test/files/pos/overzealous-assert-genbcode.scala
@@ -0,0 +1,10 @@
+object Test {
+
+ def main(args: Array[String]) {
+ args(0) match {
+ case a: String => while(a == null) {}
+ }
+ }
+
+}
+
diff --git a/test/files/run/t6253a.scala b/test/files/run/t6253a.scala
new file mode 100644
index 0000000000..efa3230df6
--- /dev/null
+++ b/test/files/run/t6253a.scala
@@ -0,0 +1,64 @@
+import scala.collection.immutable.HashSet
+
+object Test extends App {
+
+ var hashCount = 0
+
+ /**
+ * A key that produces lots of hash collisions, to exercise the part of the code that deals with those
+ */
+ case class Collision(value: Int) {
+
+ override def hashCode = {
+ // we do not check hash counts for Collision keys because ListSet.++ uses a mutable hashset internally,
+ // so when we have hash collisions, union will call key.hashCode.
+ // hashCount += 1
+ value / 5
+ }
+ }
+
+ /**
+ * A key that is identical to int other than that it counts hashCode invocations
+ */
+ case class HashCounter(value: Int) {
+
+ override def hashCode = {
+ hashCount += 1
+ value
+ }
+ }
+
+ def testUnion[T](sizes: Seq[Int], offsets: Seq[Double], keyType: String, mkKey: Int => T) {
+ for {
+ i <- sizes
+ o <- offsets
+ } {
+ val e = HashSet.empty[T]
+ val j = (i * o).toInt
+ // create two sets of size i with overlap o
+ val a = e ++ (0 until i).map(mkKey)
+ require(a.size == i, s"Building HashSet of size $i failed. Key type $keyType.")
+ val b = e ++ (j until (i + j)).map(mkKey)
+ require(b.size == i, s"Building HashSet of size $i failed. Key type $keyType.")
+ val as = e ++ (0 until j).map(mkKey)
+ require(as.size == j, s"Building HashSet of size $j failed. Key type $keyType.")
+ val hashCount0 = hashCount
+ val u = a union b
+ require(hashCount == hashCount0, s"key.hashCode should not be called, but has been called ${hashCount - hashCount0} times. Key type $keyType.")
+ require(u == (a union scala.collection.mutable.HashSet(b.toSeq: _*)), s"Operation must still work for other sets!")
+ require(u.size == i + j, s"Expected size ${i+j}. Real size ${u.size}. Key type $keyType.")
+ for (x <- 0 until i + j)
+ require(u.contains(mkKey(x)), s"Key type $keyType. Set (0 until ${i + j}) should contain $x but does not.")
+ val a_as = a union as
+ val as_a = as union a
+ require((a_as eq a) || (a_as eq as), s"No structural sharing in a union as. Key type $keyType, a=(0 until $i) as=(0 until $j)")
+ require((as_a eq a) || (as_a eq as), s"No structural sharing in as union a. Key type $keyType, a=(0 until $i) as=(0 until $j)")
+ }
+ }
+
+ val sizes = Seq(1, 10, 100, 1000, 10000, 100000)
+ val offsets = Seq(0.0, 0.25, 0.5, 0.75, 1.0)
+ testUnion(sizes, offsets, "int", identity[Int])
+ testUnion(sizes, offsets, "hashcounter", HashCounter.apply)
+ testUnion(sizes, offsets, "collision", Collision.apply)
+}
diff --git a/test/files/run/t6253b.scala b/test/files/run/t6253b.scala
new file mode 100644
index 0000000000..9cbfefd49e
--- /dev/null
+++ b/test/files/run/t6253b.scala
@@ -0,0 +1,62 @@
+import scala.collection.immutable.HashSet
+
+object Test extends App {
+
+ var hashCount = 0
+
+ /**
+ * A key that produces lots of hash collisions, to exercise the part of the code that deals with those
+ */
+ case class Collision(value: Int) {
+
+ override def hashCode = {
+ hashCount += 1
+ value / 5
+ }
+ }
+
+ /**
+ * A key that is identical to int other than that it counts hashCode invocations
+ */
+ case class HashCounter(value: Int) {
+
+ override def hashCode = {
+ hashCount += 1
+ value
+ }
+ }
+
+ def testIntersect[T](sizes: Seq[Int], offsets: Seq[Double], keyType: String, mkKey: Int => T) {
+ for {
+ i <- sizes
+ o <- offsets
+ } {
+ val e = HashSet.empty[T]
+ val j = (i * o).toInt
+ // create two sets of size i with overlap o
+ val a = e ++ (0 until i).map(mkKey)
+ require(a.size == i, s"Building HashSet of size $i failed. Key type $keyType.")
+ val b = e ++ (j until (i + j)).map(mkKey)
+ require(b.size == i, s"Building HashSet of size $i failed. Key type $keyType.")
+ val as = e ++ (0 until j).map(mkKey)
+ require(as.size == j, s"Building HashSet of size $j failed. Key type $keyType.")
+ val hashCount0 = hashCount
+ val u = a intersect b
+ require(hashCount == hashCount0, s"key.hashCode should not be called, but has been called ${hashCount - hashCount0} times. Key type $keyType.")
+ require(u == (a intersect scala.collection.mutable.HashSet(b.toSeq: _*)), s"Operation must still work for other sets!")
+ require(u.size == i - j, s"Expected size ${i + j}. Real size ${u.size}. Key type $keyType.")
+ for (x <- j until i)
+ require(u.contains(mkKey(x)), s"Key type $keyType. Set (0 until ${i + j}) should contain $x but does not.")
+ val a_as = a intersect as
+ val as_a = as intersect a
+ require((a_as eq as) || (a_as eq a), s"No structural sharing in a intersect as. Key type $keyType, a=(0 until $i) as=(0 until $j)")
+ require((as_a eq as) || (as_a eq a), s"No structural sharing in as intersect a. Key type $keyType, a=(0 until $i) as=(0 until $j)")
+ }
+ }
+
+ val sizes = Seq(1, 10, 100, 1000, 10000, 100000)
+ val offsets = Seq(0.0, 0.25, 0.5, 0.75, 1.0)
+ testIntersect(sizes, offsets, "int", identity[Int])
+ testIntersect(sizes, offsets, "hashcounter", HashCounter.apply)
+ testIntersect(sizes, offsets, "collision", Collision.apply)
+}
diff --git a/test/files/run/t6253c.scala b/test/files/run/t6253c.scala
new file mode 100644
index 0000000000..71dfe1473e
--- /dev/null
+++ b/test/files/run/t6253c.scala
@@ -0,0 +1,63 @@
+import scala.collection.immutable.HashSet
+
+object Test extends App {
+
+ var hashCount = 0
+
+ /**
+ * A key that produces lots of hash collisions, to exercise the part of the code that deals with those
+ */
+ case class Collision(value: Int) {
+
+ override def hashCode = {
+ hashCount += 1
+ value / 5
+ }
+ }
+
+ /**
+ * A key that is identical to int other than that it counts hashCode invocations
+ */
+ case class HashCounter(value: Int) {
+
+ override def hashCode = {
+ hashCount += 1
+ value
+ }
+ }
+
+ def testDiff[T](sizes: Seq[Int], offsets: Seq[Double], keyType: String, mkKey: Int => T) {
+ for {
+ i <- sizes
+ o <- offsets
+ } {
+ val e = HashSet.empty[T]
+ val j = (i * o).toInt
+ // create two sets of size i with overlap o
+ val a = e ++ (0 until i).map(mkKey)
+ require(a.size == i, s"Building HashSet of size $i failed. Key type $keyType.")
+ val b = e ++ (j until (i + j)).map(mkKey)
+ require(b.size == i, s"Building HashSet of size $i failed. Key type $keyType.")
+ val as = e ++ (0 until j).map(mkKey)
+ require(as.size == j, s"Building HashSet of size $j failed. Key type $keyType.")
+ val hashCount0 = hashCount
+ val u = a diff b
+ require(hashCount == hashCount0, s"key.hashCode should not be called, but has been called ${hashCount - hashCount0} times. Key type $keyType.")
+ require(u == (a diff scala.collection.mutable.HashSet(b.toSeq: _*)), s"Operation must still work for other sets!")
+ require(u.size == j, s"Expected size $j. Real size ${u.size}. Key type $keyType.")
+ for (x <- 0 until j)
+ require(u.contains(mkKey(x)), s"Key type $keyType. Set (0 until ${i + j}) should contain $x but does not.")
+ require((as intersect b).isEmpty)
+ val b_as = b diff as
+ val as_b = as diff b
+ require((b_as eq b) || (b_as eq as), s"No structural sharing in b diff as. Key type $keyType, b=($j until ${i + j}) as=(0 until $j)")
+ require((as_b eq b) || (as_b eq as), s"No structural sharing in as diff b. Key type $keyType, b=($j until ${i + j}) as=(0 until $j)")
+ }
+ }
+
+ val sizes = Seq(1, 10, 100, 1000, 10000, 100000)
+ val offsets = Seq(0.0, 0.25, 0.5, 0.75, 1.0)
+ testDiff(sizes, offsets, "int", identity[Int])
+ testDiff(sizes, offsets, "hashCounter", HashCounter.apply)
+ testDiff(sizes, offsets, "collision", Collision.apply)
+}
diff --git a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
index 6fb05ff9a4..38fbfa9f7f 100644
--- a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
@@ -224,4 +224,9 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") {
property("SI-8009") = test {
q"`foo`".asInstanceOf[reflect.internal.SymbolTable#Ident].isBackquoted
}
+
+ property("SI-8148") = test {
+ val q"($a, $b) => $_" = q"_ + _"
+ assert(a.name != b.name)
+ }
}
diff --git a/test/junit/scala/collection/NumericRangeTest.scala b/test/junit/scala/collection/NumericRangeTest.scala
new file mode 100644
index 0000000000..0260723b9d
--- /dev/null
+++ b/test/junit/scala/collection/NumericRangeTest.scala
@@ -0,0 +1,123 @@
+package scala.collection.immutable
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+import scala.math._
+import scala.util._
+
+/* Tests various maps by making sure they all agree on the same answers. */
+@RunWith(classOf[JUnit4])
+class RangeConsistencyTest {
+ def r2nr[T: Integral](
+ r: Range, puff: T, stride: T, check: (T,T) => Boolean, bi: T => BigInt
+ ): List[(BigInt,Try[Int])] = {
+ val num = implicitly[Integral[T]]
+ import num._
+ val one = num.one
+
+ if (!check(puff, fromInt(r.start))) return Nil
+ val start = puff * fromInt(r.start)
+ val sp1 = start + one
+ val sn1 = start - one
+
+ if (!check(puff, fromInt(r.end))) return Nil
+ val end = puff * fromInt(r.end)
+ val ep1 = end + one
+ val en1 = end - one
+
+ if (!check(stride, fromInt(r.step))) return Nil
+ val step = stride * fromInt(r.step)
+
+ def NR(s: T, e: T, i: T) = {
+ val delta = (bi(e) - bi(s)).abs - (if (r.isInclusive) 0 else 1)
+ val n = if (r.length == 0) BigInt(0) else delta / bi(i).abs + 1
+ if (r.isInclusive) {
+ (n, Try(NumericRange.inclusive(s,e,i).length))
+ }
+ else {
+ (n, Try(NumericRange(s,e,i).length))
+ }
+ }
+
+ List(NR(start, end, step)) :::
+ (if (sn1 < start) List(NR(sn1, end, step)) else Nil) :::
+ (if (start < sp1) List(NR(sp1, end, step)) else Nil) :::
+ (if (en1 < end) List(NR(start, en1, step)) else Nil) :::
+ (if (end < ep1) List(NR(start, ep1, step)) else Nil)
+ }
+
+ // Motivated by SI-4370: Wrong result for Long.MinValue to Long.MaxValue by Int.MaxValue
+ @Test
+ def rangeChurnTest() {
+ val rn = new Random(4370)
+ for (i <- 0 to 10000) { control.Breaks.breakable {
+ val start = rn.nextInt
+ val end = rn.nextInt
+ val step = rn.nextInt(4) match {
+ case 0 => 1
+ case 1 => -1
+ case 2 => (rn.nextInt(11)+2)*(2*rn.nextInt(2)+1)
+ case 3 => var x = rn.nextInt; while (x==0) x = rn.nextInt; x
+ }
+ val r = if (rn.nextBoolean) Range.inclusive(start, end, step) else Range(start, end, step)
+
+ try { r.length }
+ catch { case iae: IllegalArgumentException => control.Breaks.break }
+
+ val lpuff = rn.nextInt(4) match {
+ case 0 => 1L
+ case 1 => rn.nextInt(11)+2L
+ case 2 => 1L << rn.nextInt(60)
+ case 3 => math.max(1L, math.abs(rn.nextLong))
+ }
+ val lstride = rn.nextInt(4) match {
+ case 0 => lpuff
+ case 1 => 1L
+ case 2 => 1L << rn.nextInt(60)
+ case 3 => math.max(1L, math.abs(rn.nextLong))
+ }
+ val lr = r2nr[Long](
+ r, lpuff, lstride,
+ (a,b) => { val x = BigInt(a)*BigInt(b); x.isValidLong },
+ x => BigInt(x)
+ )
+
+ lr.foreach{ case (n,t) => assert(
+ t match {
+ case Failure(_) => n > Int.MaxValue
+ case Success(m) => n == m
+ },
+ (r.start, r.end, r.step, r.isInclusive, lpuff, lstride, n, t)
+ )}
+
+ val bipuff = rn.nextInt(3) match {
+ case 0 => BigInt(1)
+ case 1 => BigInt(rn.nextLong) + Long.MaxValue + 2
+ case 2 => BigInt("1" + "0"*(rn.nextInt(100)+1))
+ }
+ val bistride = rn.nextInt(3) match {
+ case 0 => bipuff
+ case 1 => BigInt(1)
+ case 2 => BigInt("1" + "0"*(rn.nextInt(100)+1))
+ }
+ val bir = r2nr[BigInt](r, bipuff, bistride, (a,b) => true, identity)
+
+ bir.foreach{ case (n,t) => assert(
+ t match {
+ case Failure(_) => n > Int.MaxValue
+ case Success(m) => n == m
+ },
+ (r.start, r.end, r.step, r.isInclusive, bipuff, bistride, n, t)
+ )}
+ }}
+ }
+
+ @Test
+ def testSI4370() { assert{
+ Try((Long.MinValue to Long.MaxValue by Int.MaxValue).length) match {
+ case Failure(iae: IllegalArgumentException) => true
+ case _ => false
+ }
+ }}
+}