summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland <rk@rkuhn.info>2012-09-12 14:28:39 +0200
committerRoland <rk@rkuhn.info>2012-09-12 14:28:39 +0200
commit13ff968b9d273e03bfa226ca1ec52949391a6b68 (patch)
tree51e64bff6fb38fa212b7e187ee4f0a02be1e3e23
parent300803606ebca352955e945cf468a0c2bfc83b9c (diff)
parentd9a4e94f8716b810e8122c6494b1718410238668 (diff)
downloadscala-13ff968b9d273e03bfa226ca1ec52949391a6b68.tar.gz
scala-13ff968b9d273e03bfa226ca1ec52949391a6b68.tar.bz2
scala-13ff968b9d273e03bfa226ca1ec52949391a6b68.zip
Merge remote-tracking branch 'origin/2.10.x' into fix-duration-issues-RK
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala5
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala55
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala8
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala27
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala21
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala5
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala243
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala13
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala20
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala18
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala16
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala15
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala49
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala27
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala38
-rw-r--r--src/library/scala/collection/GenIterableViewLike.scala1
-rw-r--r--src/library/scala/concurrent/Awaitable.scala23
-rw-r--r--src/library/scala/concurrent/BlockContext.scala3
-rw-r--r--src/library/scala/concurrent/ExecutionContext.scala1
-rw-r--r--src/library/scala/concurrent/Future.scala1
-rw-r--r--src/library/scala/concurrent/impl/ExecutionContextImpl.scala1
-rw-r--r--src/library/scala/concurrent/impl/Promise.scala43
-rw-r--r--src/library/scala/concurrent/package.scala33
-rw-r--r--src/library/scala/deprecatedInheritance.scala22
-rw-r--r--src/library/scala/deprecatedOverriding.scala21
-rw-r--r--src/library/scala/math/BigDecimal.scala1
-rw-r--r--src/library/scala/math/BigInt.scala1
-rw-r--r--src/library/scala/reflect/ClassTag.scala64
-rw-r--r--src/library/scala/reflect/Manifest.scala19
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala29
-rw-r--r--src/library/scala/util/Try.scala63
-rw-r--r--src/partest/scala/tools/partest/nest/RunnerManager.scala4
-rw-r--r--src/reflect/scala/reflect/api/Symbols.scala12
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Names.scala12
-rw-r--r--src/reflect/scala/reflect/internal/SymbolTable.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala89
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala25
-rw-r--r--test/files/jvm/scala-concurrent-tck.scala29
-rw-r--r--test/files/neg/override.check2
-rwxr-xr-xtest/files/neg/override.scala2
-rw-r--r--test/files/neg/t5031.check6
-rw-r--r--test/files/neg/t5031b.check5
-rw-r--r--test/files/neg/t5031b/a.scala3
-rw-r--r--test/files/neg/t5031b/b.scala3
-rw-r--r--test/files/neg/t6162-inheritance.check10
-rw-r--r--test/files/neg/t6162-inheritance.flags1
-rw-r--r--test/files/neg/t6162-inheritance.scala19
-rw-r--r--test/files/neg/t6162-overriding.check7
-rw-r--r--test/files/neg/t6162-overriding.flags1
-rw-r--r--test/files/neg/t6162-overriding.scala17
-rw-r--r--test/files/neg/t6258.check16
-rw-r--r--test/files/neg/t6258.scala25
-rw-r--r--test/files/neg/t6276.check19
-rw-r--r--test/files/neg/t6276.flags1
-rw-r--r--test/files/neg/t6276.scala44
-rw-r--r--test/files/neg/t6335.check9
-rw-r--r--test/files/neg/t6335.scala7
-rw-r--r--test/files/pos/t6278-synth-def.scala30
-rw-r--r--test/files/pos/t6335.scala25
-rw-r--r--test/files/run/classtags_core.check30
-rw-r--r--test/files/run/classtags_multi.check10
-rw-r--r--test/files/run/compiler-asSeenFrom.check12
-rw-r--r--test/files/run/getClassTest-valueClass.check2
-rw-r--r--test/files/run/getClassTest-valueClass.scala10
-rw-r--r--test/files/run/interop_classtags_are_classmanifests.check6
-rw-r--r--test/files/run/macro-expand-tparams-implicit.check2
-rw-r--r--test/files/run/macro-expand-tparams-prefix-a.check2
-rw-r--r--test/files/run/macro-expand-tparams-prefix-b.check2
-rw-r--r--test/files/run/macro-expand-tparams-prefix-c1.check2
-rw-r--r--test/files/run/macro-expand-tparams-prefix-c2.check2
-rw-r--r--test/files/run/macro-undetparams-macroitself.check2
-rw-r--r--test/files/run/t5881.check4
-rw-r--r--test/files/run/t6246.check90
-rw-r--r--test/files/run/t6246.scala26
-rw-r--r--test/files/run/t6271.scala32
-rw-r--r--test/files/run/t6318_derived.check3
-rw-r--r--test/files/run/t6318_derived.scala15
-rw-r--r--test/files/run/t6318_primitives.check36
-rw-r--r--test/files/run/t6318_primitives.scala71
-rw-r--r--test/files/run/t6327.check4
-rw-r--r--test/files/run/t6327.scala22
-rw-r--r--test/files/run/t6333.scala29
-rw-r--r--test/files/run/valueclasses-classtag-basic.check2
-rw-r--r--test/files/run/valueclasses-classtag-existential.check2
-rw-r--r--test/files/run/valueclasses-classtag-generic.check2
-rw-r--r--test/files/run/virtpatmat_typetag.check20
-rw-r--r--test/flaky/pos/t2868.cmds (renamed from test/files/pos/t2868.cmds)0
-rw-r--r--test/flaky/pos/t2868/Jann.java (renamed from test/files/pos/t2868/Jann.java)0
-rw-r--r--test/flaky/pos/t2868/Nest.java (renamed from test/files/pos/t2868/Nest.java)0
-rw-r--r--test/flaky/pos/t2868/pick_1.scala (renamed from test/files/pos/t2868/pick_1.scala)0
-rw-r--r--test/flaky/pos/t2868/t2868_src_2.scala (renamed from test/files/pos/t2868/t2868_src_2.scala)0
101 files changed, 1292 insertions, 506 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 98a8359f89..d101337087 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -266,9 +266,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
log("Running operation '%s' after every phase.\n".format(msg) + describeAfterEveryPhase(op))
}
- def shouldLogAtThisPhase = (
- (settings.log.isSetByUser)
- && ((settings.log containsPhase globalPhase) || (settings.log containsPhase phase))
+ override def shouldLogAtThisPhase = settings.log.isSetByUser && (
+ (settings.log containsPhase globalPhase) || (settings.log containsPhase phase)
)
// Over 200 closure objects are eliminated by inlining this.
@inline final def log(msg: => AnyRef) {
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 085ce82025..bd5c9b2f68 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -48,12 +48,12 @@ trait Trees extends reflect.internal.Trees { self: Global =>
override def isType = definition.isType
}
- /** Array selection <qualifier> . <name> only used during erasure */
+ /** Array selection `<qualifier> . <name>` only used during erasure */
case class SelectFromArray(qualifier: Tree, name: Name, erasure: Type)
extends RefTree with TermTree
- /** Derived value class injection (equivalent to: new C(arg) after easure); only used during erasure
- * The class C is stored as the symbol of the tree node.
+ /** Derived value class injection (equivalent to: `new C(arg)` after erasure); only used during erasure.
+ * The class `C` is stored as a tree attachment.
*/
case class InjectDerivedValue(arg: Tree)
extends SymTree
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 739aa2b184..24662e2ac3 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -128,7 +128,6 @@ abstract class GenICode extends SubComponent {
if (staticfield != NoSymbol) {
// in companion object accessors to @static fields, we access the static field directly
val hostClass = m.symbol.owner.companionClass
-
if (m.symbol.isGetter) {
ctx1.bb.emit(LOAD_FIELD(staticfield, true) setHostClass hostClass, tree.pos)
ctx1.bb.closeWith(RETURN(m.returnType))
@@ -662,16 +661,16 @@ abstract class GenICode extends SubComponent {
} else {
val sym = tree.symbol
val local = ctx.method.addLocal(new Local(sym, toTypeKind(sym.info), false))
-
+
if (rhs == EmptyTree) {
debuglog("Uninitialized variable " + tree + " at: " + (tree.pos));
ctx.bb.emit(getZeroOf(local.kind))
}
-
+
var ctx1 = ctx
if (rhs != EmptyTree)
ctx1 = genLoad(rhs, ctx, local.kind);
-
+
ctx1.bb.emit(STORE_LOCAL(local), tree.pos)
ctx1.scope.add(local)
ctx1.bb.emit(SCOPE_ENTER(local))
@@ -730,10 +729,10 @@ abstract class GenICode extends SubComponent {
ctx1.bb.enterIgnoreMode
generatedType = expectedType
ctx1
- }
+ }
genLoadReturn
- case t @ Try(_, _, _) =>
+ case t @ Try(_, _, _) =>
genLoadTry(t, ctx, generatedType = _)
case Throw(expr) =>
@@ -753,7 +752,7 @@ abstract class GenICode extends SubComponent {
case Object_asInstanceOf => true
case _ => abort("Unexpected type application " + fun + "[sym: " + sym.fullName + "]" + " in: " + tree)
}
-
+
val Select(obj, _) = fun
val l = toTypeKind(obj.tpe)
val r = toTypeKind(targs.head.tpe)
@@ -797,7 +796,7 @@ abstract class GenICode extends SubComponent {
ctx.bb.emit(THIS(ctx.clazz.symbol), tree.pos)
val ctx1 = genLoadArguments(args, fun.symbol.info.paramTypes, ctx)
-
+
ctx1.bb.emit(CALL_METHOD(fun.symbol, invokeStyle), tree.pos)
generatedType =
if (fun.symbol.isConstructor) UNIT
@@ -815,7 +814,7 @@ abstract class GenICode extends SubComponent {
val ctor = fun.symbol
debugassert(ctor.isClassConstructor,
"'new' call to non-constructor: " + ctor.name)
-
+
generatedType = toTypeKind(tpt.tpe)
debugassert(generatedType.isReferenceType || generatedType.isArrayType,
"Non reference type cannot be instantiated: " + generatedType)
@@ -861,7 +860,7 @@ abstract class GenICode extends SubComponent {
ctx1
}
ctx2
-
+
case _ =>
abort("Cannot instantiate " + tpt + " of kind: " + generatedType)
}
@@ -902,7 +901,7 @@ abstract class GenICode extends SubComponent {
ctx1
case app @ Apply(fun @ Select(qual, _), args)
- if !ctx.method.symbol.isStaticConstructor
+ if !ctx.method.symbol.isStaticConstructor
&& fun.symbol.isAccessor && fun.symbol.accessed.hasStaticAnnotation
&& qual.tpe.typeSymbol.orElse(fun.symbol.owner).companionClass != NoSymbol =>
// bypass the accessor to the companion object and load the static field directly
@@ -941,11 +940,11 @@ abstract class GenICode extends SubComponent {
}
}
genLoadApply5
-
+
case app @ Apply(fun, args) =>
def genLoadApply6 = {
val sym = fun.symbol
-
+
if (sym.isLabel) { // jump to a label
val label = ctx.labels.getOrElse(sym, {
// it is a forward jump, scan for labels
@@ -982,7 +981,7 @@ abstract class GenICode extends SubComponent {
Static(true)
else
Dynamic
-
+
var ctx1 =
if (invokeStyle.hasInstance) {
if (forMSIL && !(invokeStyle.isInstanceOf[SuperCall]) && msil_IsValuetypeInstMethod(sym))
@@ -990,24 +989,26 @@ abstract class GenICode extends SubComponent {
else
genLoadQualifier(fun, ctx)
} else ctx
-
+
ctx1 = genLoadArguments(args, sym.info.paramTypes, ctx1)
val cm = CALL_METHOD(sym, invokeStyle)
-
+
/** In a couple cases, squirrel away a little extra information in the
* CALL_METHOD for use by GenJVM.
*/
fun match {
case Select(qual, _) =>
val qualSym = findHostClass(qual.tpe, sym)
-
- if (qualSym == ArrayClass) cm setTargetTypeKind toTypeKind(qual.tpe)
- else cm setHostClass qualSym
-
- log(
- if (qualSym == ArrayClass) "Stored target type kind " + toTypeKind(qual.tpe) + " for " + sym.fullName
- else s"Set more precise host class for ${sym.fullName} hostClass: $qualSym"
- )
+ if (qualSym == ArrayClass) {
+ val kind = toTypeKind(qual.tpe)
+ cm setTargetTypeKind kind
+ log(s"Stored target type kind for {$sym.fullName} as $kind")
+ }
+ else {
+ cm setHostClass qualSym
+ if (qual.tpe.typeSymbol != qualSym)
+ log(s"Precisified host class for $sym from ${qual.tpe.typeSymbol.fullName} to ${qualSym.fullName}")
+ }
case _ =>
}
ctx1.bb.emit(cm, tree.pos)
@@ -1143,7 +1144,7 @@ abstract class GenICode extends SubComponent {
val elmKind = toTypeKind(tpt.tpe)
generatedType = ARRAY(elmKind)
val elems = _elems.toIndexedSeq
-
+
ctx1.bb.emit(CONSTANT(new Constant(elems.length)), tree.pos)
ctx1.bb.emit(CREATE_ARRAY(elmKind, 1))
// inline array literals
@@ -1166,7 +1167,7 @@ abstract class GenICode extends SubComponent {
val afterCtx = ctx1.newBlock
var caseCtx: Context = null
generatedType = toTypeKind(tree.tpe)
-
+
var targets: List[BasicBlock] = Nil
var tags: List[Int] = Nil
var default: BasicBlock = afterCtx.bb
@@ -1193,7 +1194,7 @@ abstract class GenICode extends SubComponent {
abort("Invalid case statement in switch-like pattern match: " +
tree + " at: " + (tree.pos))
}
-
+
caseCtx = genLoad(body, tmpCtx, generatedType)
// close the block unless it's already been closed by the body, which closes the block if it ends in a jump (which is emitted to have alternatives share their body)
caseCtx.bb.closeWith(JUMP(afterCtx.bb) setPos caze.pos)
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
index d1d8e4a385..df158a29ea 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
@@ -200,7 +200,7 @@ abstract class CopyPropagation {
in(b) = lattice.bottom
out(b) = lattice.bottom
assert(out.contains(b), out)
- log("Added point: " + b)
+ debuglog("CopyAnalysis added point: " + b)
}
m.exh foreach { e =>
in(e.startBlock) = new copyLattice.State(copyLattice.emptyBinding, copyLattice.exceptionHandlerStack);
@@ -531,11 +531,11 @@ abstract class CopyPropagation {
case 0 => ()
case 1 if ctor.tpe.paramTypes.head == ctor.owner.rawowner.tpe =>
// it's an unused outer
- log("considering unused outer at position 0 in " + ctor.tpe.paramTypes)
+ debuglog("considering unused outer at position 0 in " + ctor.tpe.paramTypes)
paramTypes = paramTypes.tail
values = values.tail
case _ =>
- log("giving up on " + ctor + "(diff: " + diff + ")")
+ debuglog("giving up on " + ctor + "(diff: " + diff + ")")
return bindings
}
@@ -566,7 +566,7 @@ abstract class CopyPropagation {
method.blocks map { b =>
"\nIN(%s):\t Bindings: %s".format(b.label, in(b).bindings) +
"\nIN(%s):\t Stack: %s".format(b.label, in(b).stack)
- }
+ }
).mkString
} /* class CopyAnalysis */
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index b57f5e86a3..ea0a0148e4 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -154,8 +154,10 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
inform("[running phase " + name + " on icode]")
if (settings.Xdce.value)
- for ((sym, cls) <- icodes.classes if inliner.isClosureClass(sym) && !deadCode.liveClosures(sym))
+ for ((sym, cls) <- icodes.classes if inliner.isClosureClass(sym) && !deadCode.liveClosures(sym)) {
+ log(s"Optimizer eliminated ${sym.fullNameString}")
icodes.classes -= sym
+ }
// For predictably ordered error messages.
var sortedClasses = classes.values.toList sortBy ("" + _.symbol.fullName)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 930791d88d..0f64a55d70 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -122,8 +122,10 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
inform("[running phase " + name + " on icode]")
if (settings.Xdce.value)
- for ((sym, cls) <- icodes.classes if inliner.isClosureClass(sym) && !deadCode.liveClosures(sym))
+ for ((sym, cls) <- icodes.classes if inliner.isClosureClass(sym) && !deadCode.liveClosures(sym)) {
+ log(s"Optimizer eliminated ${sym.fullNameString}")
icodes.classes -= sym
+ }
// For predictably ordered error messages.
val sortedClasses = classes.values.toList sortBy ("" + _.symbol.fullName)
diff --git a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
index 7772ccbdd5..eb2da72401 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
@@ -35,7 +35,7 @@ abstract class ClosureElimination extends SubComponent {
case (STORE_LOCAL(x), LOAD_LOCAL(y)) if (x == y) =>
var liveOut = liveness.out(bb)
if (!liveOut(x)) {
- log("store/load to a dead local? " + x)
+ debuglog("store/load to a dead local? " + x)
val instrs = bb.getArray
var idx = instrs.length - 1
while (idx > 0 && (instrs(idx) ne i2)) {
@@ -43,7 +43,7 @@ abstract class ClosureElimination extends SubComponent {
idx -= 1
}
if (!liveOut(x)) {
- log("removing dead store/load " + x)
+ log("Removing dead store/load of " + x.sym.initialize.defString)
Some(Nil)
} else None
} else
@@ -84,6 +84,7 @@ abstract class ClosureElimination extends SubComponent {
*/
class ClosureElim {
def analyzeClass(cls: IClass): Unit = if (settings.Xcloselim.value) {
+ log(s"Analyzing ${cls.methods.size} methods in $cls.")
cls.methods foreach { m =>
analyzeMethod(m)
peephole(m)
@@ -95,7 +96,6 @@ abstract class ClosureElimination extends SubComponent {
/* Some embryonic copy propagation. */
def analyzeMethod(m: IMethod): Unit = try {if (m.hasCode) {
- log("Analyzing " + m)
cpp.init(m)
cpp.run
@@ -110,23 +110,20 @@ abstract class ClosureElimination extends SubComponent {
t match {
case Deref(This) | Const(_) =>
bb.replaceInstruction(i, valueToInstruction(t));
- log("replaced " + i + " with " + t)
+ debuglog(s"replaced $i with $t")
case _ =>
- bb.replaceInstruction(i, LOAD_LOCAL(info.getAlias(l)))
- log("replaced " + i + " with " + info.getAlias(l))
-
+ val t = info.getAlias(l)
+ bb.replaceInstruction(i, LOAD_LOCAL(t))
+ debuglog(s"replaced $i with $t")
}
case LOAD_FIELD(f, false) /* if accessible(f, m.symbol) */ =>
def replaceFieldAccess(r: Record) {
val Record(cls, bindings) = r
- info.getFieldNonRecordValue(r, f) match {
- case Some(v) =>
- bb.replaceInstruction(i,
- DROP(REFERENCE(cls)) :: valueToInstruction(v) :: Nil);
- log("Replaced " + i + " with " + info.getFieldNonRecordValue(r, f));
- case None =>
+ info.getFieldNonRecordValue(r, f) foreach { v =>
+ bb.replaceInstruction(i, DROP(REFERENCE(cls)) :: valueToInstruction(v) :: Nil)
+ debuglog(s"replaced $i with $v")
}
}
@@ -157,14 +154,14 @@ abstract class ClosureElimination extends SubComponent {
value match {
case Boxed(LocalVar(loc2)) =>
bb.replaceInstruction(i, DROP(icodes.ObjectReference) :: valueToInstruction(info.getBinding(loc2)) :: Nil)
- log("replaced " + i + " with " + info.getBinding(loc2))
+ debuglog("replaced " + i + " with " + info.getBinding(loc2))
case _ =>
()
}
case Boxed(LocalVar(loc1)) :: _ =>
val loc2 = info.getAlias(loc1)
bb.replaceInstruction(i, DROP(icodes.ObjectReference) :: valueToInstruction(Deref(LocalVar(loc2))) :: Nil)
- log("replaced " + i + " with " + LocalVar(loc2))
+ debuglog("replaced " + i + " with " + LocalVar(loc2))
case _ =>
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index fd949576e1..36a5d61cfb 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -44,6 +44,7 @@ abstract class DeadCodeElimination extends SubComponent {
class DeadCode {
def analyzeClass(cls: IClass) {
+ log(s"Analyzing ${cls.methods.size} methods in $cls.")
cls.methods.foreach { m =>
this.method = m
dieCodeDie(m)
@@ -73,7 +74,7 @@ abstract class DeadCodeElimination extends SubComponent {
def dieCodeDie(m: IMethod) {
if (m.hasCode) {
- log("dead code elimination on " + m);
+ debuglog("dead code elimination on " + m);
dropOf.clear()
m.code.blocks.clear()
accessedLocals = m.params.reverse
@@ -82,8 +83,10 @@ abstract class DeadCodeElimination extends SubComponent {
mark
sweep(m)
accessedLocals = accessedLocals.distinct
- if ((m.locals diff accessedLocals).nonEmpty) {
- log("Removed dead locals: " + (m.locals diff accessedLocals))
+ val diff = m.locals diff accessedLocals
+ if (diff.nonEmpty) {
+ val msg = diff.map(_.sym.name)mkString(", ")
+ log(s"Removed ${diff.size} dead locals: $msg")
m.locals = accessedLocals.reverse
}
}
@@ -126,7 +129,7 @@ abstract class DeadCodeElimination extends SubComponent {
case RETURN(_) | JUMP(_) | CJUMP(_, _, _, _) | CZJUMP(_, _, _, _) | STORE_FIELD(_, _) |
THROW(_) | LOAD_ARRAY_ITEM(_) | STORE_ARRAY_ITEM(_) | SCOPE_ENTER(_) | SCOPE_EXIT(_) | STORE_THIS(_) |
LOAD_EXCEPTION(_) | SWITCH(_, _) | MONITOR_ENTER() | MONITOR_EXIT() => worklist += ((bb, idx))
- case CALL_METHOD(m1, _) if isSideEffecting(m1) => worklist += ((bb, idx)); log("marking " + m1)
+ case CALL_METHOD(m1, _) if isSideEffecting(m1) => worklist += ((bb, idx)); debuglog("marking " + m1)
case CALL_METHOD(m1, SuperCall(_)) =>
worklist += ((bb, idx)) // super calls to constructor
case DROP(_) =>
@@ -173,7 +176,7 @@ abstract class DeadCodeElimination extends SubComponent {
instr match {
case LOAD_LOCAL(l1) =>
for ((l2, bb1, idx1) <- defs((bb, idx)) if l1 == l2; if !useful(bb1)(idx1)) {
- log("\tAdding " + bb1(idx1))
+ debuglog("\tAdding " + bb1(idx1))
worklist += ((bb1, idx1))
}
@@ -197,7 +200,7 @@ abstract class DeadCodeElimination extends SubComponent {
case _ =>
for ((bb1, idx1) <- rdef.findDefs(bb, idx, instr.consumed) if !useful(bb1)(idx1)) {
- log("\tAdding " + bb1(idx1))
+ debuglog("\tAdding " + bb1(idx1))
worklist += ((bb1, idx1))
}
}
@@ -232,7 +235,7 @@ abstract class DeadCodeElimination extends SubComponent {
} else {
i match {
case NEW(REFERENCE(sym)) =>
- log("skipped object creation: " + sym + "inside " + m)
+ log(s"Eliminated instantation of $sym inside $m")
case _ => ()
}
debuglog("Skipped: bb_" + bb + ": " + idx + "( " + i + ")")
@@ -240,7 +243,7 @@ abstract class DeadCodeElimination extends SubComponent {
}
if (bb.nonEmpty) bb.close
- else log("empty block encountered")
+ else log(s"empty block encountered in $m")
}
}
@@ -252,7 +255,7 @@ abstract class DeadCodeElimination extends SubComponent {
foreachWithIndex(bb.toList) { (i, idx) =>
if (!useful(bb)(idx)) {
foreachWithIndex(i.consumedTypes.reverse) { (consumedType, depth) =>
- log("Finding definitions of: " + i + "\n\t" + consumedType + " at depth: " + depth)
+ debuglog("Finding definitions of: " + i + "\n\t" + consumedType + " at depth: " + depth)
val defs = rdef.findDefs(bb, idx, 1, depth)
for (d <- defs) {
val (bb, idx) = d
diff --git a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala
index f1f597322e..98120f0614 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala
@@ -93,10 +93,9 @@ abstract class InlineExceptionHandlers extends SubComponent {
val startTime = System.currentTimeMillis
currentClass = c
- log("Starting " + c)
+ debuglog("Starting InlineExceptionHandlers on " + c)
c.methods foreach applyMethod
-
- log("Finished " + c + "... " + (System.currentTimeMillis - startTime) + "ms")
+ debuglog("Finished InlineExceptionHandlers on " + c + "... " + (System.currentTimeMillis - startTime) + "ms")
currentClass = null
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index 5464b6fc3b..62bb23c3a7 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -44,7 +44,7 @@ abstract class Inliners extends SubComponent {
import definitions.{
NullClass, NothingClass, ObjectClass,
PredefModule, RuntimePackage, ScalaInlineClass, ScalaNoInlineClass,
- isFunctionType
+ isFunctionType, isByNameParamType
}
val phaseName = "inliner"
@@ -143,7 +143,6 @@ abstract class Inliners extends SubComponent {
}
def isBottomType(sym: Symbol) = sym == NullClass || sym == NothingClass
- def posToStr(pos: scala.reflect.internal.util.Position) = if (pos.isDefined) pos.point.toString else "<nopos>"
/** Is the given class a closure? */
def isClosureClass(cls: Symbol): Boolean =
@@ -194,6 +193,27 @@ abstract class Inliners extends SubComponent {
private var currentIClazz: IClass = _
private def warn(pos: Position, msg: String) = currentIClazz.cunit.inlinerWarning(pos, msg)
+ private def ownedName(sym: Symbol): String = afterUncurry {
+ val count = (
+ if (!sym.isMethod) 1
+ else if (sym.owner.isAnonymousFunction) 3
+ else 2
+ )
+ (sym.ownerChain take count filterNot (_.isPackageClass)).reverseMap(_.nameString).mkString(".")
+ }
+ private def inlineLog(what: String, main: => String, comment: => String) {
+ def cstr = comment match {
+ case "" => ""
+ case str => " // " + str
+ }
+ val width = if (currentIClazz eq null) 40 else currentIClazz.symbol.enclosingPackage.fullName.length + 25
+ val fmt = "%8s %-" + width + "s" + cstr
+ log(fmt.format(what, main))
+ }
+ private def inlineLog(what: String, main: Symbol, comment: => String) {
+ inlineLog(what, ownedName(main), comment)
+ }
+
val recentTFAs = mutable.Map.empty[Symbol, Tuple2[Boolean, analysis.MethodTFA]]
private def getRecentTFA(incm: IMethod, forceable: Boolean): (Boolean, analysis.MethodTFA) = {
@@ -244,14 +264,15 @@ abstract class Inliners extends SubComponent {
def analyzeClass(cls: IClass): Unit =
if (settings.inline.value) {
- debuglog("Analyzing " + cls)
+ inlineLog("class", s"${cls.symbol.decodedName}", s"analyzing ${cls.methods.size} methods in $cls")
this.currentIClazz = cls
val ms = cls.methods sorted imethodOrdering
ms foreach { im =>
- if(hasInline(im.symbol)) {
- log("Not inlining into " + im.symbol.originalName.decode + " because it is marked @inline.")
- } else if(im.hasCode && !im.symbol.isBridge) {
+ if (hasInline(im.symbol)) {
+ inlineLog("skip", im.symbol, "no inlining into @inline methods")
+ }
+ else if(im.hasCode && !im.symbol.isBridge) {
analyzeMethod(im)
}
}
@@ -296,6 +317,8 @@ abstract class Inliners extends SubComponent {
* */
def analyzeMethod(m: IMethod): Unit = {
// m.normalize
+ if (settings.debug.value)
+ inlineLog("caller", ownedName(m.symbol), "in " + m.symbol.owner.fullName)
var sizeBeforeInlining = m.code.blockCount
var instrBeforeInlining = m.code.instructionCount
@@ -306,8 +329,8 @@ abstract class Inliners extends SubComponent {
val fresh = mutable.HashMap.empty[String, Int] withDefaultValue 0
// how many times have we already inlined this method here?
val inlinedMethodCount = mutable.HashMap.empty[Symbol, Int] withDefaultValue 0
-
val caller = new IMethodInfo(m)
+ def analyzeMessage = s"Analyzing ${caller.length} blocks of $m for inlining sites."
def preInline(isFirstRound: Boolean): Int = {
val inputBlocks = caller.m.linearizedBlocks()
@@ -354,15 +377,17 @@ abstract class Inliners extends SubComponent {
*/
def analyzeInc(i: CALL_METHOD, bb: BasicBlock, receiver: Symbol, stackLength: Int, concreteMethod: Symbol): Boolean = {
assert(bb.toList contains i, "Candidate callsite does not belong to BasicBlock.")
-
- var inlined = false
val shouldWarn = hasInline(i.method)
- def warnNoInline(reason: String) = {
- if (shouldWarn) {
- warn(i.pos, "Could not inline required method %s because %s.".format(i.method.originalName.decode, reason))
- }
- }
+ def warnNoInline(reason: String): Boolean = {
+ def msg = "Could not inline required method %s because %s.".format(i.method.originalName.decode, reason)
+ if (settings.debug.value)
+ inlineLog("fail", i.method.fullName, reason)
+ if (shouldWarn)
+ warn(i.pos, msg)
+
+ false
+ }
var isAvailable = icodes available concreteMethod.enclClass
@@ -378,92 +403,69 @@ abstract class Inliners extends SubComponent {
isAvailable = icodes.load(concreteMethod.enclClass)
}
- def isCandidate = (
- isClosureClass(receiver)
- || concreteMethod.isEffectivelyFinal
- || receiver.isEffectivelyFinal
- )
+ def isCandidate = (
+ isClosureClass(receiver)
+ || concreteMethod.isEffectivelyFinal
+ || receiver.isEffectivelyFinal
+ )
- def isApply = concreteMethod.name == nme.apply
+ def isApply = concreteMethod.name == nme.apply
- def isCountable = !(
- isClosureClass(receiver)
- || isApply
- || isMonadicMethod(concreteMethod)
- || receiver.enclosingPackage == definitions.RuntimePackage
- ) // only count non-closures
+ def isCountable = !(
+ isClosureClass(receiver)
+ || isApply
+ || isMonadicMethod(concreteMethod)
+ || receiver.enclosingPackage == definitions.RuntimePackage
+ ) // only count non-closures
debuglog("Treating " + i
+ "\n\treceiver: " + receiver
+ "\n\ticodes.available: " + isAvailable
+ "\n\tconcreteMethod.isEffectivelyFinal: " + concreteMethod.isEffectivelyFinal)
- if (isAvailable && isCandidate) {
- lookupIMethod(concreteMethod, receiver) match {
-
- case Some(callee) if callee.hasCode =>
- val inc = new IMethodInfo(callee)
- val pair = new CallerCalleeInfo(caller, inc, fresh, inlinedMethodCount)
-
- if(inc.hasHandlers && (stackLength == -1)) {
- // no inlining is done, yet don't warn about it, stackLength == -1 indicates we're trying to inlineWithoutTFA.
- // Shortly, a TFA will be computed and an error message reported if indeed inlining not possible.
- return false
- }
-
- (pair isStampedForInlining stackLength) match {
-
- case inlInfo if inlInfo.isSafe =>
-
- (inlInfo: @unchecked) match {
-
- case FeasibleInline(accessNeeded, toBecomePublic) =>
- for(f <- toBecomePublic) {
- debuglog("Making public (synthetic) field-symbol: " + f)
- f setFlag Flags.notPRIVATE
- f setFlag Flags.notPROTECTED
- }
- // only add to `knownSafe` after all `toBecomePublic` fields actually made public.
- if(accessNeeded == NonPublicRefs.Public) { tfa.knownSafe += inc.sym }
-
- case InlineableAtThisCaller => ()
-
- }
-
- retry = true
- inlined = true
- if (isCountable) { count += 1 };
+ if (!isCandidate) warnNoInline("it can be overridden")
+ else if (!isAvailable) warnNoInline("bytecode unavailable")
+ else lookupIMethod(concreteMethod, receiver) filter (callee => callee.hasCode || warnNoInline("callee has no code")) exists { callee =>
+ val inc = new IMethodInfo(callee)
+ val pair = new CallerCalleeInfo(caller, inc, fresh, inlinedMethodCount)
- pair.doInline(bb, i)
- if (!pair.isInlineForced || inc.isMonadic) { caller.inlinedCalls += 1 };
- inlinedMethodCount(inc.sym) += 1
-
- // Remove the caller from the cache (this inlining might have changed its calls-private relation).
- usesNonPublics -= m
- recentTFAs -= m.symbol
-
-
- case DontInlineHere(msg) =>
- debuglog("inline failed, reason: " + msg)
- warnNoInline(msg)
-
- case NeverSafeToInline => ()
- }
-
- case Some(callee) =>
- assert(!callee.hasCode, "The case clause right before this one should have handled this case.")
- warnNoInline("callee (" + callee + ") has no code")
- ()
+ if (inc.hasHandlers && (stackLength == -1)) {
+ // no inlining is done, yet don't warn about it, stackLength == -1 indicates we're trying to inlineWithoutTFA.
+ // Shortly, a TFA will be computed and an error message reported if indeed inlining not possible.
+ false
+ }
+ else {
+ val isSafe = pair isStampedForInlining stackLength match {
+ case DontInlineHere(msg) => warnNoInline(msg)
+ case NeverSafeToInline => false
+ case InlineableAtThisCaller => true
+ case inl @ FeasibleInline(_, _) if !inl.isSafe => false
+ case FeasibleInline(required, toPublicize) =>
+ for (f <- toPublicize) {
+ inlineLog("access", f, "making public")
+ f setFlag Flags.notPRIVATE
+ f setFlag Flags.notPROTECTED
+ }
+ // only add to `knownSafe` after all `toPublicize` fields actually made public.
+ if (required == NonPublicRefs.Public)
+ tfa.knownSafe += inc.sym
- case None =>
- warnNoInline("bytecode was not available")
- debuglog("could not find icode\n\treceiver: " + receiver + "\n\tmethod: " + concreteMethod)
+ true
+ }
+ isSafe && {
+ retry = true
+ if (isCountable) count += 1
+ pair.doInline(bb, i)
+ if (!pair.isInlineForced || inc.isMonadic) caller.inlinedCalls += 1
+ inlinedMethodCount(inc.sym) += 1
+
+ // Remove the caller from the cache (this inlining might have changed its calls-private relation).
+ usesNonPublics -= m
+ recentTFAs -= m.symbol
+ true
+ }
}
- } else {
- warnNoInline(if(!isAvailable) "bytecode was not available" else "it can be overridden")
}
-
- inlined
}
/* Pre-inlining consists in invoking the usual inlining subroutine with (receiver class, concrete method) pairs as input
@@ -485,7 +487,7 @@ abstract class Inliners extends SubComponent {
do {
retry = false
- log("Analyzing " + m + " count " + count + " with " + caller.length + " blocks")
+ debuglog(analyzeMessage)
/* it's important not to inline in unreachable basic blocks. linearizedBlocks() returns only reachable ones. */
tfa.callerLin = caller.m.linearizedBlocks()
@@ -567,9 +569,16 @@ abstract class Inliners extends SubComponent {
m.normalize
if (sizeBeforeInlining > 0) {
val instrAfterInlining = m.code.instructionCount
- val prefix = if ((instrAfterInlining > 2 * instrBeforeInlining) && (instrAfterInlining > 200)) " !! " else ""
- log(prefix + " %s blocks before inlining: %d (%d) after: %d (%d)".format(
- m.symbol.fullName, sizeBeforeInlining, instrBeforeInlining, m.code.blockCount, instrAfterInlining))
+ val prefix = if ((instrAfterInlining > 2 * instrBeforeInlining) && (instrAfterInlining > 200)) "!!" else ""
+ val inlinings = caller.inlinedCalls
+ if (inlinings > 0) {
+ val s1 = s"instructions $instrBeforeInlining -> $instrAfterInlining"
+ val s2 = if (sizeBeforeInlining == m.code.blockCount) "" else s", blocks $sizeBeforeInlining -> ${m.code.blockCount}"
+ val callees = inlinedMethodCount.toList map { case (k, v) => k.fullNameString + ( if (v == 1) "" else "/" + v ) }
+
+ inlineLog("inlined", m.symbol.fullName, callees.sorted.mkString(inlinings + " inlined: ", ", ", ""))
+ inlineLog("<<tldr>>", m.symbol.fullName, s"${m.symbol.nameString}: $s1$s2")
+ }
}
}
@@ -589,6 +598,8 @@ abstract class Inliners extends SubComponent {
}
class IMethodInfo(val m: IMethod) {
+ override def toString = m.toString
+
val sym = m.symbol
val name = sym.name
def owner = sym.owner
@@ -608,10 +619,11 @@ abstract class Inliners extends SubComponent {
def instructions = m.code.instructions
// def linearized = linearizer linearize m
- def isSmall = (length <= SMALL_METHOD_SIZE) && blocks(0).length < 10
- def isLarge = length > MAX_INLINE_SIZE
- def isRecursive = m.recursive
- def hasHandlers = handlers.nonEmpty || m.bytecodeHasEHs
+ def isSmall = (length <= SMALL_METHOD_SIZE) && blocks(0).length < 10
+ def isLarge = length > MAX_INLINE_SIZE
+ def isRecursive = m.recursive
+ def hasHandlers = handlers.nonEmpty || m.bytecodeHasEHs
+ def hasClosureParam = paramTypes exists (tp => isByNameParamType(tp) || isFunctionType(tp))
def isSynchronized = sym.hasFlag(Flags.SYNCHRONIZED)
def hasNonFinalizerHandler = handlers exists {
@@ -661,9 +673,9 @@ abstract class Inliners extends SubComponent {
*
* TODO handle more robustly the case of a trait var changed at the source-level from public to private[this]
* (eg by having ICodeReader use unpickler, see SI-5442).
-
+
DISABLED
-
+
def potentiallyPublicized(f: Symbol): Boolean = {
(m.sourceFile eq NoSourceFile) && f.name.containsChar('$')
}
@@ -687,7 +699,7 @@ abstract class Inliners extends SubComponent {
val i = iter.next()
getAccess(i) match {
case Private =>
- log("instruction " + i + " requires private access.")
+ inlineLog("access", s"instruction $i requires private access", "pos=" + i.pos)
toBecomePublic = Nil
seen = Private
case Protected => seen = Protected
@@ -764,11 +776,10 @@ abstract class Inliners extends SubComponent {
tfa.warnIfInlineFails.remove(instr)
val targetPos = instr.pos
- log("Inlining " + inc.m + " in " + caller.m + " at pos: " + posToStr(targetPos))
def blockEmit(i: Instruction) = block.emit(i, targetPos)
def newLocal(baseName: String, kind: TypeKind) =
- new Local(caller.sym.newVariable(freshName(baseName), targetPos), kind, false)
+ new Local(caller.sym.newVariable(freshName(baseName), targetPos) setInfo kind.toType, kind, false)
val (hasRETURN, a) = getRecentTFA(inc.m, isInlineForced)
@@ -955,6 +966,7 @@ abstract class Inliners extends SubComponent {
if(reasonWhyNever != null) {
tfa.knownNever += inc.sym
+ inlineLog("never", inc.sym, reasonWhyNever)
// next time around NeverSafeToInline is returned, thus skipping (duplicate) msg, this is intended.
return DontInlineHere(inc.m + " " + reasonWhyNever)
}
@@ -977,10 +989,15 @@ abstract class Inliners extends SubComponent {
* As a result of (b), some synthetic private members can be chosen to become public.
*/
- if(!isInlineForced && !isScoreOK) {
+ val score = inlinerScore
+ val scoreStr = if (score > 0) "+" + score else "" + score
+ val what = if (score > 0) "ok to" else "don't"
+ inlineLog(scoreStr, inc.m.symbol, s"$what inline into ${ownedName(caller.m.symbol)}")
+
+ if (!isInlineForced && score <= 0) {
// During inlining retry, a previous caller-callee pair that scored low may pass.
// Thus, adding the callee to tfa.knownUnsafe isn't warranted.
- return DontInlineHere("too low score (heuristics)")
+ return DontInlineHere(s"inliner heuristic")
}
if(inc.hasHandlers && (stackLength > inc.minimumStack)) {
@@ -999,7 +1016,9 @@ abstract class Inliners extends SubComponent {
val accReq = inc.accessRequirements
if(!canAccess(accReq.accessNeeded)) {
tfa.knownUnsafe += inc.sym
- return DontInlineHere("access level required by callee not matched by caller")
+ val msg = "access level required by callee not matched by caller"
+ inlineLog("fail", inc.sym, msg)
+ return DontInlineHere(msg)
}
FeasibleInline(accReq.accessNeeded, accReq.toBecomePublic)
@@ -1021,9 +1040,7 @@ abstract class Inliners extends SubComponent {
* - it's good to inline closures functions.
* - it's bad (useless) to inline inside bridge methods
*/
- def isScoreOK: Boolean = {
- debuglog("shouldInline: " + caller.m + " , callee:" + inc.m)
-
+ def inlinerScore: Int = {
var score = 0
// better not inline inside closures, but hope that the closure itself is repeatedly inlined
@@ -1031,21 +1048,19 @@ abstract class Inliners extends SubComponent {
else if (caller.inlinedCalls < 1) score -= 1 // only monadic methods can trigger the first inline
if (inc.isSmall) score += 1;
+ // if (inc.hasClosureParam) score += 2
if (inc.isLarge) score -= 1;
if (caller.isSmall && isLargeSum) {
score -= 1
- debuglog("shouldInline: score decreased to " + score + " because small " + caller + " would become large")
+ debuglog(s"inliner score decreased to $score because small caller $caller would become large")
}
if (inc.isMonadic) score += 3
else if (inc.isHigherOrder) score += 1
- if (inc.isInClosure) score += 2;
- if (inlinedMethodCount(inc.sym) > 2) score -= 2;
-
- log("shouldInline(" + inc.m + ") score: " + score)
-
- score > 0
+ if (inc.isInClosure) score += 2
+ if (inlinedMethodCount(inc.sym) > 2) score -= 2
+ score
}
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index 96d7dadbd7..a2df1494ef 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -387,8 +387,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
newSym <- req.definedSymbols get name
oldSym <- oldReq.definedSymbols get name.companionName
} {
- replwarn("warning: previously defined %s is not a companion to %s.".format(
- stripString("" + oldSym), stripString("" + newSym)))
+ afterTyper(replwarn(s"warning: previously defined $oldSym is not a companion to $newSym."))
replwarn("Companions must be defined together; you may wish to use :paste mode for this.")
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index 437a5e1434..175c322786 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -37,7 +37,7 @@ abstract class ICodeReader extends ClassfileParser {
cls.info // ensure accurate type information
isScalaModule = cls.isModule && !cls.isJavaDefined
- log("Reading class: " + cls + " isScalaModule?: " + isScalaModule)
+ log("ICodeReader reading " + cls)
val name = cls.javaClassName
classPath.findSourceFile(name) match {
@@ -99,11 +99,9 @@ abstract class ICodeReader extends ClassfileParser {
if (sym == NoSymbol)
sym = owner.info.findMember(newTermName(name + nme.LOCAL_SUFFIX_STRING), 0, 0, false).suchThat(_.tpe =:= tpe)
if (sym == NoSymbol) {
- log("Could not find symbol for " + name + ": " + tpe)
- log(owner.info.member(name).tpe + " : " + tpe)
sym = if (field) owner.newValue(name, owner.pos, toScalaFieldFlags(jflags)) else dummySym
sym setInfoAndEnter tpe
- log("added " + sym + ": " + sym.tpe)
+ log(s"ICodeReader could not locate ${name.decode} in $owner. Created ${sym.defString}.")
}
(jflags, sym)
}
@@ -172,10 +170,7 @@ abstract class ICodeReader extends ClassfileParser {
}
else if (nme.isModuleName(name)) {
val strippedName = nme.stripModuleSuffix(name)
- val sym = forceMangledName(newTermName(strippedName.decode), true)
-
- if (sym == NoSymbol) rootMirror.getModule(strippedName)
- else sym
+ forceMangledName(newTermName(strippedName.decode), true) orElse rootMirror.getModule(strippedName)
}
else {
forceMangledName(name, false)
@@ -956,7 +951,7 @@ abstract class ICodeReader extends ClassfileParser {
case None =>
checkValidIndex
val l = freshLocal(idx, kind, false)
- log("Added new local for idx " + idx + ": " + kind)
+ debuglog("Added new local for idx " + idx + ": " + kind)
locals += (idx -> List((l, kind)))
l
}
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
index a8cdee7154..4a668d4c61 100644
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
@@ -79,12 +79,11 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
// -optimise and not otherwise, but the classpath can use arbitrary
// logic so the classpath must be queried.
if (classPath.context.isValidName(implName + ".class")) {
- log("unlinking impl class " + implSym)
iface.owner.info.decls unlink implSym
NoSymbol
}
else {
- log("not unlinking existing " + implSym + " as the impl class is not visible on the classpath.")
+ log(s"not unlinking $iface's existing implClass ${implSym.name} because it is not on the classpath.")
implSym
}
}
@@ -113,9 +112,10 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
iface.info
implClassMap.getOrElse(iface, atPhase(implClassPhase) {
- log("Creating implClass for " + iface)
- if (iface.implClass ne NoSymbol)
- log("%s.implClass already exists: %s".format(iface, iface.implClass))
+ if (iface.implClass eq NoSymbol)
+ debuglog(s"${iface.fullLocationString} has no implClass yet, creating it now.")
+ else
+ log(s"${iface.fullLocationString} impl class is ${iface.implClass.nameString}")
newImplClass(iface)
})
@@ -137,7 +137,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
* given the decls ifaceDecls of its interface.
*/
private def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = {
- log("LazyImplClassType calculating decls for " + implClass)
+ debuglog("LazyImplClassType calculating decls for " + implClass)
val decls = newScope
if ((ifaceDecls lookup nme.MIXIN_CONSTRUCTOR) == NoSymbol) {
@@ -152,16 +152,16 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
for (sym <- ifaceDecls) {
if (isInterfaceMember(sym)) {
if (needsImplMethod(sym)) {
- log("Cloning " + sym + " for implementation method in " + implClass)
val clone = sym.cloneSymbol(implClass).resetFlag(lateDEFERRED)
if (currentRun.compiles(implClass)) implMethodMap(sym) = clone
decls enter clone
sym setFlag lateDEFERRED
+ if (!sym.isSpecialized)
+ log(s"Cloned ${sym.name} from ${sym.owner} into implClass ${implClass.fullName}")
}
- else log(sym + " needs no implementation method in " + implClass)
}
else {
- log("Destructively modifying owner of %s from %s to %s".format(sym, sym.owner, implClass))
+ log(s"Destructively modifying owner of $sym from ${sym.owner} to $implClass")
sym.owner = implClass
// note: OK to destructively modify the owner here,
// because symbol will not be accessible from outside the sourcefile.
@@ -174,7 +174,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
}
override def complete(implSym: Symbol) {
- log("LazyImplClassType completing " + implSym)
+ debuglog("LazyImplClassType completing " + implSym)
/** If `tp` refers to a non-interface trait, return a
* reference to its implementation class. Otherwise return `tp`.
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index d97fbf5daa..ae1a2c7e8e 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -326,7 +326,7 @@ abstract class Erasure extends AddInterfaces
}
// Methods on Any/Object which we rewrite here while we still know what
// is a primitive and what arrived boxed.
- private lazy val interceptedMethods = Set[Symbol](Any_##, Object_##, Any_getClass) ++ (
+ private lazy val interceptedMethods = Set[Symbol](Any_##, Object_##, Any_getClass, AnyVal_getClass) ++ (
// Each value class has its own getClass for ultra-precise class object typing.
ScalaValueClasses map (_.tpe member nme.getClass_)
)
@@ -490,7 +490,7 @@ abstract class Erasure extends AddInterfaces
@inline private def box(tree: Tree, target: => String): Tree = {
val result = box1(tree)
- log("boxing "+tree+":"+tree.tpe+" to "+target+" = "+result+":"+result.tpe)
+ log(s"boxing ${tree.summaryString}: ${tree.tpe} into $target: ${result.tpe}")
result
}
@@ -525,7 +525,7 @@ abstract class Erasure extends AddInterfaces
* fields (see TupleX). (ID)
*/
case Apply(boxFun, List(arg)) if isUnbox(tree.symbol) && safeToRemoveUnbox(arg.tpe.typeSymbol) =>
- log("boxing an unbox: " + tree + "/" + tree.symbol + " and replying with " + arg + " of type " + arg.tpe)
+ log(s"boxing an unbox: ${tree.symbol} -> ${arg.tpe}")
arg
case _ =>
(REF(boxMethod(x)) APPLY tree) setPos (tree.pos) setType ObjectClass.tpe
@@ -537,7 +537,7 @@ abstract class Erasure extends AddInterfaces
private def unbox(tree: Tree, pt: Type): Tree = {
val result = unbox1(tree, pt)
- log("unboxing "+tree+":"+tree.tpe+" to "+pt+" = "+result+":"+result.tpe)
+ log(s"unboxing ${tree.summaryString}: ${tree.tpe} with pt=$pt as type ${result.tpe}")
result
}
@@ -614,7 +614,7 @@ abstract class Erasure extends AddInterfaces
* @return the adapted tree
*/
private def adaptToType(tree: Tree, pt: Type): Tree = {
- //if (settings.debug.value && pt != WildcardType)
+ if (settings.debug.value && pt != WildcardType)
log("adapting " + tree + ":" + tree.tpe + " : " + tree.tpe.parents + " to " + pt)//debug
if (tree.tpe <:< pt)
tree
@@ -1069,9 +1069,11 @@ abstract class Erasure extends AddInterfaces
case _ =>
global.typer.typed(gen.mkRuntimeCall(nme.hash_, List(qual)))
}
- } else if (isPrimitiveValueClass(qual.tpe.typeSymbol)) {
+ } else if (isPrimitiveValueClass(qual.tpe.typeSymbol)) {
// Rewrite 5.getClass to ScalaRunTime.anyValClass(5)
global.typer.typed(gen.mkRuntimeCall(nme.anyValClass, List(qual, typer.resolveClassTag(tree.pos, qual.tpe.widen))))
+ } else if (fn.symbol == AnyVal_getClass) {
+ tree setSymbol Object_getClass
} else {
tree
}
@@ -1079,8 +1081,8 @@ abstract class Erasure extends AddInterfaces
case New(tpt) if name == nme.CONSTRUCTOR && tpt.tpe.typeSymbol.isDerivedValueClass =>
// println("inject derived: "+arg+" "+tpt.tpe)
val List(arg) = args
- InjectDerivedValue(arg) addAttachment //@@@ setSymbol tpt.tpe.typeSymbol
- new TypeRefAttachment(tree.tpe.asInstanceOf[TypeRef])
+ val attachment = new TypeRefAttachment(tree.tpe.asInstanceOf[TypeRef])
+ InjectDerivedValue(arg) addAttachment attachment
case _ =>
preEraseNormalApply(tree)
}
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index 94eaba67d7..3bbf429fc2 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -22,12 +22,14 @@ abstract class Flatten extends InfoTransform {
*/
private def replaceSymbolInCurrentScope(sym: Symbol): Symbol = afterFlatten {
val scope = sym.owner.info.decls
- val old = scope lookup sym.name
- if (old ne NoSymbol)
- scope unlink old
-
+ val old = scope lookup sym.name andAlso scope.unlink
scope enter sym
- log("lifted " + sym.fullLocationString)
+
+ if (old eq NoSymbol)
+ log(s"lifted ${sym.fullLocationString}")
+ else
+ log(s"lifted ${sym.fullLocationString} after unlinking existing $old from scope.")
+
old
}
@@ -35,9 +37,7 @@ abstract class Flatten extends InfoTransform {
if (!sym.isLifted) {
sym setFlag LIFTED
debuglog("re-enter " + sym.fullLocationString)
- val old = replaceSymbolInCurrentScope(sym)
- if (old ne NoSymbol)
- log("unlinked " + old.fullLocationString + " after lifting " + sym)
+ replaceSymbolInCurrentScope(sym)
}
}
private def liftSymbol(sym: Symbol) {
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index fc9e611d20..5097ecc3fe 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -436,7 +436,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val sClassMap = anyrefSpecCache.getOrElseUpdate(sClass, mutable.Map[Symbol, Symbol]())
sClassMap.getOrElseUpdate(tparam,
- tparam.cloneSymbol(sClass, tparam.flags, (tparam.name append tpnme.SPECIALIZED_SUFFIX).asInstanceOf[Name]) // [Eugene] why do we need this cast?
+ tparam.cloneSymbol(sClass, tparam.flags, tparam.name append tpnme.SPECIALIZED_SUFFIX)
modifyInfo (info => TypeBounds(info.bounds.lo, AnyRefClass.tpe))
).tpe
}
@@ -811,12 +811,17 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
specializingOn = specializingOn filterNot (unusedStvars contains)
}
for (env0 <- specializations(specializingOn) if needsSpecialization(env0, sym)) yield {
+ // !!! Can't this logic be structured so that the new symbol's name is
+ // known when the symbol is cloned? It is much cleaner not to be mutating
+ // names after the fact. And it adds about a billion lines of
+ // "Renaming value _1 in class Tuple2 to _1$mcZ$sp" to obscure the small
+ // number of other (important) actual symbol renamings.
val tps = survivingParams(sym.info.typeParams, env0)
- val specMember = sym.cloneSymbol(owner, (sym.flags | SPECIALIZED) & ~DEFERRED)
+ val specMember = sym.cloneSymbol(owner, (sym.flags | SPECIALIZED) & ~DEFERRED) // <-- this needs newName = ...
val env = mapAnyRefsInSpecSym(env0, sym, specMember)
val (keys, vals) = env.toList.unzip
- specMember setName specializedName(sym, env)
+ specMember setName specializedName(sym, env) // <-- but the name is calculated based on the cloned symbol
// debuglog("%s normalizes to %s%s".format(sym, specMember,
// if (tps.isEmpty) "" else " with params " + tps.mkString(", ")))
@@ -897,7 +902,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
private def specializedOverload(owner: Symbol, sym: Symbol, env: TypeEnv): Symbol = {
val newFlags = (sym.flags | SPECIALIZED) & ~(DEFERRED | CASEACCESSOR)
// this method properly duplicates the symbol's info
- ( sym.cloneSymbol(owner, newFlags, specializedName(sym, env))
+ ( sym.cloneSymbol(owner, newFlags, newName = specializedName(sym, env))
modifyInfo (info => subst(env, info.asSeenFrom(owner.thisType, sym.owner)))
)
}
@@ -912,7 +917,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*
* this method will return List('apply$mcII$sp')
*/
- private def specialOverrides(clazz: Symbol) = logResultIf[List[Symbol]]("specialOverrides(" + clazz + ")", _.nonEmpty) {
+ private def specialOverrides(clazz: Symbol) = logResultIf[List[Symbol]]("specialized overrides in " + clazz, _.nonEmpty) {
/** Return the overridden symbol in syms that needs a specialized overriding symbol,
* together with its specialization environment. The overridden symbol may not be
* the closest to 'overriding', in a given hierarchy.
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 181463657b..5bff653499 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -484,11 +484,7 @@ abstract class UnCurry extends InfoTransform
arg setType functionType(Nil, arg.tpe)
}
else {
- log("byname | %s | %s | %s".format(
- arg.pos.source.path + ":" + arg.pos.line, fun.fullName,
- if (fun.isPrivate) "private" else "")
- )
-
+ log(s"Argument '$arg' at line ${arg.pos.safeLine} is $formal from ${fun.fullName}")
arg match {
// don't add a thunk for by-name argument if argument already is an application of
// a Function0. We can then remove the application and use the existing Function0.
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 1b3602fca2..803fb2857e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -923,10 +923,13 @@ trait Infer {
/** Is sym1 (or its companion class in case it is a module) a subclass of
* sym2 (or its companion class in case it is a module)?
*/
- def isProperSubClassOrObject(sym1: Symbol, sym2: Symbol): Boolean =
- sym1 != sym2 && sym1 != NoSymbol && (sym1 isSubClass sym2) ||
- sym1.isModuleClass && isProperSubClassOrObject(sym1.linkedClassOfClass, sym2) ||
- sym2.isModuleClass && isProperSubClassOrObject(sym1, sym2.linkedClassOfClass)
+ def isProperSubClassOrObject(sym1: Symbol, sym2: Symbol): Boolean = (
+ (sym1 != sym2) && (sym1 != NoSymbol) && (
+ (sym1 isSubClass sym2)
+ || (sym1.isModuleClass && isProperSubClassOrObject(sym1.linkedClassOfClass, sym2))
+ || (sym2.isModuleClass && isProperSubClassOrObject(sym1, sym2.linkedClassOfClass))
+ )
+ )
/** is symbol `sym1` defined in a proper subclass of symbol `sym2`?
*/
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 01e773e528..59935677a8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -630,7 +630,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
macroDef.owner)
} else
targ.tpe
- if (tpe.isConcrete) context.TypeTag(tpe) else context.AbsTypeTag(tpe)
+ context.AbsTypeTag(tpe)
})
macroTraceVerbose("tags: ")(tags)
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index 4f597f97c9..83740f1658 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -369,7 +369,7 @@ trait MethodSynthesis {
}
/** A synthetic method which performs the implicit conversion implied by
- * the declaration of an implicit class. Yet to be written.
+ * the declaration of an implicit class.
*/
case class ImplicitClassWrapper(tree: ClassDef) extends DerivedFromClassDef {
def completer(sym: Symbol): Type = ??? // not needed
@@ -377,7 +377,7 @@ trait MethodSynthesis {
def derivedSym: Symbol = {
// Only methods will do! Don't want to pick up any stray
// companion objects of the same name.
- val result = enclClass.info decl name suchThat (_.isMethod)
+ val result = enclClass.info decl name suchThat (x => x.isMethod && x.isSynthetic)
assert(result != NoSymbol, "not found: "+name+" in "+enclClass+" "+enclClass.info.decls)
result
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index adced9d8c9..62f01b8afa 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -359,10 +359,39 @@ trait Namers extends MethodSynthesis {
}
}
+ /** Given a ClassDef or ModuleDef, verifies there isn't a companion which
+ * has been defined in a separate file.
+ */
+ private def validateCompanionDefs(tree: ImplDef) {
+ val sym = tree.symbol
+ if (sym eq NoSymbol) return
+
+ val ctx = if (context.owner.isPackageObjectClass) context.outer else context
+ val module = if (sym.isModule) sym else ctx.scope lookup tree.name.toTermName
+ val clazz = if (sym.isClass) sym else ctx.scope lookup tree.name.toTypeName
+ val fails = (
+ module.isModule
+ && clazz.isClass
+ && !module.isSynthetic
+ && !clazz.isSynthetic
+ && (clazz.sourceFile ne null)
+ && (module.sourceFile ne null)
+ && !(module isCoDefinedWith clazz)
+ )
+ if (fails) {
+ context.unit.error(tree.pos, (
+ s"Companions '$clazz' and '$module' must be defined in same file:\n"
+ + s" Found in ${clazz.sourceFile.canonicalPath} and ${module.sourceFile.canonicalPath}")
+ )
+ }
+ }
+
def enterModuleDef(tree: ModuleDef) = {
val sym = enterModuleSymbol(tree)
sym.moduleClass setInfo namerOf(sym).moduleClassTypeCompleter(tree)
sym setInfo completerOf(tree)
+ validateCompanionDefs(tree)
+ sym
}
/** Enter a module symbol. The tree parameter can be either
@@ -635,6 +664,7 @@ trait Namers extends MethodSynthesis {
}
else context.unit.error(tree.pos, "implicit classes must accept exactly one primary constructor parameter")
}
+ validateCompanionDefs(tree)
}
// this logic is needed in case typer was interrupted half
@@ -699,7 +729,7 @@ trait Namers extends MethodSynthesis {
// }
}
- def moduleClassTypeCompleter(tree: Tree) = {
+ def moduleClassTypeCompleter(tree: ModuleDef) = {
mkTypeCompleter(tree) { sym =>
val moduleSymbol = tree.symbol
assert(moduleSymbol.moduleClass == sym, moduleSymbol.moduleClass)
@@ -1545,18 +1575,11 @@ trait Namers extends MethodSynthesis {
* call this method?
*/
def companionSymbolOf(original: Symbol, ctx: Context): Symbol = {
- try {
- original.companionSymbol orElse {
- ctx.lookup(original.name.companionName, original.owner).suchThat(sym =>
- (original.isTerm || sym.hasModuleFlag) &&
- (sym isCoDefinedWith original)
- )
- }
- }
- catch {
- case e: InvalidCompanions =>
- ctx.unit.error(original.pos, e.getMessage)
- NoSymbol
+ original.companionSymbol orElse {
+ ctx.lookup(original.name.companionName, original.owner).suchThat(sym =>
+ (original.isTerm || sym.hasModuleFlag) &&
+ (sym isCoDefinedWith original)
+ )
}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 166bb2d18c..d515934c58 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -430,6 +430,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
overrideError("cannot override a macro")
} else {
checkOverrideTypes()
+ checkOverrideDeprecated()
if (settings.warnNullaryOverride.value) {
if (other.paramss.isEmpty && !member.paramss.isEmpty) {
unit.warning(member.pos, "non-nullary method overrides nullary method")
@@ -508,6 +509,14 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
}
}
+
+ def checkOverrideDeprecated() {
+ if (other.hasDeprecatedOverridingAnnotation) {
+ val suffix = other.deprecatedOverridingMessage map (": " + _) getOrElse ""
+ val msg = s"overriding ${other.fullLocationString} is deprecated$suffix"
+ unit.deprecationWarning(member.pos, msg)
+ }
+ }
}
val opc = new overridingPairs.Cursor(clazz)
@@ -1197,6 +1206,23 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
case _ =>
}
+ // SI-6276 warn for `def foo = foo` or `val bar: X = bar`, which come up more frequently than you might think.
+ def checkInfiniteLoop(valOrDef: ValOrDefDef) {
+ def callsSelf = valOrDef.rhs match {
+ case t @ (Ident(_) | Select(This(_), _)) =>
+ t hasSymbolWhich (_.accessedOrSelf == valOrDef.symbol)
+ case _ => false
+ }
+ val trivialInifiniteLoop = (
+ !valOrDef.isErroneous
+ && !valOrDef.symbol.isValueParameter
+ && valOrDef.symbol.paramss.isEmpty
+ && callsSelf
+ )
+ if (trivialInifiniteLoop)
+ unit.warning(valOrDef.rhs.pos, s"${valOrDef.symbol.fullLocationString} does nothing other than call itself recursively")
+ }
+
// Transformation ------------------------------------------------------------
/* Convert a reference to a case factory of type `tpe` to a new of the class it produces. */
@@ -1640,6 +1666,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
case ValDef(_, _, _, _) | DefDef(_, _, _, _, _, _) =>
checkDeprecatedOvers(tree)
+ checkInfiniteLoop(tree.asInstanceOf[ValOrDefDef])
if (settings.warnNullaryUnit.value)
checkNullaryMethodReturnType(sym)
if (settings.warnInaccessible.value) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index d227f485c2..67afb0c118 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -63,7 +63,7 @@ trait SyntheticMethods extends ast.TreeDSL {
// in the original order.
def accessors = clazz.caseFieldAccessors sortBy { acc =>
originalAccessors indexWhere { orig =>
- (acc.name == orig.name) || (acc.name startsWith (orig.name append "$").asInstanceOf[Name]) // [Eugene] why do we need this cast?
+ (acc.name == orig.name) || (acc.name startsWith (orig.name append "$"))
}
}
val arity = accessors.size
@@ -87,7 +87,7 @@ trait SyntheticMethods extends ast.TreeDSL {
)
def forwardToRuntime(method: Symbol): Tree =
- forwardMethod(method, getMember(ScalaRunTimeModule, (method.name prepend "_").asInstanceOf[Name]))(mkThis :: _) // [Eugene] why do we need this cast?
+ forwardMethod(method, getMember(ScalaRunTimeModule, (method.name prepend "_")))(mkThis :: _)
def callStaticsMethod(name: String)(args: Tree*): Tree = {
val method = termMember(RuntimeStaticsModule, name)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 9cf5d42e00..d90141b732 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1577,6 +1577,12 @@ trait Typers extends Modes with Adaptations with Tags {
if (psym.isFinal)
pending += ParentFinalInheritanceError(parent, psym)
+ if (psym.hasDeprecatedInheritanceAnnotation) {
+ val suffix = psym.deprecatedInheritanceMessage map (": " + _) getOrElse ""
+ val msg = s"inheritance from ${psym.fullLocationString} is deprecated$suffix"
+ unit.deprecationWarning(parent.pos, msg)
+ }
+
if (psym.isSealed && !phase.erasedTypes)
if (context.unit.source.file == psym.sourceFile)
psym addChild context.owner
@@ -1871,7 +1877,7 @@ trait Typers extends Modes with Adaptations with Tags {
* @param rhs ...
*/
def computeParamAliases(clazz: Symbol, vparamss: List[List[ValDef]], rhs: Tree) {
- log("computing param aliases for "+clazz+":"+clazz.primaryConstructor.tpe+":"+rhs)//debug
+ debuglog(s"computing param aliases for $clazz:${clazz.primaryConstructor.tpe}:$rhs")
def decompose(call: Tree): (Tree, List[Tree]) = call match {
case Apply(fn, args) =>
val (superConstr, args1) = decompose(fn)
@@ -2395,7 +2401,7 @@ trait Typers extends Modes with Adaptations with Tags {
else targs.init
def mkParams(methodSym: Symbol, formals: List[Type] = deriveFormals) =
- if (formals.isEmpty) { MissingParameterTypeAnonMatchError(tree, pt); Nil }
+ if (formals.isEmpty || !formals.forall(isFullyDefined)) { MissingParameterTypeAnonMatchError(tree, pt); Nil }
else methodSym newSyntheticValueParams formals
def mkSel(params: List[Symbol]) =
@@ -2743,12 +2749,18 @@ trait Typers extends Modes with Adaptations with Tags {
// this code by associating defaults and companion objects
// with the original tree instead of the new symbol.
def matches(stat: Tree, synt: Tree) = (stat, synt) match {
+ // synt is default arg for stat
case (DefDef(_, statName, _, _, _, _), DefDef(mods, syntName, _, _, _, _)) =>
mods.hasDefaultFlag && syntName.toString.startsWith(statName.toString)
+ // synt is companion module
case (ClassDef(_, className, _, _), ModuleDef(_, moduleName, _)) =>
className.toTermName == moduleName
+ // synt is implicit def for implicit class (#6278)
+ case (ClassDef(cmods, cname, _, _), DefDef(dmods, dname, _, _, _, _)) =>
+ cmods.isImplicit && dmods.isImplicit && cname.toTermName == dname
+
case _ => false
}
@@ -3432,7 +3444,7 @@ trait Typers extends Modes with Adaptations with Tags {
}
if (hasError) annotationError
- else AnnotationInfo(annType, List(), nvPairs map {p => (p._1.asInstanceOf[Name], p._2.get)}).setOriginal(Apply(typedFun, args).setPos(ann.pos)) // [Eugene] why do we need this cast?
+ else AnnotationInfo(annType, List(), nvPairs map {p => (p._1, p._2.get)}).setOriginal(Apply(typedFun, args).setPos(ann.pos))
}
} else if (requireJava) {
reportAnnotationError(NestedAnnotationError(ann, annType))
@@ -3811,18 +3823,23 @@ trait Typers extends Modes with Adaptations with Tags {
* - simplest solution: have two method calls
*
*/
- def mkInvoke(cxTree: Tree, tree: Tree, qual: Tree, name: Name): Option[Tree] =
+ def mkInvoke(cxTree: Tree, tree: Tree, qual: Tree, name: Name): Option[Tree] = {
+ debuglog(s"mkInvoke($cxTree, $tree, $qual, $name)")
acceptsApplyDynamicWithType(qual, name) map { tp =>
// tp eq NoType => can call xxxDynamic, but not passing any type args (unless specified explicitly by the user)
// in scala-virtualized, when not NoType, tp is passed as type argument (for selection on a staged Struct)
- // strip off type application -- we're not doing much with outer, so don't bother preserving cxTree's attributes etc
- val (outer, explicitTargs) = cxTree match {
- case TypeApply(fun, targs) => (fun, targs)
- case Apply(TypeApply(fun, targs), args) => (Apply(fun, args), targs)
- case t => (t, Nil)
+ // strip off type application -- we're not doing much with outer,
+ // so don't bother preserving cxTree's attributes etc
+ val cxTree1 = cxTree match {
+ case t: ValOrDefDef => t.rhs
+ case t => t
+ }
+ val (outer, explicitTargs) = cxTree1 match {
+ case TypeApply(fun, targs) => (fun, targs)
+ case Apply(TypeApply(fun, targs), args) => (Apply(fun, args), targs)
+ case t => (t, Nil)
}
-
@inline def hasNamedArg(as: List[Tree]) = as.collectFirst{case AssignOrNamedArg(lhs, rhs) =>}.nonEmpty
// note: context.tree includes at most one Apply node
@@ -3847,6 +3864,7 @@ trait Typers extends Modes with Adaptations with Tags {
atPos(qual.pos)(Apply(tappSel, List(Literal(Constant(name.decode)))))
}
+ }
}
@inline final def deindentTyping() = context.typingIndentLevel -= 2
diff --git a/src/library/scala/collection/GenIterableViewLike.scala b/src/library/scala/collection/GenIterableViewLike.scala
index 9e3927eaf4..142561df20 100644
--- a/src/library/scala/collection/GenIterableViewLike.scala
+++ b/src/library/scala/collection/GenIterableViewLike.scala
@@ -25,6 +25,7 @@ self =>
def iterator: Iterator[B]
override def foreach[U](f: B => U): Unit = iterator foreach f
override def toString = viewToString
+ override def isEmpty = !iterator.hasNext
}
trait EmptyView extends Transformed[Nothing] with super.EmptyView {
diff --git a/src/library/scala/concurrent/Awaitable.scala b/src/library/scala/concurrent/Awaitable.scala
index 99bdfbc5a9..655115349a 100644
--- a/src/library/scala/concurrent/Awaitable.scala
+++ b/src/library/scala/concurrent/Awaitable.scala
@@ -16,15 +16,34 @@ import scala.concurrent.util.Duration
trait Awaitable[+T] {
/**
- * Should throw [[scala.concurrent.TimeoutException]] if it times out
+ * Await the "resolved" state of this Awaitable.
* This method should not be called directly.
+ *
+ * @param atMost
+ * maximum wait time, which may be negative (no waiting is done),
+ * [[Duration.Inf]] for unbounded waiting, or a finite positive
+ * duration
+ * @return the Awaitable itself
+ * @throws InterruptedException if the wait call was interrupted
+ * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready
+ * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]]
*/
@throws(classOf[TimeoutException])
+ @throws(classOf[InterruptedException])
def ready(atMost: Duration)(implicit permit: CanAwait): this.type
/**
- * Throws exceptions if it cannot produce a T within the specified time.
+ * Await and return the result of this Awaitable, which is either of type T or a thrown exception (any Throwable).
* This method should not be called directly.
+ *
+ * @param atMost
+ * maximum wait time, which may be negative (no waiting is done),
+ * [[Duration.Inf]] for unbounded waiting, or a finite positive
+ * duration
+ * @return the value if the Awaitable was successful within the specific maximum wait time
+ * @throws InterruptedException if the wait call was interrupted
+ * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready
+ * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]]
*/
@throws(classOf[Exception])
def result(atMost: Duration)(implicit permit: CanAwait): T
diff --git a/src/library/scala/concurrent/BlockContext.scala b/src/library/scala/concurrent/BlockContext.scala
index 640560a174..83333a9e94 100644
--- a/src/library/scala/concurrent/BlockContext.scala
+++ b/src/library/scala/concurrent/BlockContext.scala
@@ -8,9 +8,6 @@
package scala.concurrent
-import java.lang.Thread
-import scala.concurrent.util.Duration
-
/**
* A context to be notified by `scala.concurrent.blocking` when
* a thread is about to block. In effect this trait provides
diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala
index 1be6050303..844ec14241 100644
--- a/src/library/scala/concurrent/ExecutionContext.scala
+++ b/src/library/scala/concurrent/ExecutionContext.scala
@@ -10,7 +10,6 @@ package scala.concurrent
import java.util.concurrent.{ ExecutorService, Executor }
-import scala.concurrent.util.Duration
import scala.annotation.implicitNotFound
import scala.util.Try
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index bc0b437a33..a5d9cdd5d1 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -16,7 +16,6 @@ import java.lang.{ Iterable => JIterable }
import java.util.{ LinkedList => JLinkedList }
import java.util.concurrent.atomic.{ AtomicReferenceFieldUpdater, AtomicInteger, AtomicBoolean }
-import scala.concurrent.util.Duration
import scala.util.control.NonFatal
import scala.Option
import scala.util.{Try, Success, Failure}
diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
index 875a558887..c517a05a81 100644
--- a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
+++ b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
@@ -14,7 +14,6 @@ import java.util.concurrent.{ LinkedBlockingQueue, Callable, Executor, ExecutorS
import java.util.Collection
import scala.concurrent.forkjoin._
import scala.concurrent.{ BlockContext, ExecutionContext, Awaitable, CanAwait, ExecutionContextExecutor, ExecutionContextExecutorService }
-import scala.concurrent.util.Duration
import scala.util.control.NonFatal
diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala
index b19bed004b..f7ab85dc0c 100644
--- a/src/library/scala/concurrent/impl/Promise.scala
+++ b/src/library/scala/concurrent/impl/Promise.scala
@@ -12,7 +12,7 @@ package scala.concurrent.impl
import java.util.concurrent.TimeUnit.NANOSECONDS
import scala.concurrent.{ ExecutionContext, CanAwait, OnCompleteRunnable, TimeoutException, ExecutionException }
-import scala.concurrent.util.Duration
+import scala.concurrent.util.{ Duration, Deadline }
import scala.annotation.tailrec
import scala.util.control.NonFatal
import scala.util.{ Try, Success, Failure }
@@ -64,30 +64,41 @@ private[concurrent] object Promise {
protected final def tryAwait(atMost: Duration): Boolean = {
@tailrec
- def awaitUnsafe(waitTimeNanos: Long): Boolean = {
- if (value.isEmpty && waitTimeNanos > 0) {
- val ms = NANOSECONDS.toMillis(waitTimeNanos)
- val ns = (waitTimeNanos % 1000000l).toInt // as per object.wait spec
- val start = System.nanoTime()
- try {
- synchronized {
- if (!isCompleted) wait(ms, ns) // previously - this was a `while`, ending up in an infinite loop
- }
- } catch {
- case e: InterruptedException =>
- }
+ def awaitUnsafe(deadline: Deadline, nextWait: Duration): Boolean = {
+ if (!isCompleted && nextWait > Duration.Zero) {
+ val ms = nextWait.toMillis
+ val ns = (nextWait.toNanos % 1000000l).toInt // as per object.wait spec
+
+ synchronized { if (!isCompleted) wait(ms, ns) }
- awaitUnsafe(waitTimeNanos - (System.nanoTime() - start))
+ awaitUnsafe(deadline, deadline.timeLeft)
} else
isCompleted
}
- awaitUnsafe(if (atMost.isFinite) atMost.toNanos else Long.MaxValue)
+ @tailrec
+ def awaitUnbounded(): Boolean = {
+ if (isCompleted) true
+ else {
+ synchronized { if (!isCompleted) wait() }
+ awaitUnbounded()
+ }
+ }
+
+ if (atMost eq Duration.Undefined)
+ throw new IllegalArgumentException("cannot wait for Undefined period")
+ else if (atMost <= Duration.Zero)
+ isCompleted
+ else if (atMost == Duration.Inf)
+ awaitUnbounded()
+ else
+ awaitUnsafe(atMost.fromNow, atMost)
}
@throws(classOf[TimeoutException])
+ @throws(classOf[InterruptedException])
def ready(atMost: Duration)(implicit permit: CanAwait): this.type =
if (isCompleted || tryAwait(atMost)) this
- else throw new TimeoutException("Futures timed out after [" + atMost.toMillis + "] milliseconds")
+ else throw new TimeoutException("Futures timed out after [" + atMost + "]")
@throws(classOf[Exception])
def result(atMost: Duration)(implicit permit: CanAwait): T =
diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala
index a2ef42fac8..1d06341d4d 100644
--- a/src/library/scala/concurrent/package.scala
+++ b/src/library/scala/concurrent/package.scala
@@ -67,26 +67,39 @@ package concurrent {
*/
object Await {
/**
+ * Await the "resolved" state of this Awaitable.
* Invokes ready() on the awaitable, properly wrapped by a call to `scala.concurrent.blocking`.
- * ready() blocks until the awaitable has completed or the timeout expires.
*
- * Throws a TimeoutException if the timeout expires, as that is in the contract of `Awaitable.ready`.
- * @param awaitable the `Awaitable` on which `ready` is to be called
- * @param atMost the maximum timeout for which to wait
- * @return the result of `awaitable.ready` which is defined to be the awaitable itself.
+ * @param awaitable
+ * the `Awaitable` on which `ready` is to be called
+ * @param atMost
+ * maximum wait time, which may be negative (no waiting is done),
+ * [[Duration.Inf]] for unbounded waiting, or a finite positive
+ * duration
+ * @return the awaitable itself
+ * @throws InterruptedException if the wait call was interrupted
+ * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready
+ * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]]
*/
@throws(classOf[TimeoutException])
+ @throws(classOf[InterruptedException])
def ready[T](awaitable: Awaitable[T], atMost: Duration): awaitable.type =
blocking(awaitable.ready(atMost)(AwaitPermission))
/**
+ * Await and return the result of this Awaitable, which is either of type T or a thrown exception (any Throwable).
* Invokes result() on the awaitable, properly wrapped by a call to `scala.concurrent.blocking`.
- * result() blocks until the awaitable has completed or the timeout expires.
*
- * Throws a TimeoutException if the timeout expires, or any exception thrown by `Awaitable.result`.
- * @param awaitable the `Awaitable` on which `result` is to be called
- * @param atMost the maximum timeout for which to wait
- * @return the result of `awaitable.result`
+ * @param awaitable
+ * the `Awaitable` on which `result` is to be called
+ * @param atMost
+ * maximum wait time, which may be negative (no waiting is done),
+ * [[Duration.Inf]] for unbounded waiting, or a finite positive
+ * duration
+ * @return the value if the Awaitable was successful within the specific maximum wait time
+ * @throws InterruptedException if the wait call was interrupted
+ * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready
+ * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]]
*/
@throws(classOf[Exception])
def result[T](awaitable: Awaitable[T], atMost: Duration): T =
diff --git a/src/library/scala/deprecatedInheritance.scala b/src/library/scala/deprecatedInheritance.scala
new file mode 100644
index 0000000000..ca1b586223
--- /dev/null
+++ b/src/library/scala/deprecatedInheritance.scala
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2012, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala
+
+/** An annotation that designates that inheriting from a class is deprecated.
+ *
+ * This is usually done to warn about a non-final class being made final in a future version.
+ * Sub-classing such a class then generates a warning.
+ *
+ * @param message the message to print during compilation if the class was sub-classed
+ * @param since a string identifying the first version in which inheritance was deprecated
+ * @since 2.10
+ * @see [[scala.deprecatedOverriding]]
+ */
+private[scala] // for now, this needs to be generalized to communicate other modifier deltas
+class deprecatedInheritance(message: String = "", since: String = "") extends annotation.StaticAnnotation
diff --git a/src/library/scala/deprecatedOverriding.scala b/src/library/scala/deprecatedOverriding.scala
new file mode 100644
index 0000000000..566cb59431
--- /dev/null
+++ b/src/library/scala/deprecatedOverriding.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2012, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala
+
+/** An annotation that designates that overriding a member is deprecated.
+ *
+ * Overriding such a member in a sub-class then generates a warning.
+ *
+ * @param message the message to print during compilation if the member was overridden
+ * @param since a string identifying the first version in which overriding was deprecated
+ * @since 2.10
+ * @see [[scala.deprecatedInheritance]]
+ */
+private[scala] // for the same reasons as deprecatedInheritance
+class deprecatedOverriding(message: String = "", since: String = "") extends annotation.StaticAnnotation
diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala
index 8669b2e2e8..a475d663f4 100644
--- a/src/library/scala/math/BigDecimal.scala
+++ b/src/library/scala/math/BigDecimal.scala
@@ -159,6 +159,7 @@ object BigDecimal {
* @author Stephane Micheloud
* @version 1.0
*/
+@deprecatedInheritance("This class will me made final.", "2.10.0")
class BigDecimal(
val bigDecimal: BigDec,
val mc: MathContext)
diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala
index 09e8ae2026..e354117e14 100644
--- a/src/library/scala/math/BigInt.scala
+++ b/src/library/scala/math/BigInt.scala
@@ -114,6 +114,7 @@ object BigInt {
* @author Martin Odersky
* @version 1.0, 15/07/2003
*/
+@deprecatedInheritance("This class will me made final.", "2.10.0")
class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericConversions with Serializable {
/** Returns the hash code for this BigInt. */
override def hashCode(): Int =
diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala
index 5255c44f10..e42c89d21f 100644
--- a/src/library/scala/reflect/ClassTag.scala
+++ b/src/library/scala/reflect/ClassTag.scala
@@ -2,7 +2,7 @@ package scala.reflect
import java.lang.{ Class => jClass }
import language.{implicitConversions, existentials}
-import scala.runtime.ScalaRunTime.arrayClass
+import scala.runtime.ScalaRunTime.{ arrayClass, arrayElementClass }
/** A `ClassTag[T]` wraps a runtime class, which can be accessed via the `runtimeClass` method.
*
@@ -54,35 +54,59 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial
* `SomeExtractor(...)` is turned into `ct(SomeExtractor(...))` if `T` in `SomeExtractor.unapply(x: T)`
* is uncheckable, but we have an instance of `ClassTag[T]`.
*/
- def unapply(x: Any): Option[T] = if (x != null && runtimeClass.isAssignableFrom(x.getClass)) Some(x.asInstanceOf[T]) else None
+ def unapply(x: Any): Option[T] = unapply_impl(x)
+ def unapply(x: Byte): Option[T] = unapply_impl(x)
+ def unapply(x: Short): Option[T] = unapply_impl(x)
+ def unapply(x: Char): Option[T] = unapply_impl(x)
+ def unapply(x: Int): Option[T] = unapply_impl(x)
+ def unapply(x: Long): Option[T] = unapply_impl(x)
+ def unapply(x: Float): Option[T] = unapply_impl(x)
+ def unapply(x: Double): Option[T] = unapply_impl(x)
+ def unapply(x: Boolean): Option[T] = unapply_impl(x)
+ def unapply(x: Unit): Option[T] = unapply_impl(x)
+
+ private def unapply_impl[U: ClassTag](x: U): Option[T] =
+ if (x == null) None
+ else {
+ val staticClass = classTag[U].runtimeClass
+ val dynamicClass = x.getClass
+ val effectiveClass = if (staticClass.isPrimitive) staticClass else dynamicClass
+ val conforms = runtimeClass.isAssignableFrom(effectiveClass)
+ if (conforms) Some(x.asInstanceOf[T]) else None
+ }
/** case class accessories */
override def canEqual(x: Any) = x.isInstanceOf[ClassTag[_]]
override def equals(x: Any) = x.isInstanceOf[ClassTag[_]] && this.runtimeClass == x.asInstanceOf[ClassTag[_]].runtimeClass
override def hashCode = scala.runtime.ScalaRunTime.hash(runtimeClass)
- override def toString = "ClassTag[" + runtimeClass + "]"
+ override def toString = {
+ def prettyprint(clazz: jClass[_]): String =
+ if (clazz.isArray) s"Array[${prettyprint(arrayElementClass(clazz))}]" else
+ clazz.getName
+ prettyprint(runtimeClass)
+ }
}
object ClassTag {
+ private val ObjectTYPE = classOf[java.lang.Object]
private val NothingTYPE = classOf[scala.runtime.Nothing$]
private val NullTYPE = classOf[scala.runtime.Null$]
- private val ObjectTYPE = classOf[java.lang.Object]
- val Byte : ClassTag[scala.Byte] = new ClassTag[scala.Byte]{ def runtimeClass = java.lang.Byte.TYPE; private def readResolve() = ClassTag.Byte }
- val Short : ClassTag[scala.Short] = new ClassTag[scala.Short]{ def runtimeClass = java.lang.Short.TYPE; private def readResolve() = ClassTag.Short }
- val Char : ClassTag[scala.Char] = new ClassTag[scala.Char]{ def runtimeClass = java.lang.Character.TYPE; private def readResolve() = ClassTag.Char }
- val Int : ClassTag[scala.Int] = new ClassTag[scala.Int]{ def runtimeClass = java.lang.Integer.TYPE; private def readResolve() = ClassTag.Int }
- val Long : ClassTag[scala.Long] = new ClassTag[scala.Long]{ def runtimeClass = java.lang.Long.TYPE; private def readResolve() = ClassTag.Long }
- val Float : ClassTag[scala.Float] = new ClassTag[scala.Float]{ def runtimeClass = java.lang.Float.TYPE; private def readResolve() = ClassTag.Float }
- val Double : ClassTag[scala.Double] = new ClassTag[scala.Double]{ def runtimeClass = java.lang.Double.TYPE; private def readResolve() = ClassTag.Double }
- val Boolean : ClassTag[scala.Boolean] = new ClassTag[scala.Boolean]{ def runtimeClass = java.lang.Boolean.TYPE; private def readResolve() = ClassTag.Boolean }
- val Unit : ClassTag[scala.Unit] = new ClassTag[scala.Unit]{ def runtimeClass = java.lang.Void.TYPE; private def readResolve() = ClassTag.Unit }
- val Any : ClassTag[scala.Any] = new ClassTag[scala.Any]{ def runtimeClass = ObjectTYPE; private def readResolve() = ClassTag.Any }
- val Object : ClassTag[java.lang.Object] = new ClassTag[java.lang.Object]{ def runtimeClass = ObjectTYPE; private def readResolve() = ClassTag.Object }
- val AnyVal : ClassTag[scala.AnyVal] = ClassTag.Object.asInstanceOf[ClassTag[scala.AnyVal]]
- val AnyRef : ClassTag[scala.AnyRef] = ClassTag.Object.asInstanceOf[ClassTag[scala.AnyRef]]
- val Nothing : ClassTag[scala.Nothing] = new ClassTag[scala.Nothing]{ def runtimeClass = NothingTYPE; private def readResolve() = ClassTag.Nothing }
- val Null : ClassTag[scala.Null] = new ClassTag[scala.Null]{ def runtimeClass = NullTYPE; private def readResolve() = ClassTag.Null }
+ val Byte : ClassTag[scala.Byte] = Manifest.Byte
+ val Short : ClassTag[scala.Short] = Manifest.Short
+ val Char : ClassTag[scala.Char] = Manifest.Char
+ val Int : ClassTag[scala.Int] = Manifest.Int
+ val Long : ClassTag[scala.Long] = Manifest.Long
+ val Float : ClassTag[scala.Float] = Manifest.Float
+ val Double : ClassTag[scala.Double] = Manifest.Double
+ val Boolean : ClassTag[scala.Boolean] = Manifest.Boolean
+ val Unit : ClassTag[scala.Unit] = Manifest.Unit
+ val Any : ClassTag[scala.Any] = Manifest.Any
+ val Object : ClassTag[java.lang.Object] = Manifest.Object
+ val AnyVal : ClassTag[scala.AnyVal] = Manifest.AnyVal
+ val AnyRef : ClassTag[scala.AnyRef] = Manifest.AnyRef
+ val Nothing : ClassTag[scala.Nothing] = Manifest.Nothing
+ val Null : ClassTag[scala.Null] = Manifest.Null
def apply[T](runtimeClass1: jClass[_]): ClassTag[T] =
runtimeClass1 match {
@@ -96,6 +120,8 @@ object ClassTag {
case java.lang.Boolean.TYPE => ClassTag.Boolean.asInstanceOf[ClassTag[T]]
case java.lang.Void.TYPE => ClassTag.Unit.asInstanceOf[ClassTag[T]]
case ObjectTYPE => ClassTag.Object.asInstanceOf[ClassTag[T]]
+ case NothingTYPE => ClassTag.Nothing.asInstanceOf[ClassTag[T]]
+ case NullTYPE => ClassTag.Null.asInstanceOf[ClassTag[T]]
case _ => new ClassTag[T]{ def runtimeClass = runtimeClass1 }
}
diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala
index 9347f5b6bb..f2a23f4372 100644
--- a/src/library/scala/reflect/Manifest.scala
+++ b/src/library/scala/reflect/Manifest.scala
@@ -155,28 +155,34 @@ object ManifestFactory {
private def readResolve(): Any = Manifest.Unit
}
- val Any: Manifest[scala.Any] = new PhantomManifest[scala.Any]("Any") {
+ private val ObjectTYPE = classOf[java.lang.Object]
+ private val NothingTYPE = classOf[scala.runtime.Nothing$]
+ private val NullTYPE = classOf[scala.runtime.Null$]
+
+ val Any: Manifest[scala.Any] = new PhantomManifest[scala.Any](ObjectTYPE, "Any") {
override def <:<(that: ClassManifest[_]): Boolean = (that eq this)
private def readResolve(): Any = Manifest.Any
}
- val Object: Manifest[java.lang.Object] = new PhantomManifest[java.lang.Object]("Object") {
+ val Object: Manifest[java.lang.Object] = new PhantomManifest[java.lang.Object](ObjectTYPE, "Object") {
override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any)
private def readResolve(): Any = Manifest.Object
}
- val AnyVal: Manifest[scala.AnyVal] = new PhantomManifest[scala.AnyVal]("AnyVal") {
+ val AnyRef: Manifest[scala.AnyRef] = Object.asInstanceOf[Manifest[scala.AnyRef]]
+
+ val AnyVal: Manifest[scala.AnyVal] = new PhantomManifest[scala.AnyVal](ObjectTYPE, "AnyVal") {
override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any)
private def readResolve(): Any = Manifest.AnyVal
}
- val Null: Manifest[scala.Null] = new PhantomManifest[scala.Null]("Null") {
+ val Null: Manifest[scala.Null] = new PhantomManifest[scala.Null](NullTYPE, "Null") {
override def <:<(that: ClassManifest[_]): Boolean =
(that ne null) && (that ne Nothing) && !(that <:< AnyVal)
private def readResolve(): Any = Manifest.Null
}
- val Nothing: Manifest[scala.Nothing] = new PhantomManifest[scala.Nothing]("Nothing") {
+ val Nothing: Manifest[scala.Nothing] = new PhantomManifest[scala.Nothing](NothingTYPE, "Nothing") {
override def <:<(that: ClassManifest[_]): Boolean = (that ne null)
private def readResolve(): Any = Manifest.Nothing
}
@@ -211,7 +217,8 @@ object ManifestFactory {
def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
new ClassTypeManifest[T](Some(prefix), clazz, args.toList)
- private abstract class PhantomManifest[T](override val toString: String) extends ClassTypeManifest[T](None, classOf[java.lang.Object], Nil) {
+ private abstract class PhantomManifest[T](_runtimeClass: Predef.Class[_],
+ override val toString: String) extends ClassTypeManifest[T](None, _runtimeClass, Nil) {
override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef]
override val hashCode = System.identityHashCode(this)
}
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index e5f5e9dc5d..a8635151ff 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -167,35 +167,6 @@ object ScalaRunTime {
def checkInitialized[T <: AnyRef](x: T): T =
if (x == null) throw new UninitializedError else x
- abstract class Try[+A] {
- def Catch[B >: A](handler: PartialFunction[Throwable, B]): B
- def Finally(fin: => Unit): A
- }
-
- def Try[A](block: => A): Try[A] = new Try[A] with Runnable {
- private var result: A = _
- private var exception: Throwable =
- try { run() ; null }
- catch {
- case e: ControlThrowable => throw e // don't catch non-local returns etc
- case e: Throwable => e
- }
-
- def run() { result = block }
-
- def Catch[B >: A](handler: PartialFunction[Throwable, B]): B =
- if (exception == null) result
- else if (handler isDefinedAt exception) handler(exception)
- else throw exception
-
- def Finally(fin: => Unit): A = {
- fin
-
- if (exception == null) result
- else throw exception
- }
- }
-
def _toString(x: Product): String =
x.productIterator.mkString(x.productPrefix + "(", ",", ")")
diff --git a/src/library/scala/util/Try.scala b/src/library/scala/util/Try.scala
index f381a18b0c..7afbfcdd66 100644
--- a/src/library/scala/util/Try.scala
+++ b/src/library/scala/util/Try.scala
@@ -52,6 +52,8 @@ import language.implicitConversions
* ''Note'': only non-fatal exceptions are caught by the combinators on `Try` (see [[scala.util.control.NonFatal]]).
* Serious system errors, on the other hand, will be thrown.
*
+ * ''Note:'': all Try combinators will catch exceptions and return failure unless otherwise specified in the documentation.
+ *
* `Try` comes to the Scala standard library after years of use as an integral part of Twitter's stack.
*
* @author based on Twitter's original implementation in com.twitter.util.
@@ -68,12 +70,19 @@ sealed abstract class Try[+T] {
def isSuccess: Boolean
/** Returns the value from this `Success` or the given `default` argument if this is a `Failure`.
+ *
+ * ''Note:'': This will throw an exception if it is not a success and default throws an exception.
*/
- def getOrElse[U >: T](default: => U) = if (isSuccess) get else default
+ def getOrElse[U >: T](default: => U): U =
+ if (isSuccess) get else default
/** Returns this `Try` if it's a `Success` or the given `default` argument if this is a `Failure`.
*/
- def orElse[U >: T](default: => Try[U]) = if (isSuccess) this else default
+ def orElse[U >: T](default: => Try[U]): Try[U] =
+ try if (isSuccess) this else default
+ catch {
+ case NonFatal(e) => Failure(e)
+ }
/** Returns the value from this `Success` or throws the exception if this is a `Failure`.
*/
@@ -81,6 +90,8 @@ sealed abstract class Try[+T] {
/**
* Applies the given function `f` if this is a `Success`, otherwise returns `Unit` if this is a `Failure`.
+ *
+ * ''Note:'' If `f` throws, then this method may throw an exception.
*/
def foreach[U](f: T => U): Unit
@@ -114,7 +125,7 @@ sealed abstract class Try[+T] {
/**
* Returns `None` if this is a `Failure` or a `Some` containing the value if this is a `Success`.
*/
- def toOption = if (isSuccess) Some(get) else None
+ def toOption: Option[T] = if (isSuccess) Some(get) else None
/**
* Transforms a nested `Try`, ie, a `Try` of type `Try[Try[T]]`,
@@ -131,20 +142,25 @@ sealed abstract class Try[+T] {
/** Completes this `Try` by applying the function `f` to this if this is of type `Failure`, or conversely, by applying
* `s` if this is a `Success`.
*/
- def transform[U](s: T => Try[U], f: Throwable => Try[U]): Try[U] = this match {
- case Success(v) => s(v)
- case Failure(e) => f(e)
- }
+ def transform[U](s: T => Try[U], f: Throwable => Try[U]): Try[U] =
+ try this match {
+ case Success(v) => s(v)
+ case Failure(e) => f(e)
+ } catch {
+ case NonFatal(e) => Failure(e)
+ }
}
object Try {
-
- def apply[T](r: => T): Try[T] = {
- try { Success(r) } catch {
+ /** Constructs a `Try` using the by-name parameter. This
+ * method will ensure any non-fatal exception is caught and a
+ * `Failure` object is returned.
+ */
+ def apply[T](r: => T): Try[T] =
+ try Success(r) catch {
case NonFatal(e) => Failure(e)
}
- }
}
@@ -152,24 +168,25 @@ final case class Failure[+T](val exception: Throwable) extends Try[T] {
def isFailure: Boolean = true
def isSuccess: Boolean = false
def recoverWith[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U] =
- if (f.isDefinedAt(exception)) f(exception) else this
+ try {
+ if (f isDefinedAt exception) f(exception) else this
+ } catch {
+ case NonFatal(e) => Failure(e)
+ }
def get: T = throw exception
- def flatMap[U](f: T => Try[U]): Try[U] = Failure[U](exception)
- def flatten[U](implicit ev: T <:< Try[U]): Try[U] = Failure[U](exception)
- def foreach[U](f: T => U): Unit = {}
- def map[U](f: T => U): Try[U] = Failure[U](exception)
+ def flatMap[U](f: T => Try[U]): Try[U] = this.asInstanceOf[Try[U]]
+ def flatten[U](implicit ev: T <:< Try[U]): Try[U] = this.asInstanceOf[Try[U]]
+ def foreach[U](f: T => U): Unit = ()
+ def map[U](f: T => U): Try[U] = this.asInstanceOf[Try[U]]
def filter(p: T => Boolean): Try[T] = this
- def recover[U >: T](rescueException: PartialFunction[Throwable, U]): Try[U] = {
+ def recover[U >: T](rescueException: PartialFunction[Throwable, U]): Try[U] =
try {
- if (rescueException.isDefinedAt(exception)) {
+ if (rescueException isDefinedAt exception) {
Try(rescueException(exception))
- } else {
- this
- }
+ } else this
} catch {
case NonFatal(e) => Failure(e)
}
- }
def failed: Try[Throwable] = Success(exception)
}
@@ -177,7 +194,7 @@ final case class Failure[+T](val exception: Throwable) extends Try[T] {
final case class Success[+T](value: T) extends Try[T] {
def isFailure: Boolean = false
def isSuccess: Boolean = true
- def recoverWith[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U] = Success(value)
+ def recoverWith[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U] = this
def get = value
def flatMap[U](f: T => Try[U]): Try[U] =
try f(value)
diff --git a/src/partest/scala/tools/partest/nest/RunnerManager.scala b/src/partest/scala/tools/partest/nest/RunnerManager.scala
index 20d61d0831..376e0e9bdb 100644
--- a/src/partest/scala/tools/partest/nest/RunnerManager.scala
+++ b/src/partest/scala/tools/partest/nest/RunnerManager.scala
@@ -312,8 +312,8 @@ class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunP
val testFiles = dir.listFiles.toList filter isJavaOrScala
def isInGroup(f: File, num: Int) = SFile(f).stripExtension endsWith ("_" + num)
- val groups = (0 to 9).toList map (num => testFiles filter (f => isInGroup(f, num)))
- val noGroupSuffix = testFiles filterNot (groups.flatten contains)
+ val groups = (0 to 9).toList map (num => (testFiles filter (f => isInGroup(f, num))).sorted)
+ val noGroupSuffix = (testFiles filterNot (groups.flatten contains)).sorted
noGroupSuffix :: groups filterNot (_.isEmpty)
}
diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala
index d167099979..1fbbc0c0a4 100644
--- a/src/reflect/scala/reflect/api/Symbols.scala
+++ b/src/reflect/scala/reflect/api/Symbols.scala
@@ -140,18 +140,6 @@ trait Symbols extends base.Symbols { self: Universe =>
*/
def isErroneous : Boolean
- /** Can this symbol be loaded by a reflective mirror?
- *
- * Scalac relies on `ScalaSignature' annotation to retain symbols across compilation runs.
- * Such annotations (also called "pickles") are applied on top-level classes and include information
- * about all symbols reachable from the annotee. However, local symbols (e.g. classes or definitions local to a block)
- * are typically unreachable and information about them gets lost.
- *
- * This method is useful for macro writers who wish to save certain ASTs to be used at runtime.
- * With `isLocatable' it's possible to check whether a tree can be retained as is, or it needs special treatment.
- */
- def isLocatable: Boolean
-
/** Is this symbol static (i.e. with no outer instance)?
* Q: When exactly is a sym marked as STATIC?
* A: If it's a member of a toplevel object, or of an object contained in a toplevel object, or any number of levels deep.
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index c21ebfe997..15b74058b7 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -277,6 +277,7 @@ trait Definitions extends api.StandardDefinitions {
anyval
}).asInstanceOf[ClassSymbol]
lazy val AnyValTpe = definitions.AnyValClass.toTypeConstructor
+ def AnyVal_getClass = getMemberMethod(AnyValClass, nme.getClass_)
// bottom types
lazy val RuntimeNothingClass = getClassByName(fulltpnme.RuntimeNothing)
@@ -940,6 +941,8 @@ trait Definitions extends api.StandardDefinitions {
lazy val CloneableAttr = requiredClass[scala.annotation.cloneable]
lazy val DeprecatedAttr = requiredClass[scala.deprecated]
lazy val DeprecatedNameAttr = requiredClass[scala.deprecatedName]
+ lazy val DeprecatedInheritanceAttr = requiredClass[scala.deprecatedInheritance]
+ lazy val DeprecatedOverridingAttr = requiredClass[scala.deprecatedOverriding]
lazy val NativeAttr = requiredClass[scala.native]
lazy val RemoteAttr = requiredClass[scala.remote]
lazy val ScalaInlineClass = requiredClass[scala.inline]
diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala
index 2fdf27d847..3f85db0f54 100644
--- a/src/reflect/scala/reflect/internal/Names.scala
+++ b/src/reflect/scala/reflect/internal/Names.scala
@@ -149,11 +149,15 @@ trait Names extends api.Names with LowPriorityNames {
type ThisNameType >: Null <: Name
protected[this] def thisName: ThisNameType
+ // Note that "Name with ThisNameType" should be redundant
+ // because ThisNameType <: Name, but due to SI-6161 the
+ // compile loses track of this fact.
+
/** Index into name table */
def start: Int = index
/** The next name in the same hash bucket. */
- def next: ThisNameType
+ def next: Name with ThisNameType
/** The length of this name. */
final def length: Int = len
@@ -169,13 +173,13 @@ trait Names extends api.Names with LowPriorityNames {
def bothNames: List[Name] = List(toTermName, toTypeName)
/** Return the subname with characters from from to to-1. */
- def subName(from: Int, to: Int): ThisNameType
+ def subName(from: Int, to: Int): Name with ThisNameType
/** Return a new name of the same variety. */
- def newName(str: String): ThisNameType
+ def newName(str: String): Name with ThisNameType
/** Return a new name based on string transformation. */
- def mapName(f: String => String): ThisNameType = newName(f(toString))
+ def mapName(f: String => String): Name with ThisNameType = newName(f(toString))
/** Copy bytes of this name to buffer cs, starting at position `offset`. */
final def copyChars(cs: Array[Char], offset: Int) =
diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala
index 4100e97cdd..2424e75949 100644
--- a/src/reflect/scala/reflect/internal/SymbolTable.scala
+++ b/src/reflect/scala/reflect/internal/SymbolTable.scala
@@ -47,6 +47,8 @@ abstract class SymbolTable extends macros.Universe
def globalError(msg: String): Unit = abort(msg)
def abort(msg: String): Nothing = throw new FatalError(supplementErrorMessage(msg))
+ def shouldLogAtThisPhase = false
+
@deprecated("Give us a reason", "2.10.0")
def abort(): Nothing = abort("unknown error")
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 3548657c04..b1e81de037 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -114,7 +114,12 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// with the proper specific type.
def rawname: NameType
def name: NameType
- def name_=(n: Name): Unit
+ def name_=(n: Name): Unit = {
+ if (shouldLogAtThisPhase) {
+ val msg = s"Renaming $fullLocationString to $n"
+ if (isSpecialized) debuglog(msg) else log(msg)
+ }
+ }
def asNameType(n: Name): NameType
private[this] var _rawowner = initOwner // Syncnote: need not be protected, as only assignment happens in owner_=, which is not exposed to api
@@ -697,6 +702,18 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def deprecationMessage = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 0)
def deprecationVersion = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 1)
def deprecatedParamName = getAnnotation(DeprecatedNameAttr) flatMap (_ symbolArg 0)
+ def hasDeprecatedInheritanceAnnotation
+ = hasAnnotation(DeprecatedInheritanceAttr)
+ def deprecatedInheritanceMessage
+ = getAnnotation(DeprecatedInheritanceAttr) flatMap (_ stringArg 0)
+ def deprecatedInheritanceVersion
+ = getAnnotation(DeprecatedInheritanceAttr) flatMap (_ stringArg 1)
+ def hasDeprecatedOverridingAnnotation
+ = hasAnnotation(DeprecatedOverridingAttr)
+ def deprecatedOverridingMessage
+ = getAnnotation(DeprecatedOverridingAttr) flatMap (_ stringArg 0)
+ def deprecatedOverridingVersion
+ = getAnnotation(DeprecatedOverridingAttr) flatMap (_ stringArg 1)
// !!! when annotation arguments are not literal strings, but any sort of
// assembly of strings, there is a fair chance they will turn up here not as
@@ -853,7 +870,16 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isInitialized: Boolean =
validTo != NoPeriod
- /** Determines whether this symbol can be loaded by subsequent reflective compilation */
+ /** Can this symbol be loaded by a reflective mirror?
+ *
+ * Scalac relies on `ScalaSignature' annotation to retain symbols across compilation runs.
+ * Such annotations (also called "pickles") are applied on top-level classes and include information
+ * about all symbols reachable from the annotee. However, local symbols (e.g. classes or definitions local to a block)
+ * are typically unreachable and information about them gets lost.
+ *
+ * This method is useful for macro writers who wish to save certain ASTs to be used at runtime.
+ * With `isLocatable' it's possible to check whether a tree can be retained as is, or it needs special treatment.
+ */
final def isLocatable: Boolean = {
if (this == NoSymbol) return false
if (isRoot || isRootPackage) return true
@@ -945,7 +971,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** If this symbol has an expanded name, its original name, otherwise its name itself.
* @see expandName
*/
- def originalName: Name = nme.originalName(name)
+ def originalName: Name = nme.originalName(nme.dropLocalSuffix(name))
/** The name of the symbol before decoding, e.g. `\$eq\$eq` instead of `==`.
*/
@@ -990,7 +1016,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
private def fullNameInternal(separator: Char): Name = (
if (isRoot || isRootPackage || this == NoSymbol) name
else if (owner.isEffectiveRoot) name
- else effectiveOwner.enclClass.fullNameAsName(separator) append separator append name
+ else ((effectiveOwner.enclClass.fullNameAsName(separator) append separator): Name) append name
)
def fullNameAsName(separator: Char): Name = nme.dropLocalSuffix(fullNameInternal(separator))
@@ -1790,26 +1816,16 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
} else owner.enclosingTopLevelClass
/** Is this symbol defined in the same scope and compilation unit as `that` symbol? */
- def isCoDefinedWith(that: Symbol) = {
- (this.rawInfo ne NoType) &&
- (this.effectiveOwner == that.effectiveOwner) && {
- !this.effectiveOwner.isPackageClass ||
- (this.sourceFile eq null) ||
- (that.sourceFile eq null) ||
- (this.sourceFile == that.sourceFile) || {
- // recognize companion object in separate file and fail, else compilation
- // appears to succeed but highly opaque errors come later: see bug #1286
- if (this.sourceFile.path != that.sourceFile.path) {
- // The cheaper check can be wrong: do the expensive normalization
- // before failing.
- if (this.sourceFile.canonicalPath != that.sourceFile.canonicalPath)
- throw InvalidCompanions(this, that)
- }
-
- false
- }
- }
- }
+ def isCoDefinedWith(that: Symbol) = (
+ (this.rawInfo ne NoType)
+ && (this.effectiveOwner == that.effectiveOwner)
+ && ( !this.effectiveOwner.isPackageClass
+ || (this.sourceFile eq null)
+ || (that.sourceFile eq null)
+ || (this.sourceFile.path == that.sourceFile.path) // Cheap possibly wrong check, then expensive normalization
+ || (this.sourceFile.canonicalPath == that.sourceFile.canonicalPath)
+ )
+ )
/** The internal representation of classes and objects:
*
@@ -2188,10 +2204,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* If settings.Yshowsymkinds, adds abbreviated symbol kind.
*/
def nameString: String = (
- if (!settings.uniqid.value && !settings.Yshowsymkinds.value) "" + decodedName
- else if (settings.uniqid.value && !settings.Yshowsymkinds.value) decodedName + "#" + id
- else if (!settings.uniqid.value && settings.Yshowsymkinds.value) decodedName + "#" + abbreviatedKindString
- else decodedName + "#" + id + "#" + abbreviatedKindString
+ if (!settings.uniqid.value && !settings.Yshowsymkinds.value) "" + originalName.decode
+ else if (settings.uniqid.value && !settings.Yshowsymkinds.value) originalName.decode + "#" + id
+ else if (!settings.uniqid.value && settings.Yshowsymkinds.value) originalName.decode + "#" + abbreviatedKindString
+ else originalName.decode + "#" + id + "#" + abbreviatedKindString
)
def fullNameString: String = {
@@ -2301,9 +2317,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
if (Statistics.hotEnabled) Statistics.incCounter(nameCount)
_rawname
}
- def name_=(name: Name) {
+ override def name_=(name: Name) {
if (name != rawname) {
- log("Renaming %s %s %s to %s".format(shortSymbolClass, debugFlagString, rawname, name))
+ super.name_=(name) // logging
changeNameInOwners(name)
_rawname = name.toTermName
}
@@ -2604,9 +2620,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// TODO - don't allow names to be renamed in this unstructured a fashion.
// Rename as little as possible. Enforce invariants on all renames.
- def name_=(name: Name) {
+ override def name_=(name: Name) {
if (name != rawname) {
- log("Renaming %s %s %s to %s".format(shortSymbolClass, debugFlagString, rawname, name))
+ super.name_=(name) // logging
changeNameInOwners(name)
_rawname = name.toTypeName
}
@@ -3077,7 +3093,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def asNameType(n: Name) = n.toTermName
def rawname = nme.NO_NAME
def name = nme.NO_NAME
- def name_=(n: Name) = abort("Cannot set NoSymbol's name to " + n)
+ override def name_=(n: Name) = abort("Cannot set NoSymbol's name to " + n)
synchronized {
setInfo(NoType)
@@ -3202,13 +3218,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
if (settings.debug.value) printStackTrace()
}
- case class InvalidCompanions(sym1: Symbol, sym2: Symbol) extends Throwable({
- "Companions '" + sym1 + "' and '" + sym2 + "' must be defined in same file:\n" +
- " Found in " + sym1.sourceFile.canonicalPath + " and " + sym2.sourceFile.canonicalPath
- }) {
- override def toString = getMessage
- }
-
/** A class for type histories */
private sealed case class TypeHistory(var validFrom: Period, info: Type, prev: TypeHistory) {
assert((prev eq null) || phaseId(validFrom) > phaseId(prev.validFrom), this)
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index c266e26895..df44cf234e 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -317,25 +317,6 @@ trait Types extends api.Types { self: SymbolTable =>
def substituteSymbols(from: List[Symbol], to: List[Symbol]): Type = substSym(from, to)
def substituteTypes(from: List[Symbol], to: List[Type]): Type = subst(from, to)
- def isConcrete = {
- def notConcreteSym(sym: Symbol) =
- sym.isAbstractType && !sym.isExistential
-
- def notConcreteTpe(tpe: Type): Boolean = tpe match {
- case ThisType(_) => false
- case SuperType(_, _) => false
- case SingleType(pre, sym) => notConcreteSym(sym)
- case ConstantType(_) => false
- case TypeRef(_, sym, args) => notConcreteSym(sym) || (args exists notConcreteTpe)
- case RefinedType(_, _) => false
- case ExistentialType(_, _) => false
- case AnnotatedType(_, tp, _) => notConcreteTpe(tp)
- case _ => true
- }
-
- !notConcreteTpe(this)
- }
-
// the only thingies that we want to splice are: 1) type parameters, 2) abstract type members
// the thingies that we don't want to splice are: 1) concrete types (obviously), 2) existential skolems
def isSpliceable = {
@@ -3473,9 +3454,9 @@ trait Types extends api.Types { self: SymbolTable =>
}
/** A temporary type representing the erasure of a user-defined value type.
- * Created during phase reasure, eliminated again in posterasure.
- * @param sym The value class symbol
- * @param underlying The underlying type before erasure
+ * Created during phase erasure, eliminated again in posterasure.
+ *
+ * @param original The underlying type before erasure
*/
abstract case class ErasedValueType(original: TypeRef) extends UniqueType {
override def safeToString = "ErasedValueType("+original+")"
diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala
index ffb5608fd2..0e76b711de 100644
--- a/test/files/jvm/scala-concurrent-tck.scala
+++ b/test/files/jvm/scala-concurrent-tck.scala
@@ -11,6 +11,8 @@ import scala.concurrent.{
import scala.concurrent.{ future, promise, blocking }
import scala.util.{ Try, Success, Failure }
import scala.concurrent.util.Duration
+import scala.reflect.{ classTag, ClassTag }
+import scala.tools.partest.TestUtil.intercept
trait TestBase {
@@ -19,7 +21,7 @@ trait TestBase {
body(() => sv put true)
sv.take(2000)
}
-
+
// def assert(cond: => Boolean) {
// try {
// Predef.assert(cond)
@@ -663,6 +665,29 @@ trait FutureProjections extends TestBase {
case nsee: NoSuchElementException => done()
}
}
+
+ def testAwaitPositiveDuration(): Unit = once { done =>
+ val p = Promise[Int]()
+ val f = p.future
+ future {
+ intercept[IllegalArgumentException] { Await.ready(f, Duration.Undefined) }
+ p.success(0)
+ Await.ready(f, Duration.Zero)
+ Await.ready(f, Duration(500, "ms"))
+ Await.ready(f, Duration.Inf)
+ done()
+ } onFailure { case x => throw x }
+ }
+
+ def testAwaitNegativeDuration(): Unit = once { done =>
+ val f = Promise().future
+ future {
+ intercept[TimeoutException] { Await.ready(f, Duration.Zero) }
+ intercept[TimeoutException] { Await.ready(f, Duration.MinusInf) }
+ intercept[TimeoutException] { Await.ready(f, Duration(-500, "ms")) }
+ done()
+ } onFailure { case x => throw x }
+ }
testFailedFailureOnComplete()
testFailedFailureOnSuccess()
@@ -670,6 +695,8 @@ trait FutureProjections extends TestBase {
testFailedSuccessOnFailure()
testFailedFailureAwait()
testFailedSuccessAwait()
+ testAwaitPositiveDuration()
+ testAwaitNegativeDuration()
}
diff --git a/test/files/neg/override.check b/test/files/neg/override.check
index fc152cb3b1..8be98bf4d0 100644
--- a/test/files/neg/override.check
+++ b/test/files/neg/override.check
@@ -1,5 +1,5 @@
override.scala:9: error: overriding type T in trait A with bounds >: Int <: Int;
type T in trait B with bounds >: String <: String has incompatible type
- lazy val x : A with B = x
+ lazy val x : A with B = {println(""); x}
^
one error found
diff --git a/test/files/neg/override.scala b/test/files/neg/override.scala
index 3e589b52e3..7975516061 100755
--- a/test/files/neg/override.scala
+++ b/test/files/neg/override.scala
@@ -6,7 +6,7 @@ trait X {
trait Y extends X {
trait B { type T >: String <: String }
- lazy val x : A with B = x
+ lazy val x : A with B = {println(""); x}
n = "foo"
}
diff --git a/test/files/neg/t5031.check b/test/files/neg/t5031.check
index 8983d8daf9..2f1090c321 100644
--- a/test/files/neg/t5031.check
+++ b/test/files/neg/t5031.check
@@ -1,5 +1,5 @@
-Id.scala:3: error: Companions 'class Test' and 'object Test' must be defined in same file:
+package.scala:2: error: Companions 'class Test' and 'object Test' must be defined in same file:
Found in t5031/package.scala and t5031/Id.scala
-object Test
- ^
+ class Test
+ ^
one error found
diff --git a/test/files/neg/t5031b.check b/test/files/neg/t5031b.check
new file mode 100644
index 0000000000..3bc2284a4d
--- /dev/null
+++ b/test/files/neg/t5031b.check
@@ -0,0 +1,5 @@
+b.scala:3: error: Companions 'class Bippy' and 'object Bippy' must be defined in same file:
+ Found in t5031b/a.scala and t5031b/b.scala
+object Bippy
+ ^
+one error found
diff --git a/test/files/neg/t5031b/a.scala b/test/files/neg/t5031b/a.scala
new file mode 100644
index 0000000000..0ab9aa9769
--- /dev/null
+++ b/test/files/neg/t5031b/a.scala
@@ -0,0 +1,3 @@
+package foo
+
+class Bippy
diff --git a/test/files/neg/t5031b/b.scala b/test/files/neg/t5031b/b.scala
new file mode 100644
index 0000000000..bdef237af5
--- /dev/null
+++ b/test/files/neg/t5031b/b.scala
@@ -0,0 +1,3 @@
+package foo
+
+object Bippy
diff --git a/test/files/neg/t6162-inheritance.check b/test/files/neg/t6162-inheritance.check
new file mode 100644
index 0000000000..a7d3cc3238
--- /dev/null
+++ b/test/files/neg/t6162-inheritance.check
@@ -0,0 +1,10 @@
+t6162-inheritance.scala:6: error: inheritance from class Foo in package t6126 is deprecated: `Foo` will be made final in a future version.
+class SubFoo extends Foo
+ ^
+t6162-inheritance.scala:11: error: inheritance from trait T in package t6126 is deprecated
+object SubT extends T
+ ^
+t6162-inheritance.scala:17: error: inheritance from trait S in package t6126 is deprecated
+ new S {
+ ^
+three errors found
diff --git a/test/files/neg/t6162-inheritance.flags b/test/files/neg/t6162-inheritance.flags
new file mode 100644
index 0000000000..65faf53579
--- /dev/null
+++ b/test/files/neg/t6162-inheritance.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -deprecation \ No newline at end of file
diff --git a/test/files/neg/t6162-inheritance.scala b/test/files/neg/t6162-inheritance.scala
new file mode 100644
index 0000000000..7b47b9285a
--- /dev/null
+++ b/test/files/neg/t6162-inheritance.scala
@@ -0,0 +1,19 @@
+package scala.t6126
+
+@deprecatedInheritance("`Foo` will be made final in a future version.", "2.10.0")
+class Foo
+
+class SubFoo extends Foo
+
+@deprecatedInheritance()
+trait T
+
+object SubT extends T
+
+@deprecatedInheritance()
+trait S
+
+object O {
+ new S {
+ }
+}
diff --git a/test/files/neg/t6162-overriding.check b/test/files/neg/t6162-overriding.check
new file mode 100644
index 0000000000..e774888d36
--- /dev/null
+++ b/test/files/neg/t6162-overriding.check
@@ -0,0 +1,7 @@
+t6162-overriding.scala:14: error: overriding method bar in class Bar is deprecated: `bar` will be made private in a future version.
+ override def bar = 43
+ ^
+t6162-overriding.scala:15: error: overriding method baz in class Bar is deprecated
+ override def baz = 43
+ ^
+two errors found
diff --git a/test/files/neg/t6162-overriding.flags b/test/files/neg/t6162-overriding.flags
new file mode 100644
index 0000000000..65faf53579
--- /dev/null
+++ b/test/files/neg/t6162-overriding.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -deprecation \ No newline at end of file
diff --git a/test/files/neg/t6162-overriding.scala b/test/files/neg/t6162-overriding.scala
new file mode 100644
index 0000000000..4cab0c2dee
--- /dev/null
+++ b/test/files/neg/t6162-overriding.scala
@@ -0,0 +1,17 @@
+package scala.t6162
+
+class Bar {
+ @deprecatedOverriding("`bar` will be made private in a future version.", "2.10.0")
+ def bar = 42
+
+ @deprecatedOverriding()
+ def baz = 42
+
+ def baz(a: Any) = 0
+}
+
+class SubBar extends Bar {
+ override def bar = 43
+ override def baz = 43
+ override def baz(a: Any) = 43 // okay
+}
diff --git a/test/files/neg/t6258.check b/test/files/neg/t6258.check
new file mode 100644
index 0000000000..73363d8280
--- /dev/null
+++ b/test/files/neg/t6258.check
@@ -0,0 +1,16 @@
+t6258.scala:2: error: missing parameter type for expanded function
+The argument types of an anonymous function must be fully known. (SLS 8.5)
+Expected type was: PartialFunction[?, Int]
+ val f : PartialFunction[_, Int] = { case a : Int => a } // undefined param
+ ^
+t6258.scala:5: error: missing parameter type for expanded function
+The argument types of an anonymous function must be fully known. (SLS 8.5)
+Expected type was: PartialFunction[?,Int]
+ foo { case a : Int => a } // undefined param
+ ^
+t6258.scala:22: error: missing parameter type for expanded function
+The argument types of an anonymous function must be fully known. (SLS 8.5)
+Expected type was: PartialFunction[?,Any]
+ bar[M[Any]] (foo { // undefined param
+ ^
+three errors found
diff --git a/test/files/neg/t6258.scala b/test/files/neg/t6258.scala
new file mode 100644
index 0000000000..5046a4750a
--- /dev/null
+++ b/test/files/neg/t6258.scala
@@ -0,0 +1,25 @@
+object Test {
+ val f : PartialFunction[_, Int] = { case a : Int => a } // undefined param
+
+ def foo[A](pf: PartialFunction[A, Int]) {};
+ foo { case a : Int => a } // undefined param
+
+ val g : PartialFunction[Int, _] = { case a : Int => a } // okay
+}
+
+
+// Another variation, seen in the wild with Specs2.
+class X {
+ trait Matcher[-T]
+
+ def bar[T](m: Matcher[T]) = null
+ def bar[T](i: Int) = null
+
+ def foo[T](p: PartialFunction[T, Any]): Matcher[T] = null
+
+ case class M[X](a: X)
+
+ bar[M[Any]] (foo { // undefined param
+ case M(_) => null
+ })
+}
diff --git a/test/files/neg/t6276.check b/test/files/neg/t6276.check
new file mode 100644
index 0000000000..0b3dfa5531
--- /dev/null
+++ b/test/files/neg/t6276.check
@@ -0,0 +1,19 @@
+t6276.scala:4: error: method a in class C does nothing other than call itself recursively
+ def a: Any = a // warn
+ ^
+t6276.scala:5: error: value b in class C does nothing other than call itself recursively
+ val b: Any = b // warn
+ ^
+t6276.scala:7: error: method c in class C does nothing other than call itself recursively
+ def c: Any = this.c // warn
+ ^
+t6276.scala:8: error: method d in class C does nothing other than call itself recursively
+ def d: Any = C.this.d // warn
+ ^
+t6276.scala:13: error: method a does nothing other than call itself recursively
+ def a: Any = a // warn
+ ^
+t6276.scala:22: error: method a does nothing other than call itself recursively
+ def a = a // warn
+ ^
+6 errors found
diff --git a/test/files/neg/t6276.flags b/test/files/neg/t6276.flags
new file mode 100644
index 0000000000..85d8eb2ba2
--- /dev/null
+++ b/test/files/neg/t6276.flags
@@ -0,0 +1 @@
+-Xfatal-warnings
diff --git a/test/files/neg/t6276.scala b/test/files/neg/t6276.scala
new file mode 100644
index 0000000000..bd0a473f71
--- /dev/null
+++ b/test/files/neg/t6276.scala
@@ -0,0 +1,44 @@
+object Test {
+ def foo(a: Int, b: Int, c: Int) {
+ class C {
+ def a: Any = a // warn
+ val b: Any = b // warn
+
+ def c: Any = this.c // warn
+ def d: Any = C.this.d // warn
+ }
+
+ def method {
+ // method local
+ def a: Any = a // warn
+ }
+
+ trait T {
+ def a: Any
+ }
+
+ new T {
+ // inherited return type
+ def a = a // warn
+ }
+
+ // no warnings below
+ new {
+ def a: Any = {println(""); a}
+ val b: Any = {println(""); b}
+ def c(i: Int): Any = c(i - 0)
+ }
+
+ class D {
+ def other: D = null
+ def foo: Any = other.foo
+ }
+
+ class E {
+ def foo: Any = 0
+ class D extends E {
+ override def foo: Any = E.this.foo
+ }
+ }
+ }
+}
diff --git a/test/files/neg/t6335.check b/test/files/neg/t6335.check
new file mode 100644
index 0000000000..1727a05eb2
--- /dev/null
+++ b/test/files/neg/t6335.check
@@ -0,0 +1,9 @@
+t6335.scala:6: error: method Z is defined twice
+ conflicting symbols both originated in file 't6335.scala'
+ implicit class Z[A](val i: A) { def zz = i }
+ ^
+t6335.scala:3: error: method X is defined twice
+ conflicting symbols both originated in file 't6335.scala'
+ implicit class X(val x: Int) { def xx = x }
+ ^
+two errors found
diff --git a/test/files/neg/t6335.scala b/test/files/neg/t6335.scala
new file mode 100644
index 0000000000..5c41e81ef5
--- /dev/null
+++ b/test/files/neg/t6335.scala
@@ -0,0 +1,7 @@
+object ImplicitClass {
+ def X(i: Int) {}
+ implicit class X(val x: Int) { def xx = x }
+
+ def Z[A](i: A) {}
+ implicit class Z[A](val i: A) { def zz = i }
+} \ No newline at end of file
diff --git a/test/files/pos/t6278-synth-def.scala b/test/files/pos/t6278-synth-def.scala
new file mode 100644
index 0000000000..b8b660fbe3
--- /dev/null
+++ b/test/files/pos/t6278-synth-def.scala
@@ -0,0 +1,30 @@
+
+package t6278
+
+import language.implicitConversions
+
+object test {
+ def ok() {
+ class Foo(val i: Int) {
+ def foo[A](body: =>A): A = body
+ }
+ implicit def toFoo(i: Int): Foo = new Foo(i)
+
+ val k = 1
+ k foo println("k?")
+ val j = 2
+ }
+ def nope() {
+ implicit class Foo(val i: Int) {
+ def foo[A](body: =>A): A = body
+ }
+
+ val k = 1
+ k foo println("k?")
+ //lazy
+ val j = 2
+ }
+ def main(args: Array[String]) {
+ ok(); nope()
+ }
+}
diff --git a/test/files/pos/t6335.scala b/test/files/pos/t6335.scala
new file mode 100644
index 0000000000..50e34092d1
--- /dev/null
+++ b/test/files/pos/t6335.scala
@@ -0,0 +1,25 @@
+object E extends Z {
+ def X = 3
+ implicit class X(val i: Int) {
+ def xx = i
+ }
+
+ def Y(a: Any) = 0
+ object Y
+ implicit class Y(val i: String) { def yy = i }
+
+ implicit class Z(val i: Boolean) { def zz = i }
+}
+
+trait Z {
+ def Z = 0
+}
+
+object Test {
+ import E._
+ 0.xx
+
+ "".yy
+
+ true.zz
+}
diff --git a/test/files/run/classtags_core.check b/test/files/run/classtags_core.check
index 6519db2178..5a9b41fd6d 100644
--- a/test/files/run/classtags_core.check
+++ b/test/files/run/classtags_core.check
@@ -1,30 +1,30 @@
true
-ClassTag[byte]
+Byte
true
-ClassTag[short]
+Short
true
-ClassTag[char]
+Char
true
-ClassTag[int]
+Int
true
-ClassTag[long]
+Long
true
-ClassTag[float]
+Float
true
-ClassTag[double]
+Double
true
-ClassTag[boolean]
+Boolean
true
-ClassTag[void]
+Unit
true
-ClassTag[class java.lang.Object]
+Any
true
-ClassTag[class java.lang.Object]
+AnyVal
true
-ClassTag[class java.lang.Object]
+Object
true
-ClassTag[class java.lang.Object]
+Object
true
-ClassTag[class scala.runtime.Null$]
+Null
true
-ClassTag[class scala.runtime.Nothing$]
+Nothing
diff --git a/test/files/run/classtags_multi.check b/test/files/run/classtags_multi.check
index 3a7f16c3a0..68cee4841d 100644
--- a/test/files/run/classtags_multi.check
+++ b/test/files/run/classtags_multi.check
@@ -1,5 +1,5 @@
-ClassTag[int]
-ClassTag[class [I]
-ClassTag[class [[I]
-ClassTag[class [[[I]
-ClassTag[class [[[[I]
+Int
+Array[int]
+Array[Array[int]]
+Array[Array[Array[int]]]
+Array[Array[Array[Array[int]]]]
diff --git a/test/files/run/compiler-asSeenFrom.check b/test/files/run/compiler-asSeenFrom.check
index 96e257d303..47d40b0331 100644
--- a/test/files/run/compiler-asSeenFrom.check
+++ b/test/files/run/compiler-asSeenFrom.check
@@ -269,8 +269,8 @@ value jZ { // after parser
value jZ { // after explicitouter
protected val $outer: D.this.type
- val ll$D$J$$$outer(): D.this.type
- val ll$C$I$$$outer(): C.this.type
+ val $outer(): D.this.type
+ val $outer(): C.this.type
def thisI(): I.this.type
def thisC(): C.this.type
def t2(): T2
@@ -279,9 +279,9 @@ value jZ { // after explicitouter
value jZ { // after erasure
protected val $outer: ll.D
- val ll$D$J$$$outer(): ll.D
+ val $outer(): ll.D
protected val $outer: ll.C
- val ll$C$I$$$outer(): ll.C
+ val $outer(): ll.C
def thisI(): ll.C#I
def thisC(): ll.C
def t2(): Object
@@ -290,9 +290,9 @@ value jZ { // after erasure
value jZ { // after flatten
protected val $outer: ll.D
- val ll$D$J$$$outer(): ll.D
+ val $outer(): ll.D
protected val $outer: ll.C
- val ll$C$I$$$outer(): ll.C
+ val $outer(): ll.C
def thisI(): ll.C#C$I
def thisC(): ll.C
def t2(): Object
diff --git a/test/files/run/getClassTest-valueClass.check b/test/files/run/getClassTest-valueClass.check
new file mode 100644
index 0000000000..7608d92b4e
--- /dev/null
+++ b/test/files/run/getClassTest-valueClass.check
@@ -0,0 +1,2 @@
+int
+class V
diff --git a/test/files/run/getClassTest-valueClass.scala b/test/files/run/getClassTest-valueClass.scala
new file mode 100644
index 0000000000..05a116dfff
--- /dev/null
+++ b/test/files/run/getClassTest-valueClass.scala
@@ -0,0 +1,10 @@
+class V(val x: Int) extends AnyVal
+
+object Test {
+ def main(args: Array[String]) = {
+ val v = new V(2)
+ val s: Any = 2
+ println(2.getClass)
+ println(v.getClass)
+ }
+}
diff --git a/test/files/run/interop_classtags_are_classmanifests.check b/test/files/run/interop_classtags_are_classmanifests.check
index 7a0a829af2..c07ed0e657 100644
--- a/test/files/run/interop_classtags_are_classmanifests.check
+++ b/test/files/run/interop_classtags_are_classmanifests.check
@@ -1,3 +1,3 @@
-ClassTag[int]
-ClassTag[class java.lang.String]
-ClassTag[class [I]
+Int
+java.lang.String
+Array[int]
diff --git a/test/files/run/macro-expand-tparams-implicit.check b/test/files/run/macro-expand-tparams-implicit.check
index 80c6b826ba..1c1a785706 100644
--- a/test/files/run/macro-expand-tparams-implicit.check
+++ b/test/files/run/macro-expand-tparams-implicit.check
@@ -1,2 +1,2 @@
TypeTag[Int]
-TypeTag[String]
+AbsTypeTag[String]
diff --git a/test/files/run/macro-expand-tparams-prefix-a.check b/test/files/run/macro-expand-tparams-prefix-a.check
index 6c23b47d64..6a7f9c5f52 100644
--- a/test/files/run/macro-expand-tparams-prefix-a.check
+++ b/test/files/run/macro-expand-tparams-prefix-a.check
@@ -1,4 +1,4 @@
TypeTag[Int]
TypeTag[Int]
-TypeTag[String]
+AbsTypeTag[String]
TypeTag[Boolean]
diff --git a/test/files/run/macro-expand-tparams-prefix-b.check b/test/files/run/macro-expand-tparams-prefix-b.check
index 67dabff11e..daae32bd0a 100644
--- a/test/files/run/macro-expand-tparams-prefix-b.check
+++ b/test/files/run/macro-expand-tparams-prefix-b.check
@@ -1,2 +1,2 @@
TypeTag[Boolean] TypeTag[Int]
-TypeTag[Boolean] TypeTag[String]
+TypeTag[Boolean] AbsTypeTag[String]
diff --git a/test/files/run/macro-expand-tparams-prefix-c1.check b/test/files/run/macro-expand-tparams-prefix-c1.check
index 8d1c4e3416..5356b3e6d1 100644
--- a/test/files/run/macro-expand-tparams-prefix-c1.check
+++ b/test/files/run/macro-expand-tparams-prefix-c1.check
@@ -1,3 +1,3 @@
TypeTag[Int]
-TypeTag[String]
+AbsTypeTag[String]
TypeTag[Boolean]
diff --git a/test/files/run/macro-expand-tparams-prefix-c2.check b/test/files/run/macro-expand-tparams-prefix-c2.check
index 8d1c4e3416..5356b3e6d1 100644
--- a/test/files/run/macro-expand-tparams-prefix-c2.check
+++ b/test/files/run/macro-expand-tparams-prefix-c2.check
@@ -1,3 +1,3 @@
TypeTag[Int]
-TypeTag[String]
+AbsTypeTag[String]
TypeTag[Boolean]
diff --git a/test/files/run/macro-undetparams-macroitself.check b/test/files/run/macro-undetparams-macroitself.check
index 80c6b826ba..1c1a785706 100644
--- a/test/files/run/macro-undetparams-macroitself.check
+++ b/test/files/run/macro-undetparams-macroitself.check
@@ -1,2 +1,2 @@
TypeTag[Int]
-TypeTag[String]
+AbsTypeTag[String]
diff --git a/test/files/run/t5881.check b/test/files/run/t5881.check
index 477fb935a8..8e596e9323 100644
--- a/test/files/run/t5881.check
+++ b/test/files/run/t5881.check
@@ -1,2 +1,2 @@
-ClassTag[class scala.collection.immutable.List]
-ClassTag[class scala.collection.immutable.List]
+scala.collection.immutable.List
+scala.collection.immutable.List
diff --git a/test/files/run/t6246.check b/test/files/run/t6246.check
new file mode 100644
index 0000000000..9532185ead
--- /dev/null
+++ b/test/files/run/t6246.check
@@ -0,0 +1,90 @@
+runtimeClass = byte, toString = Byte
+true
+true
+true
+false
+true
+false
+false
+false
+false
+runtimeClass = short, toString = Short
+true
+true
+true
+false
+true
+false
+false
+false
+false
+runtimeClass = char, toString = Char
+true
+true
+true
+false
+true
+false
+false
+false
+false
+runtimeClass = int, toString = Int
+true
+true
+true
+false
+true
+false
+false
+false
+false
+runtimeClass = long, toString = Long
+true
+true
+true
+false
+true
+false
+false
+false
+false
+runtimeClass = float, toString = Float
+true
+true
+true
+false
+true
+false
+false
+false
+false
+runtimeClass = double, toString = Double
+true
+true
+true
+false
+true
+false
+false
+false
+false
+runtimeClass = void, toString = Unit
+true
+true
+true
+false
+true
+false
+false
+false
+false
+runtimeClass = boolean, toString = Boolean
+true
+true
+true
+false
+true
+false
+false
+false
+false \ No newline at end of file
diff --git a/test/files/run/t6246.scala b/test/files/run/t6246.scala
new file mode 100644
index 0000000000..28765e1adf
--- /dev/null
+++ b/test/files/run/t6246.scala
@@ -0,0 +1,26 @@
+import scala.reflect.{ClassTag, classTag}
+
+object Test extends App {
+ def testValueClass(tag: ClassTag[_]) {
+ println(s"runtimeClass = ${tag.runtimeClass}, toString = ${tag.toString}")
+ println(tag <:< tag)
+ println(tag <:< ClassTag.AnyVal)
+ println(tag <:< ClassTag.Any)
+ println(tag <:< ClassTag.Nothing)
+ println(ClassTag.Nothing <:< tag)
+ println(tag <:< ClassTag.Null)
+ println(ClassTag.Null <:< tag)
+ println(tag <:< ClassTag.Object)
+ println(ClassTag.Object <:< tag)
+ }
+
+ testValueClass(ClassTag.Byte)
+ testValueClass(ClassTag.Short)
+ testValueClass(ClassTag.Char)
+ testValueClass(ClassTag.Int)
+ testValueClass(ClassTag.Long)
+ testValueClass(ClassTag.Float)
+ testValueClass(ClassTag.Double)
+ testValueClass(ClassTag.Unit)
+ testValueClass(ClassTag.Boolean)
+} \ No newline at end of file
diff --git a/test/files/run/t6271.scala b/test/files/run/t6271.scala
new file mode 100644
index 0000000000..8ebf7ad8b5
--- /dev/null
+++ b/test/files/run/t6271.scala
@@ -0,0 +1,32 @@
+object Test extends App {
+ def filterIssue = {
+ val viewed : Iterable[Iterable[Int]] = List(List(0).view).view
+ val filtered = viewed flatMap { x => List( x filter (_ > 0) ) }
+ filtered.iterator.toIterable.flatten
+ }
+ def takenIssue = {
+ val viewed : Iterable[Iterable[Int]] = List(List(0).view).view
+ val filtered = viewed flatMap { x => List( x take 0 ) }
+ filtered.iterator.toIterable.flatten
+ }
+ def droppedIssue = {
+ val viewed : Iterable[Iterable[Int]] = List(List(0).view).view
+ val filtered = viewed flatMap { x => List( x drop 1 ) }
+ filtered.iterator.toIterable.flatten
+ }
+ def flatMappedIssue = {
+ val viewed : Iterable[Iterable[Int]] = List(List(0).view).view
+ val filtered = viewed flatMap { x => List( x flatMap (_ => List()) ) }
+ filtered.iterator.toIterable.flatten
+ }
+ def slicedIssue = {
+ val viewed : Iterable[Iterable[Int]] = List(List(0).view).view
+ val filtered = viewed flatMap { x => List( x slice (2,3) ) }
+ filtered.iterator.toIterable.flatten
+ }
+ filterIssue
+ takenIssue
+ droppedIssue
+ flatMappedIssue
+ slicedIssue
+}
diff --git a/test/files/run/t6318_derived.check b/test/files/run/t6318_derived.check
new file mode 100644
index 0000000000..ad43b6579b
--- /dev/null
+++ b/test/files/run/t6318_derived.check
@@ -0,0 +1,3 @@
+Some(X)
+true
+Some(X)
diff --git a/test/files/run/t6318_derived.scala b/test/files/run/t6318_derived.scala
new file mode 100644
index 0000000000..ccdc18daee
--- /dev/null
+++ b/test/files/run/t6318_derived.scala
@@ -0,0 +1,15 @@
+import scala.reflect.{ClassTag, classTag}
+
+object Test extends App {
+ def test[T: ClassTag](x: T) {
+ println(classTag[T].runtimeClass.isAssignableFrom(x.getClass))
+ println(classTag[T].unapply(x))
+ }
+
+ class X(val x: Int) extends AnyVal { override def toString = "X" }
+ val x = new X(1)
+ // the commented line crashes because of SI-6326
+ //println(classTag[X].runtimeClass.isAssignableFrom(x.getClass))
+ println(classTag[X].unapply(x))
+ test(x)
+} \ No newline at end of file
diff --git a/test/files/run/t6318_primitives.check b/test/files/run/t6318_primitives.check
new file mode 100644
index 0000000000..bb474c3bdc
--- /dev/null
+++ b/test/files/run/t6318_primitives.check
@@ -0,0 +1,36 @@
+true
+Some(1)
+false
+None
+true
+Some(1)
+false
+None
+true
+Some()
+false
+None
+true
+Some(1)
+false
+None
+true
+Some(1)
+false
+None
+true
+Some(1.0)
+false
+None
+true
+Some(1.0)
+false
+None
+true
+Some(true)
+false
+None
+true
+Some(())
+false
+None
diff --git a/test/files/run/t6318_primitives.scala b/test/files/run/t6318_primitives.scala
new file mode 100644
index 0000000000..30f27120b3
--- /dev/null
+++ b/test/files/run/t6318_primitives.scala
@@ -0,0 +1,71 @@
+import scala.reflect.{ClassTag, classTag}
+
+object Test extends App {
+ def test[T: ClassTag](x: T) {
+ println(classTag[T].runtimeClass.isAssignableFrom(x.getClass))
+ println(classTag[T].unapply(x))
+ }
+
+ {
+ val x = 1.toByte
+ println(ClassTag.Byte.runtimeClass.isAssignableFrom(x.getClass))
+ println(ClassTag.Byte.unapply(x))
+ test(x)
+ }
+
+ {
+ val x = 1.toShort
+ println(ClassTag.Short.runtimeClass.isAssignableFrom(x.getClass))
+ println(ClassTag.Short.unapply(x))
+ test(x)
+ }
+
+ {
+ val x = 1.toChar
+ println(ClassTag.Char.runtimeClass.isAssignableFrom(x.getClass))
+ println(ClassTag.Char.unapply(x))
+ test(x)
+ }
+
+ {
+ val x = 1.toInt
+ println(ClassTag.Int.runtimeClass.isAssignableFrom(x.getClass))
+ println(ClassTag.Int.unapply(x))
+ test(x)
+ }
+
+ {
+ val x = 1.toLong
+ println(ClassTag.Long.runtimeClass.isAssignableFrom(x.getClass))
+ println(ClassTag.Long.unapply(x))
+ test(x)
+ }
+
+ {
+ val x = 1.toFloat
+ println(ClassTag.Float.runtimeClass.isAssignableFrom(x.getClass))
+ println(ClassTag.Float.unapply(x))
+ test(x)
+ }
+
+ {
+ val x = 1.toDouble
+ println(ClassTag.Double.runtimeClass.isAssignableFrom(x.getClass))
+ println(ClassTag.Double.unapply(x))
+ test(x)
+ }
+
+ {
+ val x = true
+ println(ClassTag.Boolean.runtimeClass.isAssignableFrom(x.getClass))
+ println(ClassTag.Boolean.unapply(x))
+ test(x)
+ }
+
+ {
+ val x = ()
+ println(ClassTag.Unit.runtimeClass.isAssignableFrom(x.getClass))
+ println(ClassTag.Unit.unapply(x))
+ test(x)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6327.check b/test/files/run/t6327.check
new file mode 100644
index 0000000000..f7bacac931
--- /dev/null
+++ b/test/files/run/t6327.check
@@ -0,0 +1,4 @@
+A
+A
+A
+A
diff --git a/test/files/run/t6327.scala b/test/files/run/t6327.scala
new file mode 100644
index 0000000000..7683101f14
--- /dev/null
+++ b/test/files/run/t6327.scala
@@ -0,0 +1,22 @@
+import language._
+
+object Test extends App {
+
+ case class R[+T](s: String) { def x() = println(s) }
+
+ // Implicits in contention; StringR is nested to avoid ambiguity
+ object R { implicit val StringR = R[String]("A") }
+ implicit val Default = R[Any]("B")
+
+ class B() extends Dynamic {
+ def selectDynamic[T](f: String)(implicit r: R[T]): Unit = r.x()
+ }
+
+ val b = new B()
+
+ // These should all produce the same output, but they don't
+ b.selectDynamic[String]("baz")
+ b.baz[String]
+ val c = b.selectDynamic[String]("baz")
+ val d = b.baz[String]
+}
diff --git a/test/files/run/t6333.scala b/test/files/run/t6333.scala
new file mode 100644
index 0000000000..266d95ce69
--- /dev/null
+++ b/test/files/run/t6333.scala
@@ -0,0 +1,29 @@
+object Test extends App {
+ import util.Try
+
+ val a = "apple"
+ def fail: String = throw new Exception("Fail!")
+ def argh: Try[String] = throw new Exception("Argh!")
+
+ // No throw tests
+ def tryMethods(expr: => String): Unit = {
+ Try(expr) orElse argh
+ Try(expr).transform(_ => argh, _ => argh)
+ Try(expr).recoverWith { case e if (a == fail) => Try(a) }
+ Try(expr).recoverWith { case _ => argh }
+ Try(expr).getOrElse(a)
+ // TODO - Fail getOrElse?
+ Try(expr) orElse argh
+ Try(expr) orElse Try(a)
+ Try(expr) map (_ => fail)
+ Try(expr) map (_ => a)
+ Try(expr) flatMap (_ => argh)
+ Try(expr) flatMap (_ => Try(a))
+ Try(expr) filter (_ => throw new Exception("O NOES"))
+ Try(expr) filter (_ => true)
+ Try(expr) recover { case _ => fail }
+ Try(expr).failed
+ }
+ tryMethods(a)
+ tryMethods(fail)
+}
diff --git a/test/files/run/valueclasses-classtag-basic.check b/test/files/run/valueclasses-classtag-basic.check
index 0c13986b32..554c75e074 100644
--- a/test/files/run/valueclasses-classtag-basic.check
+++ b/test/files/run/valueclasses-classtag-basic.check
@@ -1 +1 @@
-ClassTag[class Foo]
+Foo
diff --git a/test/files/run/valueclasses-classtag-existential.check b/test/files/run/valueclasses-classtag-existential.check
index 95e94e7aee..15ac02630f 100644
--- a/test/files/run/valueclasses-classtag-existential.check
+++ b/test/files/run/valueclasses-classtag-existential.check
@@ -1 +1 @@
-ClassTag[class java.lang.Object]
+Object
diff --git a/test/files/run/valueclasses-classtag-generic.check b/test/files/run/valueclasses-classtag-generic.check
index 0c13986b32..554c75e074 100644
--- a/test/files/run/valueclasses-classtag-generic.check
+++ b/test/files/run/valueclasses-classtag-generic.check
@@ -1 +1 @@
-ClassTag[class Foo]
+Foo
diff --git a/test/files/run/virtpatmat_typetag.check b/test/files/run/virtpatmat_typetag.check
index f9800b84d0..eaa9f3361f 100644
--- a/test/files/run/virtpatmat_typetag.check
+++ b/test/files/run/virtpatmat_typetag.check
@@ -1,10 +1,10 @@
-1 is not a ClassTag[int]; it's a class java.lang.Integer
-1 is a ClassTag[class java.lang.Integer]
-1 is not a ClassTag[class java.lang.String]; it's a class java.lang.Integer
-true is a ClassTag[class java.lang.Object]
-woele is a ClassTag[class java.lang.String]
-1 is not a ClassTag[int]; it's a class java.lang.Integer
-1 is a ClassTag[class java.lang.Integer]
-1 is not a ClassTag[class java.lang.String]; it's a class java.lang.Integer
-true is a ClassTag[class java.lang.Object]
-woele is a ClassTag[class java.lang.String]
+1 is not a Int; it's a class java.lang.Integer
+1 is a java.lang.Integer
+1 is not a java.lang.String; it's a class java.lang.Integer
+true is a Any
+woele is a java.lang.String
+1 is not a Int; it's a class java.lang.Integer
+1 is a java.lang.Integer
+1 is not a java.lang.String; it's a class java.lang.Integer
+true is a Any
+woele is a java.lang.String
diff --git a/test/files/pos/t2868.cmds b/test/flaky/pos/t2868.cmds
index ed8124a9e0..ed8124a9e0 100644
--- a/test/files/pos/t2868.cmds
+++ b/test/flaky/pos/t2868.cmds
diff --git a/test/files/pos/t2868/Jann.java b/test/flaky/pos/t2868/Jann.java
index f5b68de7b0..f5b68de7b0 100644
--- a/test/files/pos/t2868/Jann.java
+++ b/test/flaky/pos/t2868/Jann.java
diff --git a/test/files/pos/t2868/Nest.java b/test/flaky/pos/t2868/Nest.java
index 53652291ad..53652291ad 100644
--- a/test/files/pos/t2868/Nest.java
+++ b/test/flaky/pos/t2868/Nest.java
diff --git a/test/files/pos/t2868/pick_1.scala b/test/flaky/pos/t2868/pick_1.scala
index a211687432..a211687432 100644
--- a/test/files/pos/t2868/pick_1.scala
+++ b/test/flaky/pos/t2868/pick_1.scala
diff --git a/test/files/pos/t2868/t2868_src_2.scala b/test/flaky/pos/t2868/t2868_src_2.scala
index f11ef0fae2..f11ef0fae2 100644
--- a/test/files/pos/t2868/t2868_src_2.scala
+++ b/test/flaky/pos/t2868/t2868_src_2.scala