summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/reify/Taggers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/CompileServer.scala40
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala11
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala9
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala11
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala10
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala16
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala26
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala28
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala12
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala11
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala45
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala19
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Checkable.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala10
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala16
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala14
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala97
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala184
-rw-r--r--src/compiler/scala/tools/util/SocketServer.scala4
-rw-r--r--src/library/scala/collection/mutable/HashSet.scala2
-rw-r--r--src/library/scala/collection/parallel/mutable/ParArray.scala3
-rw-r--r--src/library/scala/collection/parallel/mutable/ParHashSet.scala2
-rw-r--r--src/library/scala/sys/process/ProcessBuilder.scala2
-rw-r--r--src/library/scala/throws.scala2
-rw-r--r--src/partest/scala/tools/partest/PartestTask.scala2
-rw-r--r--src/partest/scala/tools/partest/nest/SBTRunner.scala2
-rw-r--r--src/reflect/scala/reflect/internal/AnnotationInfos.scala11
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala7
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala17
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala4
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala19
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala128
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala6
-rw-r--r--test/disabled/run/t6987.check1
-rw-r--r--test/disabled/run/t6987.scala43
-rw-r--r--test/files/neg/annot-nonconst.check2
-rw-r--r--test/files/neg/catch-all.check9
-rw-r--r--test/files/neg/names-defaults-neg.check10
-rw-r--r--test/files/neg/nested-annotation.check10
-rw-r--r--test/files/neg/nested-annotation.scala9
-rw-r--r--test/files/neg/nonlocal-warning.check3
-rw-r--r--test/files/neg/t4851.check8
-rw-r--r--test/files/neg/t4851/S.scala5
-rw-r--r--test/files/neg/t5182.check7
-rw-r--r--test/files/neg/t5182.flags1
-rw-r--r--test/files/neg/t5182.scala5
-rw-r--r--test/files/neg/t5753/Impls$class.classbin626 -> 0 bytes
-rw-r--r--test/files/neg/t5753/Impls.classbin866 -> 0 bytes
-rw-r--r--test/files/neg/t6040.check4
-rw-r--r--test/files/neg/t6083.check10
-rw-r--r--test/files/neg/t6083.scala7
-rw-r--r--test/files/neg/t6231.check6
-rw-r--r--test/files/neg/t6231.scala15
-rw-r--r--test/files/neg/t6666.check40
-rw-r--r--test/files/neg/t6666.scala132
-rw-r--r--test/files/neg/t6902.check12
-rw-r--r--test/files/neg/t6902.flags1
-rw-r--r--test/files/neg/t6902.scala23
-rw-r--r--test/files/neg/t6952.check13
-rw-r--r--test/files/neg/t6952.scala4
-rw-r--r--test/files/pos/annotations2.scala31
-rw-r--r--test/files/pos/kinds.scala13
-rw-r--r--test/files/pos/t4859.scala (renamed from test/pending/pos/t4859.scala)2
-rw-r--r--test/files/pos/t6942.flags1
-rw-r--r--test/files/pos/t6942/Bar.java235
-rw-r--r--test/files/pos/t6942/t6942.scala64
-rw-r--r--test/files/pos/t6976/Exts_1.scala10
-rw-r--r--test/files/pos/t6976/ImplicitBug_1.scala27
-rw-r--r--test/files/pos/t6976/ImplicitBug_2.scala7
-rw-r--r--test/files/pos/t6994.flags1
-rw-r--r--test/files/pos/t6994.scala8
-rw-r--r--test/files/pos/t7011.flags1
-rw-r--r--test/files/pos/t7011.scala7
-rw-r--r--test/files/run/existentials-in-compiler.check44
-rw-r--r--test/files/run/reify_magicsymbols.check2
-rw-r--r--test/files/run/t2577.check1
-rw-r--r--test/files/run/t2577.scala17
-rw-r--r--test/files/run/t4859.check8
-rw-r--r--test/files/run/t4859.scala29
-rw-r--r--test/files/run/t5568.check9
-rw-r--r--test/files/run/t5568.scala16
-rw-r--r--test/files/run/t6011c.scala13
-rw-r--r--test/files/run/t6028.check2
-rw-r--r--test/files/run/t6434.check10
-rw-r--r--test/files/run/t6434.scala8
-rw-r--r--test/files/run/t6439.check77
-rw-r--r--test/files/run/t6439.scala32
-rw-r--r--test/files/run/t6860.check4
-rw-r--r--test/files/run/t6860.scala20
-rw-r--r--test/files/run/t6956.check1
-rw-r--r--test/files/run/t6956.scala26
-rw-r--r--test/files/run/t6969.check1
-rw-r--r--test/files/run/t6969.scala28
-rwxr-xr-xtest/partest4
-rw-r--r--test/pending/pos/those-kinds-are-high.scala53
103 files changed, 1655 insertions, 351 deletions
diff --git a/src/compiler/scala/reflect/reify/Taggers.scala b/src/compiler/scala/reflect/reify/Taggers.scala
index af0341fd38..9659134e5b 100644
--- a/src/compiler/scala/reflect/reify/Taggers.scala
+++ b/src/compiler/scala/reflect/reify/Taggers.scala
@@ -58,7 +58,7 @@ abstract class Taggers {
val result =
tpe match {
case coreTpe if coreTags contains coreTpe =>
- val ref = if (tagModule.owner.isPackageClass) Ident(tagModule) else Select(prefix, tagModule.name)
+ val ref = if (tagModule.isTopLevel) Ident(tagModule) else Select(prefix, tagModule.name)
Select(ref, coreTags(coreTpe))
case _ =>
translatingReificationErrors(materializer)
diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala
index e4c250a3d9..72e8cc69c7 100644
--- a/src/compiler/scala/tools/nsc/CompileServer.scala
+++ b/src/compiler/scala/tools/nsc/CompileServer.scala
@@ -87,10 +87,11 @@ class StandardCompileServer extends SocketServer {
val args = input.split("\0", -1).toList
val newSettings = new FscSettings(fscError)
- this.verbose = newSettings.verbose.value
val command = new OfflineCompilerCommand(args, newSettings)
+ this.verbose = newSettings.verbose.value
info("Settings after normalizing paths: " + newSettings)
+ if (!command.files.isEmpty) info("Input files after normalizing paths: " + (command.files mkString ","))
printMemoryStats()
// Update the idle timeout if given
@@ -168,11 +169,22 @@ object CompileServer extends StandardCompileServer {
/** A directory holding redirected output */
private lazy val redirectDir = (compileSocket.tmpDir / "output-redirects").createDirectory()
- private def redirect(setter: PrintStream => Unit, filename: String) {
- setter(new PrintStream((redirectDir / filename).createFile().bufferedOutput()))
- }
+ private def createRedirect(filename: String) =
+ new PrintStream((redirectDir / filename).createFile().bufferedOutput())
+
+ def main(args: Array[String]) =
+ execute(() => (), args)
- def main(args: Array[String]) {
+ /**
+ * Used for internal testing. The callback is called upon
+ * server start, notifying the caller that the server is
+ * ready to run. WARNING: the callback runs in the
+ * server's thread, blocking the server from doing any work
+ * until the callback is finished. Callbacks should be kept
+ * simple and clients should not try to interact with the
+ * server while the callback is processing.
+ */
+ def execute(startupCallback : () => Unit, args: Array[String]) {
val debug = args contains "-v"
if (debug) {
@@ -180,14 +192,16 @@ object CompileServer extends StandardCompileServer {
echo("Redirect dir is " + redirectDir)
}
- redirect(System.setOut, "scala-compile-server-out.log")
- redirect(System.setErr, "scala-compile-server-err.log")
- System.err.println("...starting server on socket "+port+"...")
- System.err.flush()
- compileSocket setPort port
- run()
+ Console.withErr(createRedirect("scala-compile-server-err.log")) {
+ Console.withOut(createRedirect("scala-compile-server-out.log")) {
+ Console.err.println("...starting server on socket "+port+"...")
+ Console.err.flush()
+ compileSocket setPort port
+ startupCallback()
+ run()
- compileSocket deletePort port
- sys exit 0
+ compileSocket deletePort port
+ }
+ }
}
}
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 05d0bcf6b0..d751669612 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -1378,7 +1378,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def compiles(sym: Symbol): Boolean =
if (sym == NoSymbol) false
else if (symSource.isDefinedAt(sym)) true
- else if (!sym.owner.isPackageClass) compiles(sym.enclosingTopLevelClass)
+ else if (!sym.isTopLevel) compiles(sym.enclosingTopLevelClass)
else if (sym.isModuleClass) compiles(sym.sourceModule)
else false
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 744644fd49..37da1b44bb 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1584,14 +1584,9 @@ self =>
* }}}
*/
def argumentExprs(): List[Tree] = {
- def args(): List[Tree] = commaSeparated {
- val maybeNamed = isIdent
- expr() match {
- case a @ Assign(id, rhs) if maybeNamed =>
- atPos(a.pos) { AssignOrNamedArg(id, rhs) }
- case e => e
- }
- }
+ def args(): List[Tree] = commaSeparated(
+ if (isIdent) treeInfo.assignmentToMaybeNamedArg(expr()) else expr()
+ )
in.token match {
case LBRACE => List(blockExpr())
case LPAREN => inParens(if (in.token == RPAREN) Nil else args())
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 39270719fb..379261906a 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -171,15 +171,10 @@ abstract class TreeBuilder {
/** Create tree representing (unencoded) binary operation expression or pattern. */
def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position): Tree = {
- def mkNamed(args: List[Tree]) =
- if (isExpr) args map {
- case a @ Assign(id @ Ident(name), rhs) =>
- atPos(a.pos) { AssignOrNamedArg(id, rhs) }
- case e => e
- } else args
+ def mkNamed(args: List[Tree]) = if (isExpr) args map treeInfo.assignmentToMaybeNamedArg else args
val arguments = right match {
case Parens(args) => mkNamed(args)
- case _ => List(right)
+ case _ => List(right)
}
if (isExpr) {
if (treeInfo.isLeftAssoc(op)) {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 2ea26ddaa9..3363f19025 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -835,13 +835,18 @@ abstract class GenICode extends SubComponent {
generatedType = toTypeKind(sym.info)
val hostClass = findHostClass(qualifier.tpe, sym)
log(s"Host class of $sym with qual $qualifier (${qualifier.tpe}) is $hostClass")
+ val qualSafeToElide = treeInfo isQualifierSafeToElide qualifier
+
+ def genLoadQualUnlessElidable: Context =
+ if (qualSafeToElide) ctx else genLoadQualifier(tree, ctx)
if (sym.isModule) {
- genLoadModule(ctx, tree)
+ genLoadModule(genLoadQualUnlessElidable, tree)
}
else if (sym.isStaticMember) {
- ctx.bb.emit(LOAD_FIELD(sym, true) setHostClass hostClass, tree.pos)
- ctx
+ val ctx1 = genLoadQualUnlessElidable
+ ctx1.bb.emit(LOAD_FIELD(sym, true) setHostClass hostClass, tree.pos)
+ ctx1
} else {
val ctx1 = genLoadQualifier(tree, ctx)
ctx1.bb.emit(LOAD_FIELD(sym, false) setHostClass hostClass, tree.pos)
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index f7e743a6f1..0282457a12 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -144,6 +144,8 @@ abstract class DeadCodeElimination extends SubComponent {
}
}
if (necessary) worklist += ((bb, idx))
+ case LOAD_MODULE(sym) if isLoadNeeded(sym) =>
+ worklist += ((bb, idx)) // SI-4859 Module initialization might side-effect.
case _ => ()
}
rd = rdef.interpret(bb, idx, rd)
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index 4f23d9902e..7f177c7ce4 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -386,8 +386,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
// be what people want so I'm waiting until I can do it better.
exitingTyper {
req.defines filterNot (s => req.defines contains s.companionSymbol) foreach { newSym =>
- val companion = newSym.name.companionName
- replScope lookup companion andAlso { oldSym =>
+ val oldSym = replScope lookup newSym.name.companionName
+ if (Seq(oldSym, newSym).permutations exists { case Seq(s1, s2) => s1.isClass && s2.isModule }) {
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.")
}
@@ -521,8 +521,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
Right(buildRequest(line, trees))
}
- // normalize non-public types so we don't see protected aliases like Self
- def normalizeNonPublic(tp: Type) = tp match {
+ // dealias non-public types so we don't see protected aliases like Self
+ def dealiasNonPublic(tp: Type) = tp match {
case TypeRef(_, sym, _) if sym.isAliasType && !sym.isPublic => tp.dealias
case _ => tp
}
@@ -980,7 +980,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
def cleanTypeAfterTyper(sym: => Symbol): Type = {
exitingTyper(
- normalizeNonPublic(
+ dealiasNonPublic(
dropNullaryMethod(
sym.tpe_*
)
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 04e860f9db..19d03ad04d 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -29,8 +29,8 @@ abstract class ClassfileParser {
protected var in: AbstractFileReader = _ // the class file reader
protected var clazz: Symbol = _ // the class symbol containing dynamic members
protected var staticModule: Symbol = _ // the module symbol containing static members
- protected var instanceScope: Scope = _ // the scope of all instance definitions
- protected var staticScope: Scope = _ // the scope of all static definitions
+ protected var instanceScope: Scope = _ // the scope of all instance definitions
+ protected var staticScope: Scope = _ // the scope of all static definitions
protected var pool: ConstantPool = _ // the classfile's constant pool
protected var isScala: Boolean = _ // does class file describe a scala class?
protected var isScalaAnnot: Boolean = _ // does class file describe a scala class with its pickled info in an annotation?
@@ -739,15 +739,9 @@ abstract class ClassfileParser {
// isMonomorphicType is false if the info is incomplete, as it usually is here
// so have to check unsafeTypeParams.isEmpty before worrying about raw type case below,
// or we'll create a boatload of needless existentials.
- else if (classSym.isMonomorphicType || classSym.unsafeTypeParams.isEmpty) {
- tp
- }
- else {
- // raw type - existentially quantify all type parameters
- val eparams = typeParamsToExistentials(classSym, classSym.unsafeTypeParams)
- val t = typeRef(pre, classSym, eparams.map(_.tpeHK))
- logResult(s"raw type from $classSym")(newExistentialType(eparams, t))
- }
+ else if (classSym.isMonomorphicType || classSym.unsafeTypeParams.isEmpty) tp
+ // raw type - existentially quantify all type parameters
+ else logResult(s"raw type from $classSym")(definitions.unsafeClassExistentialType(classSym))
case tp =>
assert(sig.charAt(index) != '<', tp)
tp
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index 39460ef004..f5c8907991 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -201,12 +201,17 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
var reflPoly$Cache: SoftReference[scala.runtime.MethodCache] = new SoftReference(new EmptyMethodCache())
def reflMethod$Method(forReceiver: JClass[_]): JMethod = {
- var method: JMethod = reflPoly$Cache.find(forReceiver)
- if (method != null)
+ var methodCache: MethodCache = reflPoly$Cache.find(forReceiver)
+ if (methodCache eq null) {
+ methodCache = new EmptyMethodCache
+ reflPoly$Cache = new SoftReference(methodCache)
+ }
+ var method: JMethod = methodCache.find(forReceiver)
+ if (method ne null)
return method
else {
method = ScalaRunTime.ensureAccessible(forReceiver.getMethod("xyz", reflParams$Cache))
- reflPoly$Cache = new SoftReference(reflPoly$Cache.get.add(forReceiver, method))
+ reflPoly$Cache = new SoftReference(methodCache.add(forReceiver, method))
return method
}
}
@@ -223,16 +228,22 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
def getPolyCache = gen.mkCast(fn(REF(reflPolyCacheSym), nme.get), MethodCacheClass.tpe)
addStaticMethodToClass((reflMethodSym, forReceiverSym) => {
+ val methodCache = reflMethodSym.newVariable(mkTerm("methodCache"), ad.pos) setInfo MethodCacheClass.tpe
val methodSym = reflMethodSym.newVariable(mkTerm("method"), ad.pos) setInfo MethodClass.tpe
BLOCK(
- IF (getPolyCache OBJ_EQ NULL) THEN (REF(reflPolyCacheSym) === mkNewPolyCache) ENDIF,
- VAL(methodSym) === ((getPolyCache DOT methodCache_find)(REF(forReceiverSym))) ,
- IF (REF(methodSym) OBJ_!= NULL) .
+ VAL(methodCache) === getPolyCache,
+ IF (REF(methodCache) OBJ_EQ NULL) THEN BLOCK(
+ REF(methodCache) === NEW(TypeTree(EmptyMethodCacheClass.tpe)),
+ REF(reflPolyCacheSym) === gen.mkSoftRef(REF(methodCache))
+ ) ENDIF,
+
+ VAL(methodSym) === (REF(methodCache) DOT methodCache_find)(REF(forReceiverSym)),
+ IF (REF(methodSym) OBJ_NE NULL) .
THEN (Return(REF(methodSym)))
ELSE {
def methodSymRHS = ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), REF(reflParamsCacheSym)))
- def cacheRHS = ((getPolyCache DOT methodCache_add)(REF(forReceiverSym), REF(methodSym)))
+ def cacheRHS = ((REF(methodCache) DOT methodCache_add)(REF(forReceiverSym), REF(methodSym)))
BLOCK(
REF(methodSym) === (REF(ensureAccessibleMethod) APPLY (methodSymRHS)),
REF(reflPolyCacheSym) === gen.mkSoftRef(cacheRHS),
@@ -241,6 +252,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
}
)
})
+
}
/* ### HANDLING METHODS NORMALLY COMPILED TO OPERATORS ### */
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index e3b5efde1f..0d50282000 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -50,7 +50,7 @@ abstract class Erasure extends AddInterfaces
if (sym == ArrayClass) args foreach traverse
else if (sym.isTypeParameterOrSkolem || sym.isExistentiallyBound || !args.isEmpty) result = true
else if (sym.isClass) traverse(rebindInnerClass(pre, sym)) // #2585
- else if (!sym.owner.isPackageClass) traverse(pre)
+ else if (!sym.isTopLevel) traverse(pre)
case PolyType(_, _) | ExistentialType(_, _) =>
result = true
case RefinedType(parents, _) =>
@@ -341,13 +341,18 @@ abstract class Erasure extends AddInterfaces
case _ => tp.deconst
}
}
- // 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, AnyVal_getClass) ++ (
- // Each value class has its own getClass for ultra-precise class object typing.
+
+ // Each primitive value class has its own getClass for ultra-precise class object typing.
+ private lazy val primitiveGetClassMethods = Set[Symbol](Any_getClass, AnyVal_getClass) ++ (
ScalaValueClasses map (_.tpe member nme.getClass_)
)
+ // ## requires a little translation
+ private lazy val poundPoundMethods = Set[Symbol](Any_##, Object_##)
+ // Methods on Any/Object which we rewrite here while we still know what
+ // is a primitive and what arrived boxed.
+ private lazy val interceptedMethods = poundPoundMethods ++ primitiveGetClassMethods
+
// -------- erasure on trees ------------------------------------------
override def newTyper(context: Context) = new Eraser(context)
@@ -1130,7 +1135,7 @@ abstract class Erasure extends AddInterfaces
}
}
else if (args.isEmpty && interceptedMethods(fn.symbol)) {
- if (fn.symbol == Any_## || fn.symbol == Object_##) {
+ if (poundPoundMethods.contains(fn.symbol)) {
// This is unattractive, but without it we crash here on ().## because after
// erasure the ScalaRunTime.hash overload goes from Unit => Int to BoxedUnit => Int.
// This must be because some earlier transformation is being skipped on ##, but so
@@ -1157,9 +1162,18 @@ abstract class Erasure extends AddInterfaces
} 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) {
+ } else if (primitiveGetClassMethods.contains(fn.symbol)) {
+ // if we got here then we're trying to send a primitive getClass method to either
+ // a) an Any, in which cage Object_getClass works because Any erases to object. Or
+ //
+ // b) a non-primitive, e.g. because the qualifier's type is a refinement type where one parent
+ // of the refinement is a primitive and another is AnyRef. In that case
+ // we get a primitive form of _getClass trying to target a boxed value
+ // so we need replace that method name with Object_getClass to get correct behavior.
+ // See SI-5568.
tree setSymbol Object_getClass
} else {
+ debugwarn(s"The symbol '${fn.symbol}' was interecepted but didn't match any cases, that means the intercepted methods set doesn't match the code")
tree
}
} else qual match {
diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
index 77e7e013ab..12933af138 100644
--- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
@@ -60,14 +60,18 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
}
}
- /** Return the extension method that corresponds to given instance method `meth`.
- */
+ private def companionModuleForce(sym: Symbol) = {
+ sym.andAlso(_.owner.initialize) // See SI-6976. `companionModule` only calls `rawInfo`. (Why?)
+ sym.companionModule
+ }
+
+ /** Return the extension method that corresponds to given instance method `meth`. */
def extensionMethod(imeth: Symbol): Symbol = enteringPhase(currentRun.refchecksPhase) {
- val companionInfo = imeth.owner.companionModule.info
+ val companionInfo = companionModuleForce(imeth.owner).info
val candidates = extensionNames(imeth) map (companionInfo.decl(_)) filter (_.exists)
val matching = candidates filter (alt => normalize(alt.tpe, imeth.owner) matches imeth.tpe)
assert(matching.nonEmpty,
- s"no extension method found for $imeth:${imeth.tpe} among ${candidates map (c => c.name+":"+c.tpe)} / ${extensionNames(imeth)}")
+ s"no extension method found for $imeth:${imeth.tpe} among ${candidates.map(c => c.name+":"+c.tpe).toList} / ${extensionNames(imeth).toList}")
matching.head
}
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index b2602f47de..a370b45be0 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -12,6 +12,7 @@ import scala.collection.mutable.ListBuffer
abstract class Flatten extends InfoTransform {
import global._
+ import treeInfo.isQualifierSafeToElide
/** the following two members override abstract members in Transform */
val phaseName: String = "flatten"
@@ -116,8 +117,14 @@ abstract class Flatten extends InfoTransform {
case ClassDef(_, _, _, _) if sym.isNestedClass =>
liftedDefs(sym.enclosingTopLevelClass.owner) += tree
EmptyTree
- case Select(qual, name) if (sym.isStaticModule && !sym.owner.isPackageClass) =>
- exitingFlatten(atPos(tree.pos)(gen.mkAttributedRef(sym)))
+ case Select(qual, name) if sym.isStaticModule && !sym.isTopLevel =>
+ exitingFlatten {
+ atPos(tree.pos) {
+ val ref = gen.mkAttributedRef(sym)
+ if (isQualifierSafeToElide(qual)) ref
+ else Block(List(qual), ref).setType(tree.tpe) // need to execute the qualifier but refer directly to the lifted module.
+ }
+ }
case _ =>
tree
}
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
index b081fb7e3f..f8172743b5 100644
--- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
+++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
@@ -320,12 +320,24 @@ abstract class LambdaLift extends InfoTransform {
private def memberRef(sym: Symbol) = {
val clazz = sym.owner.enclClass
//Console.println("memberRef from "+currentClass+" to "+sym+" in "+clazz)
- val qual = if (clazz == currentClass) gen.mkAttributedThis(clazz)
- else {
- sym resetFlag(LOCAL | PRIVATE)
- if (clazz.isStaticOwner) gen.mkAttributedQualifier(clazz.thisType)
- else outerPath(outerValue, currentClass.outerClass, clazz)
- }
+ def prematureSelfReference() {
+ val what =
+ if (clazz.isStaticOwner) clazz.fullLocationString
+ else s"the unconstructed `this` of ${clazz.fullLocationString}"
+ val msg = s"Implementation restriction: access of ${sym.fullLocationString} from ${currentClass.fullLocationString}, would require illegal premature access to $what"
+ currentUnit.error(curTree.pos, msg)
+ }
+ val qual =
+ if (clazz == currentClass) gen.mkAttributedThis(clazz)
+ else {
+ sym resetFlag (LOCAL | PRIVATE)
+ if (selfOrSuperCalls exists (_.owner == clazz)) {
+ prematureSelfReference()
+ EmptyTree
+ }
+ else if (clazz.isStaticOwner) gen.mkAttributedQualifier(clazz.thisType)
+ else outerPath(outerValue, currentClass.outerClass, clazz)
+ }
Select(qual, sym) setType sym.tpe
}
@@ -352,6 +364,7 @@ abstract class LambdaLift extends InfoTransform {
copyDefDef(tree)(vparamss = List(vparams ++ freeParams))
case ClassDef(_, _, _, _) =>
+ // SI-6231
// Disabled attempt to to add getters to freeParams
// this does not work yet. Problem is that local symbols need local names
// and references to local symbols need to be transformed into
@@ -369,7 +382,7 @@ abstract class LambdaLift extends InfoTransform {
tree
}
-/* Something like this will be necessary to eliminate the implementation
+/* SI-6231: Something like this will be necessary to eliminate the implementation
* restiction from paramGetter above:
* We need to pass getters to the interface of an implementation class.
private def fixTraitGetters(lifted: List[Tree]): List[Tree] =
@@ -430,10 +443,10 @@ abstract class LambdaLift extends InfoTransform {
/* Creating a constructor argument if one isn't present. */
val constructorArg = rhs match {
case EmptyTree =>
- sym.primaryConstructor.info.paramTypes match {
+ sym.tpe.typeSymbol.primaryConstructor.info.paramTypes match {
case List(tp) => gen.mkZero(tp)
case _ =>
- log("Couldn't determine how to properly construct " + sym)
+ debugwarn("Couldn't determine how to properly construct " + sym)
rhs
}
case arg => arg
@@ -495,13 +508,25 @@ abstract class LambdaLift extends InfoTransform {
private def preTransform(tree: Tree) = super.transform(tree) setType lifted(tree.tpe)
+ /** The stack of constructor symbols in which a call to this() or to the super
+ * constructor is active.
+ */
+ private val selfOrSuperCalls = mutable.Stack[Symbol]()
+ @inline private def inSelfOrSuperCall[A](sym: Symbol)(a: => A) = try {
+ selfOrSuperCalls push sym
+ a
+ } finally selfOrSuperCalls.pop()
+
override def transform(tree: Tree): Tree = tree match {
case Select(ReferenceToBoxed(idt), elem) if elem == nme.elem =>
postTransform(preTransform(idt), isBoxedRef = false)
case ReferenceToBoxed(idt) =>
postTransform(preTransform(idt), isBoxedRef = true)
case _ =>
- postTransform(preTransform(tree))
+ def transformTree = postTransform(preTransform(tree))
+ if (treeInfo isSelfOrSuperConstrCall tree)
+ inSelfOrSuperCall(currentOwner)(transformTree)
+ else transformTree
}
/** Transform statements and add lifted definitions to them. */
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 6a253a98b1..3e5ac6922e 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -1214,9 +1214,24 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
// refer to fields in some implementation class via an abstract
// getter in the interface.
val iface = toInterface(sym.owner.tpe).typeSymbol
- val getter = sym getter iface orElse abort("No getter for " + sym + " in " + iface)
+ val ifaceGetter = sym getter iface
+
+ def si6231Restriction() {
+ // See SI-6231 comments in LamdaLift for ideas on how to lift the restriction.
+ val msg = sm"""Implementation restriction: local ${iface.fullLocationString} is unable to automatically capture the
+ |free variable ${sym} on behalf of ${currentClass}. You can manually assign it to a val inside the trait,
+ |and refer that that val in ${currentClass}. For more details, see SI-6231."""
+ reporter.error(tree.pos, msg)
+ }
- typedPos(tree.pos)((qual DOT getter)())
+ if (ifaceGetter == NoSymbol) {
+ if (sym.isParamAccessor) {
+ si6231Restriction()
+ EmptyTree
+ }
+ else abort("No getter for " + sym + " in " + iface)
+ }
+ else typedPos(tree.pos)((qual DOT ifaceGetter)())
case Assign(Apply(lhs @ Select(qual, _), List()), rhs) =>
// assign to fields in some implementation class via an abstract
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 116b6ab58f..343f95782e 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -1365,7 +1365,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
debuglog("obtained env: " + e)
e.keySet == env.keySet
} catch {
- case _ =>
+ case _: Throwable =>
debuglog("Could not unify.")
false
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
index fb3909746f..88bfa6099d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
@@ -62,6 +62,9 @@ trait Checkable {
bases foreach { bc =>
val tps1 = (from baseType bc).typeArgs
val tps2 = (tvarType baseType bc).typeArgs
+ if (tps1.size != tps2.size)
+ devWarning(s"Unequally sized type arg lists in propagateKnownTypes($from, $to): ($tps1, $tps2)")
+
(tps1, tps2).zipped foreach (_ =:= _)
// Alternate, variance respecting formulation causes
// neg/unchecked3.scala to fail (abstract types). TODO -
@@ -78,7 +81,7 @@ trait Checkable {
val resArgs = tparams zip tvars map {
case (_, tvar) if tvar.instValid => tvar.constr.inst
- case (tparam, _) => tparam.tpe
+ case (tparam, _) => tparam.tpeHK
}
appliedType(to, resArgs: _*)
}
@@ -108,7 +111,7 @@ trait Checkable {
private class CheckabilityChecker(val X: Type, val P: Type) {
def Xsym = X.typeSymbol
def Psym = P.typeSymbol
- def XR = propagateKnownTypes(X, Psym)
+ def XR = if (Xsym == AnyClass) classExistentialType(Psym) else propagateKnownTypes(X, Psym)
// sadly the spec says (new java.lang.Boolean(true)).isInstanceOf[scala.Boolean]
def P1 = X matchesPattern P
def P2 = !Psym.isPrimitiveValueClass && isNeverSubType(X, P)
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 2d4054e93b..7bbbcdf541 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -736,7 +736,7 @@ trait ContextErrors {
} catch {
// the code above tries various tricks to detect the relevant portion of the stack trace
// if these tricks fail, just fall back to uninformative, but better than nothing, getMessage
- case NonFatal(ex) =>
+ case NonFatal(ex) => // currently giving a spurious warning, see SI-6994
macroLogVerbose("got an exception when processing a macro generated exception\n" +
"offender = " + stackTraceString(realex) + "\n" +
"error = " + stackTraceString(ex))
@@ -1048,8 +1048,8 @@ trait ContextErrors {
val s1 = if (prevSym.isModule) "case class companion " else ""
val s2 = if (prevSym.isSynthetic) "(compiler-generated) " + s1 else ""
val s3 = if (prevSym.isCase) "case class " + prevSym.name else "" + prevSym
- val where = if (currentSym.owner.isPackageClass != prevSym.owner.isPackageClass) {
- val inOrOut = if (prevSym.owner.isPackageClass) "outside of" else "in"
+ val where = if (currentSym.isTopLevel != prevSym.isTopLevel) {
+ val inOrOut = if (prevSym.isTopLevel) "outside of" else "in"
" %s package object %s".format(inOrOut, ""+prevSym.effectiveOwner.name)
} else ""
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 274a567075..a160a9894e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -169,6 +169,7 @@ trait Contexts { self: Analyzer =>
def typingIndent = " " * typingIndentLevel
var buffer: mutable.Set[AbsTypeError] = _
+ var warningsBuffer: mutable.Set[(Position, String)] = _
def enclClassOrMethod: Context =
if ((owner eq NoSymbol) || (owner.isClass) || (owner.isMethod)) this
@@ -190,6 +191,7 @@ trait Contexts { self: Analyzer =>
def errBuffer = buffer
def hasErrors = buffer.nonEmpty
+ def hasWarnings = warningsBuffer.nonEmpty
def state: Int = mode
def restoreState(state0: Int) = mode = state0
@@ -218,6 +220,11 @@ trait Contexts { self: Analyzer =>
buffer.clear()
current
}
+ def flushAndReturnWarningsBuffer(): mutable.Set[(Position, String)] = {
+ val current = warningsBuffer.clone()
+ warningsBuffer.clear()
+ current
+ }
def withImplicitsEnabled[T](op: => T): T = {
val saved = implicitsEnabled
@@ -305,6 +312,7 @@ trait Contexts { self: Analyzer =>
c.retyping = this.retyping
c.openImplicits = this.openImplicits
c.buffer = if (this.buffer == null) mutable.LinkedHashSet[AbsTypeError]() else this.buffer // need to initialize
+ c.warningsBuffer = if (this.warningsBuffer == null) mutable.LinkedHashSet[(Position, String)]() else this.warningsBuffer
registerContext(c.asInstanceOf[analyzer.Context])
debuglog("[context] ++ " + c.unit + " / " + tree.summaryString)
c
@@ -427,6 +435,7 @@ trait Contexts { self: Analyzer =>
def warning(pos: Position, msg: String): Unit = warning(pos, msg, false)
def warning(pos: Position, msg: String, force: Boolean) {
if (reportErrors || force) unit.warning(pos, msg)
+ else if (bufferErrors) warningsBuffer += ((pos, msg))
}
def isLocal(): Boolean = tree match {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 4177b7cdfa..e652b68b14 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -244,6 +244,8 @@ trait Infer extends Checkable {
* This method seems to be performance critical.
*/
def normalize(tp: Type): Type = tp match {
+ case pt @ PolyType(tparams, restpe) =>
+ logResult(s"Normalizing $tp in infer")(normalize(restpe))
case mt @ MethodType(params, restpe) if mt.isImplicit =>
normalize(restpe)
case mt @ MethodType(_, restpe) if !mt.isDependentMethodType =>
@@ -866,7 +868,7 @@ trait Infer extends Checkable {
val (argtpes1, argPos, namesOK) = checkNames(argtpes0, params)
// when using named application, the vararg param has to be specified exactly once
( namesOK
- && (isIdentity(argPos) || sameLength(formals, params))
+ && (allArgsArePositional(argPos) || sameLength(formals, params))
&& typesCompatible(reorderArgs(argtpes1, argPos)) // nb. arguments and names are OK, check if types are compatible
)
}
@@ -1222,8 +1224,6 @@ trait Infer extends Checkable {
}
}
- def widen(tp: Type): Type = abstractTypesToBounds(tp)
-
/** Substitute free type variables `undetparams` of type constructor
* `tree` in pattern, given prototype `pt`.
*
@@ -1232,7 +1232,7 @@ trait Infer extends Checkable {
* @param pt the expected result type of the instance
*/
def inferConstructorInstance(tree: Tree, undetparams: List[Symbol], pt0: Type) {
- val pt = widen(pt0)
+ val pt = abstractTypesToBounds(pt0)
val ptparams = freeTypeParamsOfTerms(pt)
val ctorTp = tree.tpe
val resTp = ctorTp.finalResultType
@@ -1371,7 +1371,7 @@ trait Infer extends Checkable {
}
def inferTypedPattern(tree0: Tree, pattp: Type, pt0: Type, canRemedy: Boolean): Type = {
- val pt = widen(pt0)
+ val pt = abstractTypesToBounds(pt0)
val ptparams = freeTypeParamsOfTerms(pt)
val tpparams = freeTypeParamsOfTerms(pattp)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 5b27fd9352..7d6d47b410 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -124,7 +124,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
// todo. refactor when fixing SI-5498
def className: String = {
def loop(sym: Symbol): String = sym match {
- case sym if sym.owner.isPackageClass =>
+ case sym if sym.isTopLevel =>
val suffix = if (sym.isModuleClass) "$" else ""
sym.fullName + suffix
case sym =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 352090892e..2eabc126e3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -134,7 +134,7 @@ trait Namers extends MethodSynthesis {
sym reset NoType setFlag newFlags setPos pos
sym.moduleClass andAlso (updatePosFlags(_, pos, moduleClassFlags(flags)))
- if (sym.owner.isPackageClass) {
+ if (sym.isTopLevel) {
companionSymbolOf(sym, context) andAlso { companion =>
val assignNoType = companion.rawInfo match {
case _: SymLoader => true
@@ -163,7 +163,7 @@ trait Namers extends MethodSynthesis {
protected def conflict(newS: Symbol, oldS: Symbol) = (
( !oldS.isSourceMethod
|| nme.isSetterName(newS.name)
- || newS.owner.isPackageClass
+ || newS.isTopLevel
) &&
!( // @M: allow repeated use of `_` for higher-order type params
(newS.owner.isTypeParameter || newS.owner.isAbstractType)
@@ -174,7 +174,7 @@ trait Namers extends MethodSynthesis {
)
private def allowsOverload(sym: Symbol) = (
- sym.isSourceMethod && sym.owner.isClass && !sym.owner.isPackageClass
+ sym.isSourceMethod && sym.owner.isClass && !sym.isTopLevel
)
private def inCurrentScope(m: Symbol): Boolean = {
@@ -352,7 +352,7 @@ trait Namers extends MethodSynthesis {
val existing = context.scope.lookup(tree.name)
val isRedefinition = (
existing.isType
- && existing.owner.isPackageClass
+ && existing.isTopLevel
&& context.scope == existing.owner.info.decls
&& currentRun.canRedefine(existing)
)
@@ -365,8 +365,8 @@ trait Namers extends MethodSynthesis {
else assignAndEnterSymbol(tree) setFlag inConstructorFlag
}
clazz match {
- case csym: ClassSymbol if csym.owner.isPackageClass => enterClassSymbol(tree, csym)
- case _ => clazz
+ case csym: ClassSymbol if csym.isTopLevel => enterClassSymbol(tree, csym)
+ case _ => clazz
}
}
@@ -425,7 +425,7 @@ trait Namers extends MethodSynthesis {
m.moduleClass setFlag moduleClassFlags(moduleFlags)
setPrivateWithin(tree, m.moduleClass)
}
- if (m.owner.isPackageClass && !m.isPackage) {
+ if (m.isTopLevel && !m.isPackage) {
m.moduleClass.associatedFile = contextFile
currentRun.symSource(m) = m.moduleClass.sourceFile
registerTopLevelSym(m)
@@ -1446,7 +1446,7 @@ trait Namers extends MethodSynthesis {
fail(ImplicitConstr)
if (!(sym.isTerm || (sym.isClass && !sym.isTrait)))
fail(ImplicitNotTermOrClass)
- if (sym.owner.isPackageClass)
+ if (sym.isTopLevel)
fail(ImplicitAtToplevel)
}
if (sym.isClass) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index f5884e5c34..dd60b292bf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -41,11 +41,11 @@ trait NamesDefaults { self: Analyzer =>
blockTyper: Typer
) { }
- def nameOf(arg: Tree) = arg match {
- case AssignOrNamedArg(Ident(name), rhs) => Some(name)
- case _ => None
+ private def nameOfNamedArg(arg: Tree) = Some(arg) collect { case AssignOrNamedArg(Ident(name), _) => name }
+ def isNamedArg(arg: Tree) = arg match {
+ case AssignOrNamedArg(Ident(_), _) => true
+ case _ => false
}
- def isNamed(arg: Tree) = nameOf(arg).isDefined
/** @param pos maps indices from old to new */
def reorderArgs[T: ClassTag](args: List[T], pos: Int => Int): List[T] = {
@@ -55,13 +55,13 @@ trait NamesDefaults { self: Analyzer =>
}
/** @param pos maps indices from new to old (!) */
- def reorderArgsInv[T: ClassTag](args: List[T], pos: Int => Int): List[T] = {
+ private def reorderArgsInv[T: ClassTag](args: List[T], pos: Int => Int): List[T] = {
val argsArray = args.toArray
(argsArray.indices map (i => argsArray(pos(i)))).toList
}
/** returns `true` if every element is equal to its index */
- def isIdentity(a: Array[Int]) = (0 until a.length).forall(i => a(i) == i)
+ def allArgsArePositional(a: Array[Int]) = (0 until a.length).forall(i => a(i) == i)
/**
* Transform a function application into a Block, and assigns typer.context
@@ -359,7 +359,7 @@ trait NamesDefaults { self: Analyzer =>
}
}
- def missingParams[T](args: List[T], params: List[Symbol], argName: T => Option[Name] = nameOf _): (List[Symbol], Boolean) = {
+ def missingParams[T](args: List[T], params: List[Symbol], argName: T => Option[Name] = nameOfNamedArg _): (List[Symbol], Boolean) = {
val namedArgs = args.dropWhile(arg => {
val n = argName(arg)
n.isEmpty || params.forall(p => p.name != n.get)
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index 48bdd07e66..27bdad3066 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -1944,7 +1944,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
//
// TODO: for V1 representing x1 and V2 standing for x1.head, encode that
// V1 = Nil implies -(V2 = Ci) for all Ci in V2's domain (i.e., it is unassignable)
- def removeVarEq(props: List[Prop], modelNull: Boolean = false): (Prop, List[Prop]) = {
+ // may throw an AnalysisBudget.Exception
+ def removeVarEq(props: List[Prop], modelNull: Boolean = false): (Formula, List[Formula]) = {
val start = if (Statistics.canEnable) Statistics.startTimer(patmatAnaVarEq) else null
val vars = new scala.collection.mutable.HashSet[Var]
@@ -1968,10 +1969,10 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
props foreach gatherEqualities.apply
if (modelNull) vars foreach (_.registerNull)
- val pure = props map rewriteEqualsToProp.apply
+ val pure = props map (p => eqFreePropToSolvable(rewriteEqualsToProp(p)))
- var eqAxioms: Prop = True
- def addAxiom(p: Prop) = eqAxioms = And(eqAxioms, p)
+ val eqAxioms = formulaBuilder
+ @inline def addAxiom(p: Prop) = addFormula(eqAxioms, eqFreePropToSolvable(p))
patmatDebug("removeVarEq vars: "+ vars)
vars.foreach { v =>
@@ -1997,23 +1998,37 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
}
- patmatDebug("eqAxioms:\n"+ cnfString(eqFreePropToSolvable(eqAxioms)))
- patmatDebug("pure:"+ pure.map(p => cnfString(eqFreePropToSolvable(p))).mkString("\n"))
+ patmatDebug("eqAxioms:\n"+ cnfString(toFormula(eqAxioms)))
+ patmatDebug("pure:"+ pure.map(p => cnfString(p)).mkString("\n"))
if (Statistics.canEnable) Statistics.stopTimer(patmatAnaVarEq, start)
- (eqAxioms, pure)
+ (toFormula(eqAxioms), pure)
}
+ // an interface that should be suitable for feeding a SAT solver when the time comes
type Formula
+ type FormulaBuilder
+
+ // creates an empty formula builder to which more formulae can be added
+ def formulaBuilder: FormulaBuilder
+
+ // val f = formulaBuilder; addFormula(f, f1); ... addFormula(f, fN)
+ // toFormula(f) == andFormula(f1, andFormula(..., fN))
+ def addFormula(buff: FormulaBuilder, f: Formula): Unit
+ def toFormula(buff: FormulaBuilder): Formula
+
+ // the conjunction of formulae `a` and `b`
def andFormula(a: Formula, b: Formula): Formula
+ // equivalent formula to `a`, but simplified in a lightweight way (drop duplicate clauses)
+ def simplifyFormula(a: Formula): Formula
// may throw an AnalysisBudget.Exception
def propToSolvable(p: Prop): Formula = {
val (eqAxioms, pure :: Nil) = removeVarEq(List(p), modelNull = false)
- eqFreePropToSolvable(And(eqAxioms, pure))
+ andFormula(eqAxioms, pure)
}
// may throw an AnalysisBudget.Exception
@@ -2029,24 +2044,34 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
trait CNF extends Logic {
- // CNF: a formula is a conjunction of clauses
- type Formula = Array[Clause]
/** Override Array creation for efficiency (to not go through reflection). */
private implicit val clauseTag: scala.reflect.ClassTag[Clause] = new scala.reflect.ClassTag[Clause] {
def runtimeClass: java.lang.Class[Clause] = classOf[Clause]
final override def newArray(len: Int): Array[Clause] = new Array[Clause](len)
}
- def formula(c: Clause*): Formula = c.toArray
- def andFormula(a: Formula, b: Formula): Formula = a ++ b
+ import scala.collection.mutable.ArrayBuffer
+ type FormulaBuilder = ArrayBuffer[Clause]
+ def formulaBuilder = ArrayBuffer[Clause]()
+ def addFormula(buff: FormulaBuilder, f: Formula): Unit = buff ++= f
+ def toFormula(buff: FormulaBuilder): Formula = buff
+
+ // CNF: a formula is a conjunction of clauses
+ type Formula = FormulaBuilder
+ def formula(c: Clause*): Formula = ArrayBuffer(c: _*)
+
+ type Clause = Set[Lit]
// a clause is a disjunction of distinct literals
- type Clause = Set[Lit]
def clause(l: Lit*): Clause = l.toSet
- private def merge(a: Clause, b: Clause) = a ++ b
type Lit
def Lit(sym: Sym, pos: Boolean = true): Lit
+ def andFormula(a: Formula, b: Formula): Formula = a ++ b
+ def simplifyFormula(a: Formula): Formula = a.distinct
+
+ private def merge(a: Clause, b: Clause) = a ++ b
+
// throws an AnalysisBudget.Exception when the prop results in a CNF that's too big
// TODO: be smarter/more efficient about this (http://lara.epfl.ch/w/sav09:tseitin_s_encoding)
def eqFreePropToSolvable(p: Prop): Formula = {
@@ -2617,23 +2642,22 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
val propsCasesOk = testCasesOk map (t => symbolicCase(t, modelNull = true))
val propsCasesFail = testCasesFail map (t => Not(symbolicCase(t, modelNull = true)))
- val (eqAxiomsFail, symbolicCasesFail) = removeVarEq(propsCasesFail, modelNull = true)
- val (eqAxiomsOk, symbolicCasesOk) = removeVarEq(propsCasesOk, modelNull = true)
try {
- // most of the time eqAxiomsFail == eqAxiomsOk, but the different approximations might cause different variables to disapper in general
- val eqAxiomsCNF =
- if (eqAxiomsFail == eqAxiomsOk) eqFreePropToSolvable(eqAxiomsFail)
- else eqFreePropToSolvable(And(eqAxiomsFail, eqAxiomsOk))
+ val (eqAxiomsFail, symbolicCasesFail) = removeVarEq(propsCasesFail, modelNull = true)
+ val (eqAxiomsOk, symbolicCasesOk) = removeVarEq(propsCasesOk, modelNull = true)
+ val eqAxioms = simplifyFormula(andFormula(eqAxiomsOk, eqAxiomsFail)) // I'm pretty sure eqAxiomsOk == eqAxiomsFail, but not 100% sure.
+
+ val prefix = formulaBuilder
+ addFormula(prefix, eqAxioms)
- var prefix = eqAxiomsCNF
var prefixRest = symbolicCasesFail
var current = symbolicCasesOk
var reachable = true
var caseIndex = 0
patmatDebug("reachability, vars:\n"+ ((propsCasesFail flatMap gatherVariables).distinct map (_.describe) mkString ("\n")))
- patmatDebug("equality axioms:\n"+ cnfString(eqAxiomsCNF))
+ patmatDebug("equality axioms:\n"+ cnfString(eqAxiomsOk))
// invariant (prefixRest.length == current.length) && (prefix.reverse ++ prefixRest == symbolicCasesFail)
// termination: prefixRest.length decreases by 1
@@ -2643,11 +2667,11 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
prefixRest = prefixRest.tail
if (prefixRest.isEmpty) reachable = true
else {
- prefix = andFormula(eqFreePropToSolvable(prefHead), prefix)
+ addFormula(prefix, prefHead)
current = current.tail
- val model = findModelFor(andFormula(eqFreePropToSolvable(current.head), prefix))
+ val model = findModelFor(andFormula(current.head, toFormula(prefix)))
- // patmatDebug("trying to reach:\n"+ cnfString(eqFreePropToSolvable(current.head)) +"\nunder prefix:\n"+ cnfString(prefix))
+ // patmatDebug("trying to reach:\n"+ cnfString(current.head) +"\nunder prefix:\n"+ cnfString(prefix))
// if (NoModel ne model) patmatDebug("reached: "+ modelString(model))
reachable = NoModel ne model
@@ -3213,6 +3237,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// TODO: make more fine-grained, as we don't always need to jump
def canJump: Boolean
+ /** Should exhaustivity analysis be skipped? */
def unchecked: Boolean
@@ -3446,12 +3471,10 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
case Some(cds) => cds
}
- val allReachable = unchecked || {
- // a switch with duplicate cases yields a verify error,
- // and a switch with duplicate cases and guards cannot soundly be rewritten to an unguarded switch
- // (even though the verify error would disappear, the behaviour would change)
- unreachableCase(caseDefsWithGuards) map (cd => reportUnreachable(cd.body.pos)) isEmpty
- }
+ // a switch with duplicate cases yields a verify error,
+ // and a switch with duplicate cases and guards cannot soundly be rewritten to an unguarded switch
+ // (even though the verify error would disappear, the behaviour would change)
+ val allReachable = unreachableCase(caseDefsWithGuards) map (cd => reportUnreachable(cd.body.pos)) isEmpty
if (!allReachable) Nil
else if (noGuards(caseDefsWithGuards)) {
@@ -3487,8 +3510,10 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
val alternativesSupported = true
val canJump = true
- object SwitchablePattern { def unapply(pat: Tree): Option[Tree] = pat match {
- case Literal(const@Constant((_: Byte ) | (_: Short) | (_: Int ) | (_: Char ))) =>
+ // Constant folding sets the type of a constant tree to `ConstantType(Constant(folded))`
+ // The tree itself can be a literal, an ident, a selection, ...
+ object SwitchablePattern { def unapply(pat: Tree): Option[Tree] = pat.tpe match {
+ case ConstantType(const) if const.isIntRange =>
Some(Literal(Constant(const.intValue))) // TODO: Java 7 allows strings in switches
case _ => None
}}
@@ -3692,10 +3717,10 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
with SymbolicMatchAnalysis
with DPLLSolver { self: TreeMakers =>
override def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): (List[List[TreeMaker]], List[Tree]) = {
+ unreachableCase(prevBinder, cases, pt) foreach { caseIndex =>
+ reportUnreachable(cases(caseIndex).last.pos)
+ }
if (!unchecked) {
- unreachableCase(prevBinder, cases, pt) foreach { caseIndex =>
- reportUnreachable(cases(caseIndex).last.pos)
- }
val counterExamples = exhaustive(prevBinder, cases, pt)
if (counterExamples.nonEmpty)
reportMissingCases(prevBinder.pos, counterExamples)
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index e88447c46d..fd3b020b1a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1389,9 +1389,13 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
case TypeApply(fun, targs) =>
isClassTypeAccessible(fun)
case Select(module, apply) =>
- // Fixes SI-5626. Classes in refinement types cannot be constructed with `new`. In this case,
- // the companion class is actually not a ClassSymbol, but a reference to an abstract type.
- module.symbol.companionClass.isClass
+ ( // SI-4859 `CaseClass1().InnerCaseClass2()` must not be rewritten to `new InnerCaseClass2()`;
+ // {expr; Outer}.Inner() must not be rewritten to `new Outer.Inner()`.
+ treeInfo.isQualifierSafeToElide(module) &&
+ // SI-5626 Classes in refinement types cannot be constructed with `new`. In this case,
+ // the companion class is actually not a ClassSymbol, but a reference to an abstract type.
+ module.symbol.companionClass.isClass
+ )
}
val doTransform =
@@ -1617,7 +1621,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
result match {
case ClassDef(_, _, _, _)
| TypeDef(_, _, _, _) =>
- if (result.symbol.isLocal || result.symbol.owner.isPackageClass)
+ if (result.symbol.isLocal || result.symbol.isTopLevel)
varianceValidator.traverse(result)
case _ =>
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 45f290d6c1..8fbc143fbf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -126,10 +126,7 @@ trait Typers extends Adaptations with Tags {
// paramFailed cannot be initialized with params.exists(_.tpe.isError) because that would
// hide some valid errors for params preceding the erroneous one.
var paramFailed = false
-
- def mkPositionalArg(argTree: Tree, paramName: Name) = argTree
- def mkNamedArg(argTree: Tree, paramName: Name) = atPos(argTree.pos)(new AssignOrNamedArg(Ident(paramName), (argTree)))
- var mkArg: (Tree, Name) => Tree = mkPositionalArg
+ var mkArg: (Name, Tree) => Tree = (_, tree) => tree
// DEPMETTODO: instantiate type vars that depend on earlier implicit args (see adapt (4.1))
//
@@ -144,9 +141,9 @@ trait Typers extends Adaptations with Tags {
argResultsBuff += res
if (res.isSuccess) {
- argBuff += mkArg(res.tree, param.name)
+ argBuff += mkArg(param.name, res.tree)
} else {
- mkArg = mkNamedArg // don't pass the default argument (if any) here, but start emitting named arguments for the following args
+ mkArg = gen.mkNamedArg // don't pass the default argument (if any) here, but start emitting named arguments for the following args
if (!param.hasDefault && !paramFailed) {
context.errBuffer.find(_.kind == ErrorKinds.Divergent) match {
case Some(divergentImplicit) =>
@@ -683,7 +680,15 @@ trait Typers extends Adaptations with Tags {
if (context1.hasErrors) {
stopStats()
SilentTypeError(context1.errBuffer.head)
- } else SilentResultValue(result)
+ } else {
+ // If we have a successful result, emit any warnings it created.
+ if (context1.hasWarnings) {
+ context1.flushAndReturnWarningsBuffer() foreach {
+ case (pos, msg) => unit.warning(pos, msg)
+ }
+ }
+ SilentResultValue(result)
+ }
} else {
assert(context.bufferErrors || isPastTyper, "silent mode is not available past typer")
withSavedContext(context){
@@ -1690,8 +1695,8 @@ trait Typers extends Adaptations with Tags {
*/
def validateParentClasses(parents: List[Tree], selfType: Type) {
val pending = ListBuffer[AbsTypeError]()
- def validateDynamicParent(parent: Symbol) =
- if (parent == DynamicClass) checkFeature(parent.pos, DynamicsFeature)
+ def validateDynamicParent(parent: Symbol, parentPos: Position) =
+ if (parent == DynamicClass) checkFeature(parentPos, DynamicsFeature)
def validateParentClass(parent: Tree, superclazz: Symbol) =
if (!parent.isErrorTyped) {
@@ -1738,7 +1743,7 @@ trait Typers extends Adaptations with Tags {
if (parents exists (p => p != parent && p.tpe.typeSymbol == psym && !psym.isError))
pending += ParentInheritedTwiceError(parent, psym)
- validateDynamicParent(psym)
+ validateDynamicParent(psym, parent.pos)
}
if (!parents.isEmpty && parents.forall(!_.isErrorTyped)) {
@@ -1781,12 +1786,16 @@ trait Typers extends Adaptations with Tags {
val impl2 = finishMethodSynthesis(impl1, clazz, context)
if (clazz.isTrait && clazz.info.parents.nonEmpty && clazz.info.firstParent.typeSymbol == AnyClass)
checkEphemeral(clazz, impl2.body)
- if ((clazz != ClassfileAnnotationClass) &&
- (clazz isNonBottomSubClass ClassfileAnnotationClass))
- restrictionWarning(cdef.pos, unit,
- "subclassing Classfile does not\n"+
- "make your annotation visible at runtime. If that is what\n"+
- "you want, you must write the annotation class in Java.")
+
+ if ((clazz isNonBottomSubClass ClassfileAnnotationClass) && (clazz != ClassfileAnnotationClass)) {
+ if (!clazz.owner.isPackageClass)
+ unit.error(clazz.pos, "inner classes cannot be classfile annotations")
+ else restrictionWarning(cdef.pos, unit,
+ """|subclassing Classfile does not
+ |make your annotation visible at runtime. If that is what
+ |you want, you must write the annotation class in Java.""".stripMargin)
+ }
+
if (!isPastTyper) {
for (ann <- clazz.getAnnotation(DeprecatedAttr)) {
val m = companionSymbolOf(clazz, context)
@@ -1919,7 +1928,7 @@ trait Typers extends Adaptations with Tags {
if (clazz.isTrait && hasSuperArgs(parents1.head))
ConstrArgsInParentOfTraitError(parents1.head, clazz)
- if ((clazz isSubClass ClassfileAnnotationClass) && !clazz.owner.isPackageClass)
+ if ((clazz isSubClass ClassfileAnnotationClass) && !clazz.isTopLevel)
unit.error(clazz.pos, "inner classes cannot be classfile annotations")
if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members
@@ -3093,10 +3102,10 @@ trait Typers extends Adaptations with Tags {
val (namelessArgs, argPos) = removeNames(Typer.this)(args, params)
if (namelessArgs exists (_.isErroneous)) {
duplErrTree
- } else if (!isIdentity(argPos) && !sameLength(formals, params))
- // !isIdentity indicates that named arguments are used to re-order arguments
+ } else if (!allArgsArePositional(argPos) && !sameLength(formals, params))
+ // !allArgsArePositional indicates that named arguments are used to re-order arguments
duplErrorTree(MultipleVarargError(tree))
- else if (isIdentity(argPos) && !isNamedApplyBlock(fun)) {
+ else if (allArgsArePositional(argPos) && !isNamedApplyBlock(fun)) {
// if there's no re-ordering, and fun is not transformed, no need to transform
// more than an optimization, e.g. important in "synchronized { x = update-x }"
checkNotMacro()
@@ -3146,7 +3155,7 @@ trait Typers extends Adaptations with Tags {
}
if (!sameLength(formals, args) || // wrong nb of arguments
- (args exists isNamed) || // uses a named argument
+ (args exists isNamedArg) || // uses a named argument
isNamedApplyBlock(fun)) { // fun was transformed to a named apply block =>
// integrate this application into the block
if (dyna.isApplyDynamicNamed(fun)) dyna.typedNamedApply(tree, fun, args, mode, pt)
@@ -3354,7 +3363,12 @@ trait Typers extends Adaptations with Tags {
// return the corresponding extractor (an instance of ClassTag[`pt`])
def extractorForUncheckedType(pos: Position, pt: Type): Option[Tree] = if (isPastTyper) None else {
// only look at top-level type, can't (reliably) do anything about unchecked type args (in general)
- pt.normalize.typeConstructor match {
+ // but at least make a proper type before passing it elsewhere
+ val pt1 = pt.dealias match {
+ case tr @ TypeRef(pre, sym, args) if args.nonEmpty => copyTypeRef(tr, pre, sym, sym.typeParams map (_.tpeHK)) // replace actual type args with dummies
+ case pt1 => pt1
+ }
+ pt1 match {
// if at least one of the types in an intersection is checkable, use the checkable ones
// this avoids problems as in run/matchonseq.scala, where the expected type is `Coll with scala.collection.SeqLike`
// Coll is an abstract type, but SeqLike of course is not
@@ -3369,18 +3383,24 @@ trait Typers extends Adaptations with Tags {
else None
case _ => None
- }
+ }
}
/**
* Convert an annotation constructor call into an AnnotationInfo.
- *
- * @param annClass the expected annotation class
*/
- def typedAnnotation(ann: Tree, mode: Mode = EXPRmode, selfsym: Symbol = NoSymbol, annClass: Symbol = AnnotationClass, requireJava: Boolean = false): AnnotationInfo = {
+ def typedAnnotation(ann: Tree, mode: Mode = EXPRmode, selfsym: Symbol = NoSymbol): AnnotationInfo = {
var hasError: Boolean = false
val pending = ListBuffer[AbsTypeError]()
+ def finish(res: AnnotationInfo): AnnotationInfo = {
+ if (hasError) {
+ pending.foreach(ErrorUtils.issueTypeError)
+ ErroneousAnnotation
+ }
+ else res
+ }
+
def reportAnnotationError(err: AbsTypeError) = {
pending += err
hasError = true
@@ -3391,7 +3411,10 @@ trait Typers extends Adaptations with Tags {
* floats and literals in particular) are not yet folded.
*/
def tryConst(tr: Tree, pt: Type): Option[LiteralAnnotArg] = {
- val const: Constant = typed(constfold(tr), EXPRmode, pt) match {
+ // The typed tree may be relevantly different than the tree `tr`,
+ // e.g. it may have encountered an implicit conversion.
+ val ttree = typed(constfold(tr), EXPRmode, pt)
+ val const: Constant = ttree match {
case l @ Literal(c) if !l.isErroneous => c
case tree => tree.tpe match {
case ConstantType(c) => c
@@ -3400,7 +3423,7 @@ trait Typers extends Adaptations with Tags {
}
if (const == null) {
- reportAnnotationError(AnnotationNotAConstantError(tr)); None
+ reportAnnotationError(AnnotationNotAConstantError(ttree)); None
} else if (const.value == null) {
reportAnnotationError(AnnotationArgNullError(tr)); None
} else
@@ -3415,7 +3438,14 @@ trait Typers extends Adaptations with Tags {
reportAnnotationError(ArrayConstantsError(tree)); None
case ann @ Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
- val annInfo = typedAnnotation(ann, mode, NoSymbol, pt.typeSymbol, true)
+ val annInfo = typedAnnotation(ann, mode, NoSymbol)
+ val annType = annInfo.tpe
+
+ if (!annType.typeSymbol.isSubClass(pt.typeSymbol))
+ reportAnnotationError(AnnotationTypeMismatchError(tpt, annType, annType))
+ else if (!annType.typeSymbol.isSubClass(ClassfileAnnotationClass))
+ reportAnnotationError(NestedAnnotationError(ann, annType))
+
if (annInfo.atp.isErroneous) { hasError = true; None }
else Some(NestedAnnotArg(annInfo))
@@ -3450,44 +3480,42 @@ trait Typers extends Adaptations with Tags {
}
// begin typedAnnotation
- val (fun, argss) = {
- def extract(fun: Tree, outerArgss: List[List[Tree]]):
- (Tree, List[List[Tree]]) = fun match {
- case Apply(f, args) =>
- extract(f, args :: outerArgss)
- case Select(New(tpt), nme.CONSTRUCTOR) =>
- (fun, outerArgss)
- case _ =>
- reportAnnotationError(UnexpectedTreeAnnotation(fun))
- (setError(fun), outerArgss)
- }
- extract(ann, List())
- }
-
- val res = if (fun.isErroneous) ErroneousAnnotation
- else {
- val typedFun @ Select(New(tpt), _) = typed(fun, mode.forFunMode, WildcardType)
- val annType = tpt.tpe
+ val treeInfo.Applied(fun0, targs, argss) = ann
+ if (fun0.isErroneous)
+ return finish(ErroneousAnnotation)
+ val typedFun0 = typed(fun0, mode.forFunMode, WildcardType)
+ val typedFunPart = (
+ // If there are dummy type arguments in typeFun part, it suggests we
+ // must type the actual constructor call, not only the select. The value
+ // arguments are how the type arguments will be inferred.
+ if (targs.isEmpty && typedFun0.exists(t => isDummyAppliedType(t.tpe)))
+ logResult(s"Retyped $typedFun0 to find type args")(typed(argss.foldLeft(fun0)(Apply(_, _))))
+ else
+ typedFun0
+ )
+ val treeInfo.Applied(typedFun @ Select(New(annTpt), _), _, _) = typedFunPart
+ val annType = annTpt.tpe
- if (typedFun.isErroneous) ErroneousAnnotation
+ finish(
+ if (typedFun.isErroneous)
+ ErroneousAnnotation
else if (annType.typeSymbol isNonBottomSubClass ClassfileAnnotationClass) {
// annotation to be saved as java classfile annotation
val isJava = typedFun.symbol.owner.isJavaDefined
- if (!annType.typeSymbol.isNonBottomSubClass(annClass)) {
- reportAnnotationError(AnnotationTypeMismatchError(tpt, annClass.tpe, annType))
- } else if (argss.length > 1) {
+ if (argss.length > 1) {
reportAnnotationError(MultipleArgumentListForAnnotationError(ann))
- } else {
+ }
+ else {
val annScope = annType.decls
.filter(sym => sym.isMethod && !sym.isConstructor && sym.isJavaDefined)
val names = new scala.collection.mutable.HashSet[Symbol]
- def hasValue = names exists (_.name == nme.value)
names ++= (if (isJava) annScope.iterator
else typedFun.tpe.params.iterator)
+
+ def hasValue = names exists (_.name == nme.value)
val args = argss match {
- case List(List(arg)) if !isNamed(arg) && hasValue =>
- List(new AssignOrNamedArg(Ident(nme.value), arg))
- case as :: _ => as
+ case (arg :: Nil) :: Nil if !isNamedArg(arg) && hasValue => gen.mkNamedArg(nme.value, arg) :: Nil
+ case args :: Nil => args
}
val nvPairs = args map {
@@ -3520,13 +3548,12 @@ trait Typers extends Adaptations with Tags {
if (hasError) ErroneousAnnotation
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))
- } else {
+ }
+ else {
val typedAnn = if (selfsym == NoSymbol) {
// local dummy fixes SI-5544
val localTyper = newTyper(context.make(ann, context.owner.newLocalDummy(ann.pos)))
- localTyper.typed(ann, mode, annClass.tpe)
+ localTyper.typed(ann, mode, annType)
}
else {
// Since a selfsym is supplied, the annotation should have an extra
@@ -3540,11 +3567,11 @@ trait Typers extends Adaptations with Tags {
// sometimes does. The problem is that "self" ident's within
// annot.constr will retain the old symbol from the previous typing.
val func = Function(funcparm :: Nil, ann.duplicate)
- val funcType = appliedType(FunctionClass(1), selfsym.info, annClass.tpe_*)
+ val funcType = appliedType(FunctionClass(1), selfsym.info, annType)
val Function(arg :: Nil, rhs) = typed(func, mode, funcType)
rhs.substituteSymbols(arg.symbol :: Nil, selfsym :: Nil)
- }
+ }
def annInfo(t: Tree): AnnotationInfo = t match {
case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
@@ -3571,13 +3598,7 @@ trait Typers extends Adaptations with Tags {
if ((typedAnn.tpe == null) || typedAnn.tpe.isErroneous) ErroneousAnnotation
else annInfo(typedAnn)
- }
- }
-
- if (hasError) {
- pending.foreach(ErrorUtils.issueTypeError)
- ErroneousAnnotation
- } else res
+ })
}
def isRawParameter(sym: Symbol) = // is it a type parameter leaked by a raw type?
@@ -3697,7 +3718,8 @@ trait Typers extends Adaptations with Tags {
else containsDef(owner, sym) || isRawParameter(sym) || isCapturedExistential(sym)
def containsLocal(tp: Type): Boolean =
tp exists (t => isLocal(t.typeSymbol) || isLocal(t.termSymbol))
- val normalizeLocals = new TypeMap {
+
+ val dealiasLocals = new TypeMap {
def apply(tp: Type): Type = tp match {
case TypeRef(pre, sym, args) =>
if (sym.isAliasType && containsLocal(tp)) apply(tp.dealias)
@@ -3750,9 +3772,9 @@ trait Typers extends Adaptations with Tags {
for (sym <- remainingSyms) addLocals(sym.existentialBound)
}
- val normalizedTpe = normalizeLocals(tree.tpe)
- addLocals(normalizedTpe)
- packSymbols(localSyms.toList, normalizedTpe)
+ val dealiasedType = dealiasLocals(tree.tpe)
+ addLocals(dealiasedType)
+ packSymbols(localSyms.toList, dealiasedType)
}
def typedClassOf(tree: Tree, tpt: Tree, noGen: Boolean = false) =
@@ -4788,7 +4810,7 @@ trait Typers extends Adaptations with Tags {
else if (isPredefMemberNamed(sym, nme.classOf) && pt.typeSymbol == ClassClass && pt.typeArgs.nonEmpty)
typedClassOf(tree, TypeTree(pt.typeArgs.head))
else {
- val pre1 = if (sym.owner.isPackageClass) sym.owner.thisType else if (qual == EmptyTree) NoPrefix else qual.tpe
+ val pre1 = if (sym.isTopLevel) sym.owner.thisType else if (qual == EmptyTree) NoPrefix else qual.tpe
val tree1 = if (qual == EmptyTree) tree else atPos(tree.pos)(Select(atPos(tree.pos.focusStart)(qual), name))
val (tree2, pre2) = makeAccessible(tree1, sym, pre1, qual)
// SI-5967 Important to replace param type A* with Seq[A] when seen from from a reference, to avoid
@@ -4919,13 +4941,15 @@ trait Typers extends Adaptations with Tags {
var block1 = typed(tree.block, pt)
var catches1 = typedCases(tree.catches, ThrowableClass.tpe, pt)
- for (cdef <- catches1; if treeInfo catchesThrowable cdef) {
- val name = (treeInfo assignedNameOfPattern cdef).decoded
- context.warning(cdef.pat.pos,
- s"""|This catches all Throwables, which often has undesirable consequences.
- |If intentional, use `case $name : Throwable` to clear this warning.""".stripMargin
- )
+ for (cdef <- catches1 if !isPastTyper && cdef.guard.isEmpty) {
+ def warn(name: Name) = context.warning(cdef.pat.pos, s"This catches all Throwables. If this is really intended, use `case ${name.decoded} : Throwable` to clear this warning.")
+ def unbound(t: Tree) = t.symbol == null || t.symbol == NoSymbol
+ cdef.pat match {
+ case Bind(name, i @ Ident(_)) if unbound(i) => warn(name)
+ case i @ Ident(name) if unbound(i) => warn(name)
+ case _ =>
}
+ }
val finalizer1 =
if (tree.finalizer.isEmpty) tree.finalizer
diff --git a/src/compiler/scala/tools/util/SocketServer.scala b/src/compiler/scala/tools/util/SocketServer.scala
index d29a370c28..1b06ce2ff2 100644
--- a/src/compiler/scala/tools/util/SocketServer.scala
+++ b/src/compiler/scala/tools/util/SocketServer.scala
@@ -16,8 +16,8 @@ trait CompileOutputCommon {
def verbose: Boolean
def info(msg: String) = if (verbose) echo(msg)
- def echo(msg: String) = Console println msg
- def warn(msg: String) = System.err println msg
+ def echo(msg: String) = {Console println msg; Console.flush}
+ def warn(msg: String) = {Console.err println msg; Console.flush}
def fatal(msg: String) = { warn(msg) ; sys.exit(1) }
}
diff --git a/src/library/scala/collection/mutable/HashSet.scala b/src/library/scala/collection/mutable/HashSet.scala
index b5fa557687..c4c68fdb7a 100644
--- a/src/library/scala/collection/mutable/HashSet.scala
+++ b/src/library/scala/collection/mutable/HashSet.scala
@@ -86,7 +86,7 @@ extends AbstractSet[A]
}
private def readObject(in: java.io.ObjectInputStream) {
- init(in, x => x)
+ init(in, x => ())
}
/** Toggles whether a size map is used to track hash map statistics.
diff --git a/src/library/scala/collection/parallel/mutable/ParArray.scala b/src/library/scala/collection/parallel/mutable/ParArray.scala
index db4a59f6ba..770599e9d3 100644
--- a/src/library/scala/collection/parallel/mutable/ParArray.scala
+++ b/src/library/scala/collection/parallel/mutable/ParArray.scala
@@ -470,7 +470,6 @@ self =>
Array.copy(arr, i, targetarr, 0, until - i)
pac.buff.size = pac.buff.size + until - i
pac.buff.lastPtr.size = until - i
- pac
} otherwise {
copy2builder_quick(cb, arr, until, i)
i = until
@@ -532,7 +531,6 @@ self =>
val targetarr: Array[Any] = pac.lastbuff.internalArray.asInstanceOf[Array[Any]]
reverse2combiner_quick(targetarr, arr, 0, i, until)
pac.lastbuff.setInternalSize(sz)
- pac
} otherwise {
cb.ifIs[UnrolledParArrayCombiner[T]] {
pac =>
@@ -543,7 +541,6 @@ self =>
reverse2combiner_quick(targetarr, arr, 0, i, until)
pac.buff.size = pac.buff.size + sz
pac.buff.lastPtr.size = sz
- pac
} otherwise super.reverse2combiner(cb)
}
cb
diff --git a/src/library/scala/collection/parallel/mutable/ParHashSet.scala b/src/library/scala/collection/parallel/mutable/ParHashSet.scala
index 68a5f20cb5..e5de6182e6 100644
--- a/src/library/scala/collection/parallel/mutable/ParHashSet.scala
+++ b/src/library/scala/collection/parallel/mutable/ParHashSet.scala
@@ -85,7 +85,7 @@ extends ParSet[T]
}
private def readObject(in: java.io.ObjectInputStream) {
- init(in, x => x)
+ init(in, x => ())
}
import scala.collection.DebugUtils._
diff --git a/src/library/scala/sys/process/ProcessBuilder.scala b/src/library/scala/sys/process/ProcessBuilder.scala
index d0b2ecfe73..30fd4d83ff 100644
--- a/src/library/scala/sys/process/ProcessBuilder.scala
+++ b/src/library/scala/sys/process/ProcessBuilder.scala
@@ -23,7 +23,7 @@ import ProcessBuilder._
* based on these factories made available in the package object
* [[scala.sys.process]]. Here are some examples:
* {{{
- * import.scala.sys.process._
+ * import scala.sys.process._
*
* // Executes "ls" and sends output to stdout
* "ls".!
diff --git a/src/library/scala/throws.scala b/src/library/scala/throws.scala
index 159f1f02f4..5a5dd9a1f5 100644
--- a/src/library/scala/throws.scala
+++ b/src/library/scala/throws.scala
@@ -24,5 +24,5 @@ package scala
* @since 2.1
*/
class throws[T <: Throwable](cause: String = "") extends scala.annotation.StaticAnnotation {
- def this(clazz: Class[T]) = this()
+ def this(clazz: Class[T]) = this("")
}
diff --git a/src/partest/scala/tools/partest/PartestTask.scala b/src/partest/scala/tools/partest/PartestTask.scala
index d320f20616..13207b16fd 100644
--- a/src/partest/scala/tools/partest/PartestTask.scala
+++ b/src/partest/scala/tools/partest/PartestTask.scala
@@ -346,7 +346,7 @@ class PartestTask extends Task with CompilationPathProperty {
javacmd foreach (x => antFileManager.JAVACMD = x.getAbsolutePath)
javaccmd foreach (x => antFileManager.JAVAC_CMD = x.getAbsolutePath)
- scalacArgsFlat foreach (antFileManager.SCALAC_OPTS = _)
+ scalacArgsFlat foreach (antFileManager.SCALAC_OPTS ++= _)
timeout foreach (antFileManager.timeout = _)
type TFSet = (Array[File], String, String)
diff --git a/src/partest/scala/tools/partest/nest/SBTRunner.scala b/src/partest/scala/tools/partest/nest/SBTRunner.scala
index b0ce6579ac..20f9c701d5 100644
--- a/src/partest/scala/tools/partest/nest/SBTRunner.scala
+++ b/src/partest/scala/tools/partest/nest/SBTRunner.scala
@@ -46,7 +46,7 @@ object SBTRunner extends DirectRunner {
case x => sys.error("Unknown command line options: " + x)
}
val config = parseArgs(args, CommandLineOptions())
- fileManager.SCALAC_OPTS = config.scalacOptions
+ fileManager.SCALAC_OPTS ++= config.scalacOptions
fileManager.CLASSPATH = config.classpath getOrElse sys.error("No classpath set")
def findClasspath(jar: String, name: String): Option[String] = {
diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
index 7a972c3f1a..70b8bd9be5 100644
--- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
@@ -12,7 +12,7 @@ import scala.collection.immutable.ListMap
/** AnnotationInfo and its helpers */
trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
- import definitions.{ ThrowsClass, StaticAnnotationClass, isMetaAnnotation }
+ import definitions.{ ThrowsClass, ThrowableClass, StaticAnnotationClass, isMetaAnnotation }
// Common annotation code between Symbol and Type.
// For methods altering the annotation list, on Symbol it mutates
@@ -334,7 +334,7 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
* as well as “new-stye” `@throws[Exception]("cause")` annotations.
*/
object ThrownException {
- def unapply(ann: AnnotationInfo): Option[Symbol] =
+ def unapply(ann: AnnotationInfo): Option[Symbol] = {
ann match {
case AnnotationInfo(tpe, _, _) if tpe.typeSymbol != ThrowsClass =>
None
@@ -342,8 +342,11 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
case AnnotationInfo(_, List(Literal(Constant(tpe: Type))), _) =>
Some(tpe.typeSymbol)
// new-style: @throws[Exception], @throws[Exception]("cause")
- case AnnotationInfo(TypeRef(_, _, args), _, _) =>
- Some(args.head.typeSymbol)
+ case AnnotationInfo(TypeRef(_, _, arg :: _), _, _) =>
+ Some(arg.typeSymbol)
+ case AnnotationInfo(TypeRef(_, _, Nil), _, _) =>
+ Some(ThrowableClass)
}
+ }
}
}
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index dbf07c7f06..12fb77dab1 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -714,7 +714,10 @@ trait Definitions extends api.StandardDefinitions {
* C[E1, ..., En] forSome { E1 >: LB1 <: UB1 ... en >: LBn <: UBn }.
*/
def classExistentialType(clazz: Symbol): Type =
- newExistentialType(clazz.typeParams, clazz.tpe_*)
+ existentialAbstraction(clazz.typeParams, clazz.tpe_*)
+
+ def unsafeClassExistentialType(clazz: Symbol): Type =
+ existentialAbstraction(clazz.unsafeTypeParams, clazz.tpe_*)
// members of class scala.Any
lazy val Any_== = enterNewMethod(AnyClass, nme.EQ, anyparam, booltype, FINAL)
@@ -1139,7 +1142,7 @@ trait Definitions extends api.StandardDefinitions {
}
def flatNameString(sym: Symbol, separator: Char): String =
if (sym == NoSymbol) "" // be more resistant to error conditions, e.g. neg/t3222.scala
- else if (sym.owner.isPackageClass) sym.javaClassName
+ else if (sym.isTopLevel) sym.javaClassName
else flatNameString(sym.owner, separator) + nme.NAME_JOIN_STRING + sym.simpleName
def signature1(etp: Type): String = {
if (etp.typeSymbol == ArrayClass) "[" + signature1(erasure(etp.normalize.typeArgs.head))
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 2d42d2df58..0969d9e3fa 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -591,7 +591,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Does this symbol denote a wrapper created by the repl? */
final def isInterpreterWrapper = (
(this hasFlag MODULE)
- && owner.isPackageClass
+ && isTopLevel
&& nme.isReplWrapperName(name)
)
final def getFlag(mask: Long): Long = {
@@ -813,7 +813,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Is this symbol effectively final? I.e, it cannot be overridden */
final def isEffectivelyFinal: Boolean = (
(this hasFlag FINAL | PACKAGE)
- || isModuleOrModuleClass && (owner.isPackageClass || !settings.overrideObjects.value)
+ || isModuleOrModuleClass && (isTopLevel || !settings.overrideObjects.value)
|| isTerm && (
isPrivate
|| isLocal
@@ -821,6 +821,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
)
)
+ /** Is this symbol owned by a package? */
+ final def isTopLevel = owner.isPackageClass
+
/** Is this symbol locally defined? I.e. not accessed from outside `this` instance */
final def isLocal: Boolean = owner.isTerm
@@ -870,7 +873,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// Does not always work if the rawInfo is a SourcefileLoader, see comment
// in "def coreClassesFirst" in Global.
- def exists = !owner.isPackageClass || { rawInfo.load(this); rawInfo != NoType }
+ def exists = !isTopLevel || { rawInfo.load(this); rawInfo != NoType }
final def isInitialized: Boolean =
validTo != NoPeriod
@@ -1916,7 +1919,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** The top-level class containing this symbol. */
def enclosingTopLevelClass: Symbol =
- if (owner.isPackageClass) {
+ if (isTopLevel) {
if (isClass) this else moduleClass
} else owner.enclosingTopLevelClass
@@ -2889,7 +2892,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def isAnonymousClass = name containsName tpnme.ANON_CLASS_NAME
override def isConcreteClass = !(this hasFlag ABSTRACT | TRAIT)
override def isJavaInterface = hasAllFlags(JAVA | TRAIT)
- override def isNestedClass = !owner.isPackageClass
+ override def isNestedClass = !isTopLevel
override def isNumericValueClass = definitions.isNumericValueClass(this)
override def isNumeric = isNumericValueClass
override def isPackageObjectClass = isModuleClass && (name == tpnme.PACKAGE)
@@ -2915,7 +2918,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def isLocalClass = (
isAnonOrRefinementClass
|| isLocal
- || !owner.isPackageClass && owner.isLocalClass
+ || !isTopLevel && owner.isLocalClass
)
override def enclClassChain = this :: owner.enclClassChain
@@ -2944,7 +2947,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
override def associatedFile = (
- if (!owner.isPackageClass) super.associatedFile
+ if (!isTopLevel) super.associatedFile
else if (_associatedFile eq null) NoAbstractFile // guarantee not null, but save cost of initializing the var
else _associatedFile
)
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index 6a2006e56f..54a85dee86 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -271,6 +271,10 @@ abstract class TreeGen extends macros.TreeBuilder {
case _ => Constant(null)
}
+ /** Wrap an expression in a named argument. */
+ def mkNamedArg(name: Name, tree: Tree): Tree = mkNamedArg(Ident(name), tree)
+ def mkNamedArg(lhs: Tree, rhs: Tree): Tree = atPos(rhs.pos)(AssignOrNamedArg(lhs, rhs))
+
/** Builds a tuple */
def mkTuple(elems: List[Tree]): Tree =
if (elems.isEmpty) Literal(Constant())
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index 032a4aebef..4c67771485 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -65,6 +65,9 @@ abstract class TreeInfo {
false
}
+ // TODO SI-5304 tighten this up so we don't elide side effect in module loads
+ def isQualifierSafeToElide(tree: Tree): Boolean = isExprSafeToInline(tree)
+
/** Is tree an expression which can be inlined without affecting program semantics?
*
* Note that this is not called "isExprPure" since purity (lack of side-effects)
@@ -370,6 +373,14 @@ abstract class TreeInfo {
case _ => false
}
+ /** Translates an Assign(_, _) node to AssignOrNamedArg(_, _) if
+ * the lhs is a simple ident. Otherwise returns unchanged.
+ */
+ def assignmentToMaybeNamedArg(tree: Tree) = tree match {
+ case t @ Assign(id: Ident, rhs) => atPos(t.pos)(AssignOrNamedArg(id, rhs))
+ case t => t
+ }
+
/** Is name a left-associative operator? */
def isLeftAssoc(operator: Name) = operator.nonEmpty && (operator.endChar != ':')
@@ -467,7 +478,7 @@ abstract class TreeInfo {
tp match {
case TypeRef(pre, sym, args) =>
- args.isEmpty && (sym.owner.isPackageClass || isSimple(pre))
+ args.isEmpty && (sym.isTopLevel || isSimple(pre))
case NoPrefix =>
true
case _ =>
@@ -605,6 +616,12 @@ abstract class TreeInfo {
}
loop(tree)
}
+
+ override def toString = {
+ val tstr = if (targs.isEmpty) "" else targs.mkString("[", ", ", "]")
+ val astr = argss map (args => args.mkString("(", ", ", ")")) mkString ""
+ s"$core$tstr$astr"
+ }
}
/** Returns a wrapper that knows how to destructure and analyze applications.
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 77634c1894..1bb3fd300b 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -835,23 +835,27 @@ trait Types extends api.Types { self: SymbolTable =>
}
/** Is this type a subtype of that type in a pattern context?
- * Any type arguments on the right hand side are replaced with
+ * Dummy type arguments on the right hand side are replaced with
* fresh existentials, except for Arrays.
*
* See bug1434.scala for an example of code which would fail
* if only a <:< test were applied.
*/
- def matchesPattern(that: Type): Boolean = {
- (this <:< that) || ((this, that) match {
- case (TypeRef(_, ArrayClass, List(arg1)), TypeRef(_, ArrayClass, List(arg2))) if arg2.typeSymbol.typeParams.nonEmpty =>
- arg1 matchesPattern arg2
- case (_, TypeRef(_, _, args)) =>
- val newtp = existentialAbstraction(args map (_.typeSymbol), that)
- !(that =:= newtp) && (this <:< newtp)
- case _ =>
- false
- })
- }
+ def matchesPattern(that: Type): Boolean = (this <:< that) || (that match {
+ case ArrayTypeRef(elem2) if elem2.typeConstructor.isHigherKinded =>
+ this match {
+ case ArrayTypeRef(elem1) => elem1 matchesPattern elem2
+ case _ => false
+ }
+ case TypeRef(_, sym, args) =>
+ val that1 = existentialAbstraction(args map (_.typeSymbol), that)
+ (that ne that1) && (this <:< that1) && {
+ log(s"$this.matchesPattern($that) depended on discarding args and testing <:< $that1")
+ true
+ }
+ case _ =>
+ false
+ })
def stat_<:<(that: Type): Boolean = {
if (Statistics.canEnable) Statistics.incCounter(subtypeCount)
@@ -2461,7 +2465,9 @@ trait Types extends api.Types { self: SymbolTable =>
targs match {
case in :: out :: Nil if !isTupleType(in) =>
// A => B => C should be (A => B) => C or A => (B => C)
- val in_s = if (isFunctionType(in)) "(" + in + ")" else "" + in
+ // Also if A is byname, then we want (=> A) => B because => is right associative and => A => B
+ // would mean => (A => B) which is a different type
+ val in_s = if (isFunctionType(in) || isByNameParamType(in)) "(" + in + ")" else "" + in
val out_s = if (isFunctionType(out)) "(" + out + ")" else "" + out
in_s + " => " + out_s
case xs =>
@@ -2865,6 +2871,13 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
+ object ArrayTypeRef {
+ def unapply(tp: Type) = tp match {
+ case TypeRef(_, ArrayClass, arg :: Nil) => Some(arg)
+ case _ => None
+ }
+ }
+
//@M
// a TypeVar used to be a case class with only an origin and a constr
// then, constr became mutable (to support UndoLog, I guess),
@@ -2934,20 +2947,6 @@ trait Types extends api.Types { self: SymbolTable =>
createTypeVar(tparam.tpeHK, deriveConstraint(tparam), Nil, tparam.typeParams, untouchable)
}
- /** Repack existential types, otherwise they sometimes get unpacked in the
- * wrong location (type inference comes up with an unexpected skolem)
- */
- def repackExistential(tp: Type): Type = (
- if (tp == NoType) tp
- else existentialAbstraction(existentialsInType(tp), tp)
- )
-
- def containsExistential(tpe: Type) =
- tpe exists typeIsExistentiallyBound
-
- def existentialsInType(tpe: Type) =
- tpe withFilter typeIsExistentiallyBound map (_.typeSymbol)
-
/** Precondition: params.nonEmpty. (args.nonEmpty enforced structurally.)
*/
class HKTypeVar(
@@ -3733,17 +3732,14 @@ trait Types extends api.Types { self: SymbolTable =>
}
/** Type with all top-level occurrences of abstract types replaced by their bounds */
- def abstractTypesToBounds(tp: Type): Type = tp match { // @M don't normalize here (compiler loops on pos/bug1090.scala )
- case TypeRef(_, sym, _) if sym.isAbstractType =>
- abstractTypesToBounds(tp.bounds.hi)
- case TypeRef(_, sym, _) if sym.isAliasType =>
- abstractTypesToBounds(tp.normalize)
- case rtp @ RefinedType(parents, decls) =>
- copyRefinedType(rtp, parents mapConserve abstractTypesToBounds, decls)
- case AnnotatedType(_, underlying, _) =>
- abstractTypesToBounds(underlying)
- case _ =>
- tp
+ object abstractTypesToBounds extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(_, sym, _) if sym.isAliasType => apply(tp.dealias)
+ case TypeRef(_, sym, _) if sym.isAbstractType => apply(tp.bounds.hi)
+ case rtp @ RefinedType(parents, decls) => copyRefinedType(rtp, parents mapConserve this, decls)
+ case AnnotatedType(_, _, _) => mapOver(tp)
+ case _ => tp // no recursion - top level only
+ }
}
// Set to true for A* => Seq[A]
@@ -3914,7 +3910,7 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
class ClassUnwrapper(existential: Boolean) extends TypeUnwrapper(poly = true, existential, annotated = true, nullary = false) {
- override def apply(tp: Type) = super.apply(tp.normalize)
+ override def apply(tp: Type) = super.apply(tp.normalize) // normalize is required here
}
object unwrapToClass extends ClassUnwrapper(existential = true) { }
@@ -4161,6 +4157,26 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
+ /** Repack existential types, otherwise they sometimes get unpacked in the
+ * wrong location (type inference comes up with an unexpected skolem)
+ */
+ def repackExistential(tp: Type): Type = (
+ if (tp == NoType) tp
+ else existentialAbstraction(existentialsInType(tp), tp)
+ )
+
+ def containsExistential(tpe: Type) = tpe exists typeIsExistentiallyBound
+ def existentialsInType(tpe: Type) = tpe withFilter typeIsExistentiallyBound map (_.typeSymbol)
+
+ private def isDummyOf(tpe: Type)(targ: Type) = {
+ val sym = targ.typeSymbol
+ sym.isTypeParameter && sym.owner == tpe.typeSymbol
+ }
+ def isDummyAppliedType(tp: Type) = tp.dealias match {
+ case tr @ TypeRef(_, _, args) => args exists isDummyOf(tr)
+ case _ => false
+ }
+
def typeParamsToExistentials(clazz: Symbol, tparams: List[Symbol]): List[Symbol] = {
val eparams = mapWithIndex(tparams)((tparam, i) =>
clazz.newExistential(newTypeName("?"+i), clazz.pos) setInfo tparam.info.bounds)
@@ -4170,19 +4186,21 @@ trait Types extends api.Types { self: SymbolTable =>
def typeParamsToExistentials(clazz: Symbol): List[Symbol] =
typeParamsToExistentials(clazz, clazz.typeParams)
+ def isRawIfWithoutArgs(sym: Symbol) = sym.isClass && sym.typeParams.nonEmpty && sym.isJavaDefined
+ /** Is type tp a ''raw type''? */
// note: it's important to write the two tests in this order,
// as only typeParams forces the classfile to be read. See #400
- private def isRawIfWithoutArgs(sym: Symbol) =
- sym.isClass && sym.typeParams.nonEmpty && sym.isJavaDefined
-
- def isRaw(sym: Symbol, args: List[Type]) =
- !phase.erasedTypes && isRawIfWithoutArgs(sym) && args.isEmpty
+ def isRawType(tp: Type) = !phase.erasedTypes && (tp match {
+ case TypeRef(_, sym, Nil) => isRawIfWithoutArgs(sym)
+ case _ => false
+ })
- /** Is type tp a ''raw type''? */
- def isRawType(tp: Type) = tp match {
- case TypeRef(_, sym, args) => isRaw(sym, args)
- case _ => false
- }
+ @deprecated("Use isRawType", "2.10.1") // presently used by sbt
+ def isRaw(sym: Symbol, args: List[Type]) = (
+ !phase.erasedTypes
+ && args.isEmpty
+ && isRawIfWithoutArgs(sym)
+ )
/** The raw to existential map converts a ''raw type'' to an existential type.
* It is necessary because we might have read a raw type of a
@@ -5615,7 +5633,13 @@ trait Types extends api.Types { self: SymbolTable =>
// for (tpFresh <- tpsFresh) tpFresh.setInfo(tpFresh.info.substSym(tparams1, tpsFresh))
}
} && annotationsConform(tp1.normalize, tp2.normalize)
- case (_, _) => false // @assume !tp1.isHigherKinded || !tp2.isHigherKinded
+
+ case (PolyType(_, _), MethodType(params, _)) if params exists (_.tpe.isWildcard) =>
+ false // don't warn on HasMethodMatching on right hand side
+
+ case (ntp1, ntp2) =>
+ devWarning(s"isHKSubType0($tp1, $tp2, _) is ${tp1.getClass}, ${tp2.getClass}: ($ntp1, $ntp2)")
+ false // @assume !tp1.isHigherKinded || !tp2.isHigherKinded
// --> thus, cannot be subtypes (Any/Nothing has already been checked)
}))
@@ -5713,7 +5737,7 @@ trait Types extends api.Types { self: SymbolTable =>
case NotNullClass => tp1.isNotNull
case SingletonClass => tp1.isStable || fourthTry
case _: ClassSymbol =>
- if (isRaw(sym2, tp2.args))
+ if (isRawType(tp2))
isSubType(tp1, rawToExistential(tp2), depth)
else if (sym2.name == tpnme.REFINE_CLASS_NAME)
isSubType(tp1, sym2.info, depth)
@@ -5795,7 +5819,7 @@ trait Types extends api.Types { self: SymbolTable =>
isSingleType(tp2) && isSubType(tp1, tp2.widen, depth)
}
case _: ClassSymbol =>
- if (isRaw(sym1, tr1.args))
+ if (isRawType(tp1))
isSubType(rawToExistential(tp1), tp2, depth)
else if (sym1.isModuleClass) tp2 match {
case SingleType(pre2, sym2) => equalSymsAndPrefixes(sym1.sourceModule, pre1, sym2, pre2)
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index cdb9e7159c..2bffe398f6 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -507,7 +507,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
def erasure = symbol.moduleClass.asClass
def isStatic = true
def instance = {
- if (symbol.owner.isPackageClass)
+ if (symbol.isTopLevel)
staticSingletonInstance(classLoader, symbol.fullName)
else
if (outer == null) staticSingletonInstance(classToJava(symbol.moduleClass.asClass))
@@ -1156,11 +1156,11 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
valueClassToJavaType(clazz)
else if (clazz == ArrayClass)
noClass
- else if (clazz.owner.isPackageClass)
+ else if (clazz.isTopLevel)
javaClass(clazz.javaClassName)
else if (clazz.owner.isClass) {
val childOfClass = !clazz.owner.isModuleClass
- val childOfTopLevel = clazz.owner.owner.isPackageClass
+ val childOfTopLevel = clazz.owner.isTopLevel
val childOfTopLevelObject = clazz.owner.isModuleClass && childOfTopLevel
// suggested in https://issues.scala-lang.org/browse/SI-4023?focusedCommentId=54759#comment-54759
diff --git a/test/disabled/run/t6987.check b/test/disabled/run/t6987.check
new file mode 100644
index 0000000000..86fc96c679
--- /dev/null
+++ b/test/disabled/run/t6987.check
@@ -0,0 +1 @@
+got successful verbose results!
diff --git a/test/disabled/run/t6987.scala b/test/disabled/run/t6987.scala
new file mode 100644
index 0000000000..37e91d61ae
--- /dev/null
+++ b/test/disabled/run/t6987.scala
@@ -0,0 +1,43 @@
+import java.io._
+import tools.nsc.{CompileClient, CompileServer}
+import java.util.concurrent.{CountDownLatch, TimeUnit}
+
+object Test extends App {
+ val startupLatch = new CountDownLatch(1)
+ // we have to explicitly launch our server because when the client launches a server it uses
+ // the "scala" shell command meaning whatever version of scala (and whatever version of libraries)
+ // happens to be in the path gets used
+ val t = new Thread(new Runnable {
+ def run() = {
+ CompileServer.execute(() => startupLatch.countDown(), Array[String]())
+ }
+ })
+ t setDaemon true
+ t.start()
+ if (!startupLatch.await(2, TimeUnit.MINUTES))
+ sys error "Timeout waiting for server to start"
+
+ val baos = new ByteArrayOutputStream()
+ val ps = new PrintStream(baos)
+
+ val success = (scala.Console withOut ps) {
+ // shut down the server via the client using the verbose flag
+ CompileClient.process(Array("-shutdown", "-verbose"))
+ }
+
+ // now make sure we got success and a verbose result
+ val msg = baos.toString()
+
+ if (success) {
+ if (msg contains "Settings after normalizing paths") {
+ println("got successful verbose results!")
+ } else {
+ println("did not get the string expected, full results were:")
+ println(msg)
+ }
+ } else {
+ println("got a failure. Full results were:")
+ println(msg)
+ }
+ scala.Console.flush
+}
diff --git a/test/files/neg/annot-nonconst.check b/test/files/neg/annot-nonconst.check
index b43e58a0ca..5b3da7a13c 100644
--- a/test/files/neg/annot-nonconst.check
+++ b/test/files/neg/annot-nonconst.check
@@ -8,7 +8,7 @@ make your annotation visible at runtime. If that is what
you want, you must write the annotation class in Java.
class Ann2(value: String) extends annotation.ClassfileAnnotation
^
-annot-nonconst.scala:6: error: annotation argument needs to be a constant; found: n
+annot-nonconst.scala:6: error: annotation argument needs to be a constant; found: Test.this.n
@Length(n) def foo = "foo"
^
annot-nonconst.scala:7: error: annotation argument cannot be null
diff --git a/test/files/neg/catch-all.check b/test/files/neg/catch-all.check
index 2d58dd99a8..aaf51480c3 100644
--- a/test/files/neg/catch-all.check
+++ b/test/files/neg/catch-all.check
@@ -1,13 +1,10 @@
-catch-all.scala:2: warning: This catches all Throwables, which often has undesirable consequences.
-If intentional, use `case _ : Throwable` to clear this warning.
+catch-all.scala:2: warning: This catches all Throwables. If this is really intended, use `case _ : Throwable` to clear this warning.
try { "warn" } catch { case _ => }
^
-catch-all.scala:4: warning: This catches all Throwables, which often has undesirable consequences.
-If intentional, use `case x : Throwable` to clear this warning.
+catch-all.scala:4: warning: This catches all Throwables. If this is really intended, use `case x : Throwable` to clear this warning.
try { "warn" } catch { case x => }
^
-catch-all.scala:6: warning: This catches all Throwables, which often has undesirable consequences.
-If intentional, use `case x : Throwable` to clear this warning.
+catch-all.scala:6: warning: This catches all Throwables. If this is really intended, use `case x : Throwable` to clear this warning.
try { "warn" } catch { case _: RuntimeException => ; case x => }
^
error: No warnings can be incurred under -Xfatal-warnings.
diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check
index 6f9dc7d127..f6bd703e1f 100644
--- a/test/files/neg/names-defaults-neg.check
+++ b/test/files/neg/names-defaults-neg.check
@@ -134,9 +134,17 @@ names-defaults-neg.scala:144: error: variable definition needs type because 'x'
names-defaults-neg.scala:147: error: variable definition needs type because 'x' is used as a named argument in its body.
object t6 { var x = t.f(x = 1) }
^
+names-defaults-neg.scala:147: warning: type-checking the invocation of method f checks if the named argument expression 'x = ...' is a valid assignment
+in the current scope. The resulting type inference error (see above) can be fixed by providing an explicit type in the local definition for x.
+ object t6 { var x = t.f(x = 1) }
+ ^
names-defaults-neg.scala:150: error: variable definition needs type because 'x' is used as a named argument in its body.
class t9 { var x = t.f(x = 1) }
^
+names-defaults-neg.scala:150: warning: type-checking the invocation of method f checks if the named argument expression 'x = ...' is a valid assignment
+in the current scope. The resulting type inference error (see above) can be fixed by providing an explicit type in the local definition for x.
+ class t9 { var x = t.f(x = 1) }
+ ^
names-defaults-neg.scala:164: error: variable definition needs type because 'x' is used as a named argument in its body.
def u3 { var x = u.f(x = 1) }
^
@@ -156,5 +164,5 @@ in the current scope. The resulting type inference error (see above) can be fixe
names-defaults-neg.scala:180: error: reference to x is ambiguous; it is both a method parameter and a variable in scope.
class u18 { var x: Int = u.f(x = 1) }
^
-two warnings found
+four warnings found
41 errors found
diff --git a/test/files/neg/nested-annotation.check b/test/files/neg/nested-annotation.check
new file mode 100644
index 0000000000..ca263943fe
--- /dev/null
+++ b/test/files/neg/nested-annotation.check
@@ -0,0 +1,10 @@
+nested-annotation.scala:3: warning: Implementation restriction: subclassing Classfile does not
+make your annotation visible at runtime. If that is what
+you want, you must write the annotation class in Java.
+class ComplexAnnotation(val value: Annotation) extends ClassfileAnnotation
+ ^
+nested-annotation.scala:8: error: nested classfile annotations must be defined in java; found: inline
+ @ComplexAnnotation(new inline) def bippy(): Int = 1
+ ^
+one warning found
+one error found
diff --git a/test/files/neg/nested-annotation.scala b/test/files/neg/nested-annotation.scala
new file mode 100644
index 0000000000..35c0cd3b75
--- /dev/null
+++ b/test/files/neg/nested-annotation.scala
@@ -0,0 +1,9 @@
+import annotation._
+
+class ComplexAnnotation(val value: Annotation) extends ClassfileAnnotation
+
+class A {
+ // It's hard to induce this error because @ComplexAnnotation(@inline) is a parse
+ // error so it never gets out of the parser, but:
+ @ComplexAnnotation(new inline) def bippy(): Int = 1
+}
diff --git a/test/files/neg/nonlocal-warning.check b/test/files/neg/nonlocal-warning.check
index 67b3b10095..5202df655a 100644
--- a/test/files/neg/nonlocal-warning.check
+++ b/test/files/neg/nonlocal-warning.check
@@ -1,5 +1,4 @@
-nonlocal-warning.scala:4: warning: This catches all Throwables, which often has undesirable consequences.
-If intentional, use `case x : Throwable` to clear this warning.
+nonlocal-warning.scala:4: warning: This catches all Throwables. If this is really intended, use `case x : Throwable` to clear this warning.
catch { case x => 11 }
^
nonlocal-warning.scala:2: warning: catch block may intercept non-local return from method foo
diff --git a/test/files/neg/t4851.check b/test/files/neg/t4851.check
index 0fd66b9efe..4f2919807e 100644
--- a/test/files/neg/t4851.check
+++ b/test/files/neg/t4851.check
@@ -40,6 +40,12 @@ S.scala:10: warning: Adapting argument list by inserting (): this is unlikely to
after adaptation: new J2((): Unit)
val z2 = new J2()
^
+S.scala:14: warning: Adapting argument list by creating a 3-tuple: this may not be what you want.
+ signature: Test.anyId(a: Any): Any
+ given arguments: 1, 2, 3
+ after adaptation: Test.anyId((1, 2, 3): (Int, Int, Int))
+ val w1 = anyId(1, 2 ,3)
+ ^
error: No warnings can be incurred under -Xfatal-warnings.
-7 warnings found
+8 warnings found
one error found
diff --git a/test/files/neg/t4851/S.scala b/test/files/neg/t4851/S.scala
index 1550892967..0a442ac7a9 100644
--- a/test/files/neg/t4851/S.scala
+++ b/test/files/neg/t4851/S.scala
@@ -10,6 +10,9 @@ object Test {
val z2 = new J2()
val z3 = new J2(())
+ def anyId(a: Any) = a
+ val w1 = anyId(1, 2 ,3)
+
def main(args: Array[String]): Unit = {
println(x1)
println(x2)
@@ -19,5 +22,7 @@ object Test {
println(z1)
println(z2)
println(z3)
+
+ println(w1)
}
}
diff --git a/test/files/neg/t5182.check b/test/files/neg/t5182.check
new file mode 100644
index 0000000000..3161f92680
--- /dev/null
+++ b/test/files/neg/t5182.check
@@ -0,0 +1,7 @@
+t5182.scala:2: error: unknown annotation argument name: qwe
+ @java.lang.Deprecated(qwe = "wer") def ok(q:Int) = 1
+ ^
+t5182.scala:3: error: classfile annotation arguments have to be supplied as named arguments
+ @java.lang.Deprecated("wer") def whereAmI(q:Int) = 1
+ ^
+two errors found
diff --git a/test/files/neg/t5182.flags b/test/files/neg/t5182.flags
new file mode 100644
index 0000000000..85d8eb2ba2
--- /dev/null
+++ b/test/files/neg/t5182.flags
@@ -0,0 +1 @@
+-Xfatal-warnings
diff --git a/test/files/neg/t5182.scala b/test/files/neg/t5182.scala
new file mode 100644
index 0000000000..0687e99efb
--- /dev/null
+++ b/test/files/neg/t5182.scala
@@ -0,0 +1,5 @@
+class test {
+ @java.lang.Deprecated(qwe = "wer") def ok(q:Int) = 1
+ @java.lang.Deprecated("wer") def whereAmI(q:Int) = 1
+ @java.lang.Deprecated() def bippy(q:Int) = 1
+}
diff --git a/test/files/neg/t5753/Impls$class.class b/test/files/neg/t5753/Impls$class.class
deleted file mode 100644
index 476329174e..0000000000
--- a/test/files/neg/t5753/Impls$class.class
+++ /dev/null
Binary files differ
diff --git a/test/files/neg/t5753/Impls.class b/test/files/neg/t5753/Impls.class
deleted file mode 100644
index dfcf89ed44..0000000000
--- a/test/files/neg/t5753/Impls.class
+++ /dev/null
Binary files differ
diff --git a/test/files/neg/t6040.check b/test/files/neg/t6040.check
index f6757f97e3..f91df0c46d 100644
--- a/test/files/neg/t6040.check
+++ b/test/files/neg/t6040.check
@@ -1,7 +1,9 @@
-error: extension of type scala.Dynamic needs to be enabled
+t6040.scala:1: error: extension of type scala.Dynamic needs to be enabled
by making the implicit value language.dynamics visible.
This can be achieved by adding the import clause 'import scala.language.dynamics'
or by setting the compiler option -language:dynamics.
See the Scala docs for value scala.language.dynamics for a discussion
why the feature needs to be explicitly enabled.
+class X extends Dynamic
+ ^
one error found
diff --git a/test/files/neg/t6083.check b/test/files/neg/t6083.check
new file mode 100644
index 0000000000..c9b5ba05d3
--- /dev/null
+++ b/test/files/neg/t6083.check
@@ -0,0 +1,10 @@
+t6083.scala:6: warning: Implementation restriction: subclassing Classfile does not
+make your annotation visible at runtime. If that is what
+you want, you must write the annotation class in Java.
+class annot(value: String) extends annotation.ClassfileAnnotation
+ ^
+t6083.scala:7: error: annotation argument needs to be a constant; found: conv.i2s(101)
+@annot(101) class C
+ ^
+one warning found
+one error found
diff --git a/test/files/neg/t6083.scala b/test/files/neg/t6083.scala
new file mode 100644
index 0000000000..1de18e6527
--- /dev/null
+++ b/test/files/neg/t6083.scala
@@ -0,0 +1,7 @@
+object conv {
+ implicit def i2s(i: Int): String = ""
+}
+import conv._
+
+class annot(value: String) extends annotation.ClassfileAnnotation
+@annot(101) class C
diff --git a/test/files/neg/t6231.check b/test/files/neg/t6231.check
new file mode 100644
index 0000000000..b27961d393
--- /dev/null
+++ b/test/files/neg/t6231.check
@@ -0,0 +1,6 @@
+t6231.scala:4: error: Implementation restriction: local trait Bug$X$1 is unable to automatically capture the
+free variable value ev$1 on behalf of anonymous class anonfun$qux$1. You can manually assign it to a val inside the trait,
+and refer that that val in anonymous class anonfun$qux$1. For more details, see SI-6231.
+ def qux = { () => ev }
+ ^
+one error found
diff --git a/test/files/neg/t6231.scala b/test/files/neg/t6231.scala
new file mode 100644
index 0000000000..1e5b4e0e1a
--- /dev/null
+++ b/test/files/neg/t6231.scala
@@ -0,0 +1,15 @@
+object Bug {
+ def bar(ev: Any) = {
+ trait X {
+ def qux = { () => ev }
+ }
+ new X {}.qux()
+
+ // workaround
+ trait Y {
+ val ev2 = ev // manually capture `ev` so that `ev2` is added to the trait interface.
+ def qux = { () => ev2 }
+ }
+ }
+}
+
diff --git a/test/files/neg/t6666.check b/test/files/neg/t6666.check
new file mode 100644
index 0000000000..d0378173ea
--- /dev/null
+++ b/test/files/neg/t6666.check
@@ -0,0 +1,40 @@
+t6666.scala:23: error: Implementation restriction: access of method x$2 in object O1 from anonymous class 2, would require illegal premature access to object O1
+ F.byname(x)
+ ^
+t6666.scala:30: error: Implementation restriction: access of value x$3 in object O2 from anonymous class 3, would require illegal premature access to object O2
+ F.byname(x)
+ ^
+t6666.scala:37: error: Implementation restriction: access of method x$4 in object O3 from anonymous class 4, would require illegal premature access to object O3
+ F.hof(() => x)
+ ^
+t6666.scala:50: error: Implementation restriction: access of method x$6 in class C1 from anonymous class 7, would require illegal premature access to the unconstructed `this` of class C1
+ F.byname(x)
+ ^
+t6666.scala:54: error: Implementation restriction: access of value x$7 in class C2 from anonymous class 8, would require illegal premature access to the unconstructed `this` of class C2
+ F.byname(x)
+ ^
+t6666.scala:58: error: Implementation restriction: access of method x$8 in class C3 from anonymous class 9, would require illegal premature access to the unconstructed `this` of class C3
+ F.hof(() => x)
+ ^
+t6666.scala:62: error: Implementation restriction: access of method x$9 in class C4 from object Nested$5, would require illegal premature access to the unconstructed `this` of class C4
+ object Nested { def xx = x}
+ ^
+t6666.scala:68: error: Implementation restriction: access of method x$10 in class C5 from object Nested$6, would require illegal premature access to the unconstructed `this` of class C5
+ object Nested { def xx = x}
+ ^
+t6666.scala:83: error: Implementation restriction: access of method x$12 in class C11 from anonymous class 12, would require illegal premature access to the unconstructed `this` of class C11
+ F.byname(x)
+ ^
+t6666.scala:102: error: Implementation restriction: access of method x$13 in class C13 from anonymous class 13, would require illegal premature access to the unconstructed `this` of class C13
+ F.hof(() => x)
+ ^
+t6666.scala:111: error: Implementation restriction: access of method x$14 in class C14 from object Nested$7, would require illegal premature access to the unconstructed `this` of class C14
+ object Nested { def xx = x}
+ ^
+t6666.scala:122: error: Implementation restriction: access of method x$15 in class C15 from object Nested$8, would require illegal premature access to the unconstructed `this` of class C15
+ object Nested { def xx = x}
+ ^
+t6666.scala:131: error: Implementation restriction: access of method foo$1 in class COuter from class CInner$1, would require illegal premature access to the unconstructed `this` of class COuter
+ class CInner extends C({foo})
+ ^
+13 errors found
diff --git a/test/files/neg/t6666.scala b/test/files/neg/t6666.scala
new file mode 100644
index 0000000000..d37ffaf141
--- /dev/null
+++ b/test/files/neg/t6666.scala
@@ -0,0 +1,132 @@
+class C(a: Any)
+object F {
+ def byname(a: => Any) = println(a)
+ def hof(a: () => Any) = println(a())
+}
+
+class COkay extends C(0) {
+ def this(a: Any) {
+ this()
+ def x = "".toString
+ F.byname(x)
+ }
+}
+
+//
+// The thunk's apply method accesses the MODULE$
+// field before it is set.
+//
+// 0: getstatic #23; //Field O1$.MODULE$:LO1$;
+// 3: invokevirtual #26; //Method O1$.O1$$x$1:()Ljava/lang/String;
+object O1 extends C({
+ def x = "".toString
+ F.byname(x)
+})
+
+// java.lang.NullPointerException
+// at O2$$anonfun$$init$$1.apply(<console>:11)
+object O2 extends C({
+ lazy val x = "".toString
+ F.byname(x)
+})
+
+// java.lang.NullPointerException
+// at O3$$anonfun$$init$$1.apply(<console>:11)
+object O3 extends C({
+ def x = "".toString
+ F.hof(() => x)
+})
+
+// Okay, the nested classes don't get an outer pointer passed,
+// just an extra param for `x: String`.
+object O6 extends C({
+ val x = "".toString
+ F.byname(x); F.hof(() => x); (new { val xx = x }.xx)
+})
+
+
+class C1 extends C({
+ def x = "".toString
+ F.byname(x)
+})
+class C2 extends C({
+ lazy val x = "".toString
+ F.byname(x)
+})
+class C3 extends C({
+ def x = "".toString
+ F.hof(() => x)
+})
+class C4 extends C({
+ def x = "".toString
+ object Nested { def xx = x}
+ Nested.xx
+})
+class C5 extends C({
+ def x = "".toString
+ val y = {
+ object Nested { def xx = x}
+ Nested.xx
+ }
+})
+
+// okay, for same reason as O6
+class C6 extends C({
+ val x = "".toString
+ F.byname(x); F.hof(() => x); (new { val xx = x }.xx)
+})
+
+class C11(a: Any) {
+ def this() = {
+ this({
+ def x = "".toString
+ F.byname(x)
+ })
+ }
+}
+
+// Crashes earlier in lazyVals.
+// class C12(a: Any) {
+// def this() = {
+// this({
+// lazy val x = "".toString
+// F.byname(x)
+// })
+// }
+// }
+
+class C13(a: Any) {
+ def this() = {
+ this({
+ def x = "".toString
+ F.hof(() => x)
+ })
+ }
+}
+
+class C14(a: Any) {
+ def this() = {
+ this({
+ def x = "".toString
+ object Nested { def xx = x}
+ Nested.xx
+ })
+ }
+}
+
+class C15(a: Any) {
+ def this() = {
+ this({
+ def x = "".toString
+ val y = {
+ object Nested { def xx = x}
+ Nested.xx
+ }
+ })
+ }
+}
+
+class COuter extends C({
+ def foo = 0
+ class CInner extends C({foo})
+}) \ No newline at end of file
diff --git a/test/files/neg/t6902.check b/test/files/neg/t6902.check
new file mode 100644
index 0000000000..ed0ed75303
--- /dev/null
+++ b/test/files/neg/t6902.check
@@ -0,0 +1,12 @@
+t6902.scala:4: warning: unreachable code
+ case Some(b) => 3 // no warning was emitted
+ ^
+t6902.scala:9: warning: unreachable code
+ case Some(b) => 3 // no warning was emitted
+ ^
+t6902.scala:21: warning: unreachable code
+ case 1 => 3 // crash
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+three warnings found
+one error found
diff --git a/test/files/neg/t6902.flags b/test/files/neg/t6902.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/neg/t6902.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/t6902.scala b/test/files/neg/t6902.scala
new file mode 100644
index 0000000000..ce5ff8b6fb
--- /dev/null
+++ b/test/files/neg/t6902.scala
@@ -0,0 +1,23 @@
+object Test {
+ Some(Some(1)) collect {
+ case Some(a) => 2
+ case Some(b) => 3 // no warning was emitted
+ }
+
+ (Some(1): @ unchecked) match {
+ case Some(a) => 2
+ case Some(b) => 3 // no warning was emitted
+ }
+
+ // A variation of SI-6011, which eluded the fix
+ // in 2.10.0.
+ //
+ // duplicate keys in SWITCH, can't pick arbitrarily one of them to evict, see SI-6011.
+ // at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:50)
+ // at scala.tools.nsc.Global.abort(Global.scala:249)
+ // at scala.tools.nsc.backend.jvm.GenASM$JPlainBuilder$jcode$.emitSWITCH(GenASM.scala:1850)
+ ((1: Byte): @unchecked @annotation.switch) match {
+ case 1 => 2
+ case 1 => 3 // crash
+ }
+}
diff --git a/test/files/neg/t6952.check b/test/files/neg/t6952.check
new file mode 100644
index 0000000000..f1e1881404
--- /dev/null
+++ b/test/files/neg/t6952.check
@@ -0,0 +1,13 @@
+t6952.scala:2: error: extension of type scala.Dynamic needs to be enabled
+by making the implicit value language.dynamics visible.
+This can be achieved by adding the import clause 'import scala.language.dynamics'
+or by setting the compiler option -language:dynamics.
+See the Scala docs for value scala.language.dynamics for a discussion
+why the feature needs to be explicitly enabled.
+trait B extends Dynamic
+ ^
+t6952.scala:3: error: extension of type scala.Dynamic needs to be enabled
+by making the implicit value language.dynamics visible.
+trait C extends A with Dynamic
+ ^
+two errors found
diff --git a/test/files/neg/t6952.scala b/test/files/neg/t6952.scala
new file mode 100644
index 0000000000..257ea3be68
--- /dev/null
+++ b/test/files/neg/t6952.scala
@@ -0,0 +1,4 @@
+trait A
+trait B extends Dynamic
+trait C extends A with Dynamic
+trait D extends B
diff --git a/test/files/pos/annotations2.scala b/test/files/pos/annotations2.scala
new file mode 100644
index 0000000000..3bce7f8ac4
--- /dev/null
+++ b/test/files/pos/annotations2.scala
@@ -0,0 +1,31 @@
+
+class B[T](x: (T, T)) {
+ def this(xx: (T, Any, Any)) = this((xx._1, xx._1))
+}
+class BAnn[T](x: (T, T)) extends scala.annotation.StaticAnnotation {
+ def this(xx: (T, Any, Any)) = this((xx._1, xx._1))
+}
+class CAnn[T](x: (T, T)) extends scala.annotation.StaticAnnotation {
+ def this(xx: Class[T]) = this((xx.newInstance(), xx.newInstance()))
+}
+
+class A1 {
+ val b1 = new B((1, 2, 3))
+ val b2 = new B((1, 2))
+ val b3 = new B[Int]((1, 2, 3))
+ val b4 = new B[Int]((1, 2))
+}
+
+class A2 {
+ @BAnn((1, 2, 3)) val b1 = null
+ @BAnn((1, 2)) val b2 = null
+ @BAnn[Int]((1, 2, 3)) val b3 = null
+ @BAnn[Int]((1, 2)) val b4 = null
+}
+
+class A3 {
+ @CAnn(classOf[Int]) val b1 = null
+ @CAnn((1, 2)) val b2 = null
+ @CAnn[Int](classOf[Int]) val b3 = null
+ @CAnn[Int]((1, 2)) val b4 = null
+}
diff --git a/test/files/pos/kinds.scala b/test/files/pos/kinds.scala
new file mode 100644
index 0000000000..6d6da0c8b6
--- /dev/null
+++ b/test/files/pos/kinds.scala
@@ -0,0 +1,13 @@
+trait IllKind1 {
+ def g(s: String): String = s
+ def f: String = ???
+ def f[C](c: C): String = g(f)
+}
+
+trait IllKind2 {
+ def b1: Char = ???
+ def b2: Byte = ???
+
+ def f1 = "abc" contains b1
+ def f2 = "abc" contains b2
+}
diff --git a/test/pending/pos/t4859.scala b/test/files/pos/t4859.scala
index ec5abd966d..284a39b7ab 100644
--- a/test/pending/pos/t4859.scala
+++ b/test/files/pos/t4859.scala
@@ -1,5 +1,7 @@
object O {
+ // error: C is not a legal prefix for a constructor
C().CC()
+ // but this works.
D().DD()
}
diff --git a/test/files/pos/t6942.flags b/test/files/pos/t6942.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/pos/t6942.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t6942/Bar.java b/test/files/pos/t6942/Bar.java
new file mode 100644
index 0000000000..592f62efb4
--- /dev/null
+++ b/test/files/pos/t6942/Bar.java
@@ -0,0 +1,235 @@
+package foo;
+
+public enum Bar {
+ ANGUILLA /*("US")*/,
+ ANTIGUA_AND_BARBUDA /*("US")*/,
+ ARGENTINA /*("US")*/,
+ ARUBA /*("US")*/,
+ BAHAMAS /*("US")*/,
+ BARBADOS /*("US")*/,
+ BELIZE /*("US")*/,
+ BERMUDA /*("US")*/,
+ BOLIVIA /*("US")*/,
+ BRAZIL /*("US")*/,
+ BRITISH_VIRGIN_ISLANDS /*("US")*/,
+ CANADA /*("US")*/,
+ CAYMAN_ISLANDS /*("US")*/,
+ CHILE /*("US")*/,
+ CHRISTMAS_ISLANDS /*("US")*/,
+ COCOS /*("US")*/,
+ COLOMBIA /*("US")*/,
+ COSTA_RICA /*("US")*/,
+ CUBA /*("US")*/,
+ DOMINICA /*("US")*/,
+ DOMINICAN_REPUBLIC /*("US")*/,
+ ECUADOR /*("US")*/,
+ EL_SALVADOR /*("US")*/,
+ FALKLAND_ISLANDS /*("US")*/,
+ GRENADA /*("US")*/,
+ GUADALOUPE /*("US")*/,
+ GUATEMALA /*("US")*/,
+ HAITI /*("US")*/,
+ HONDURAS /*("US")*/,
+ NETHERLANDS_ANTILLES /*("US")*/,
+ NICARAGUA /*("US")*/,
+ PANAMA /*("US")*/,
+ PARAGUAY /*("US")*/,
+ PERU /*("US")*/,
+ PUERTO_RICO /*("US")*/,
+ JAMAICA /*("US")*/,
+ MARTINIQUE /*("US")*/,
+ MEXICO /*("US")*/,
+ MONTSERRAT /*("US")*/,
+ ST_KITTS /*("US")*/,
+ ST_LUCIA /*("US")*/,
+ ST_VINCENT /*("US")*/,
+ SUPRA_NATIONAL /*("US")*/,
+ TRINIDAD /*("US")*/,
+ TURKS_AND_CAICOS /*("US")*/,
+ UNITED_STATES /*("US")*/,
+ URUGUAY /*("US")*/,
+ VENEZUELA /*("US")*/,
+ VIRGIN_ISLANDS /*("US")*/,
+
+ AUSTRALIA /*("AP")*/,
+ BANGLADESH /*("AP")*/,
+ BHUTAN /*("AP")*/,
+ CAMBODIA /*("AP")*/,
+ CHINA /*("AP")*/,
+ COOK_ISLANDS /*("AP")*/,
+ EAST_TIMOR /*("AP")*/,
+ FIJI /*("AP")*/,
+ GUAM /*("AP")*/,
+ HONG_KONG /*("AP")*/,
+ INDIA /*("AP")*/,
+ INDONESIA /*("AP")*/,
+ JAPAN /*("AP")*/,
+ KIRIBATI /*("AP")*/,
+ LAOS /*("AP")*/,
+ MACAU /*("AP")*/,
+ MALAYSIA /*("AP")*/,
+ MICRONESIA /*("AP")*/,
+ MONGOLIA /*("AP")*/,
+ MYANMAR /*("AP")*/,
+ NEPAL /*("AP")*/,
+ NEW_CALEDONIA /*("AP")*/,
+ NEW_ZEALAND /*("AP")*/,
+ NORFOLK_ISLAND /*("AP")*/,
+ NORTH_KOREA /*("AP")*/,
+ PAKISTAN /*("AP")*/,
+ PALAU /*("AP")*/,
+ PAPUA_NEW_GUINEA /*("AP")*/,
+ PHILIPPINES /*("AP")*/,
+ PITCAIRN_ISLANDS /*("AP")*/,
+ SAMOA /*("AP")*/,
+ WEST_SAMOA /*("AP")*/,
+ SINGAPORE /*("AP")*/,
+ SOUTH_KOREA /*("AP")*/,
+ SRI_LANKA /*("AP")*/,
+ TAIWAN /*("AP")*/,
+ THAILAND /*("AP")*/,
+ TOKELAU /*("AP")*/,
+ TONGA /*("AP")*/,
+ TUVALU /*("AP")*/,
+ VANUATU /*("AP")*/,
+ VIETNAM /*("AP")*/,
+
+ AFGHANISTAN /*("EU")*/,
+ ALBANIA /*("EU")*/,
+ ALGERIA /*("EU")*/,
+ ANDORRA /*("EU")*/,
+ ANGOLA /*("EU")*/,
+ ARMENIA /*("EU")*/,
+ AUSTRIA /*("EU")*/,
+ AZERBAIJAN /*("EU")*/,
+ BAHRAIN /*("EU")*/,
+ BELARUS /*("EU")*/,
+ BELGIUM /*("EU")*/,
+ BENIN /*("EU")*/,
+ BOSNIA_AND_HERZEGOVINA /*("EU")*/,
+ BOTSWANA /*("EU")*/,
+ BOUVET_ISLAND /*("EU")*/,
+ BRUNEI /*("EU")*/,
+ BULGARIA /*("EU")*/,
+ BURKINA_FASO /*("EU")*/,
+ BURUNDI /*("EU")*/,
+ CAMEROON /*("EU")*/,
+ CAPE_VERDE /*("EU")*/,
+ CHAD /*("EU")*/,
+ COMOROS /*("EU")*/,
+ CONGO /*("EU")*/,
+ CROATIA /*("EU")*/,
+ CYPRUS /*("EU")*/,
+ CZECH_REPUBLIC /*("EU")*/,
+ DR_CONGO /*("EU")*/,
+ DENMARK /*("EU")*/,
+ DJIBOUTI /*("EU")*/,
+ EGYPT /*("EU")*/,
+ EQUATORIAL_GUINEA /*("EU")*/,
+ ERITREA /*("EU")*/,
+ ESTONIA /*("EU")*/,
+ ETHIOPIA /*("EU")*/,
+ FAEROE_ISLANDS /*("EU")*/,
+ FINLAND /*("EU")*/,
+ FRANCE /*("EU")*/,
+ FRENCH_GUIANA /*("EU")*/,
+ GABON /*("EU")*/,
+ GAMBIA /*("EU")*/,
+ GEORGIA /*("EU")*/,
+ GERMANY /*("EU")*/,
+ GHANA /*("EU")*/,
+ GIBRALTAR /*("EU")*/,
+ GREAT_BRITAIN /*("EU")*/,
+ GREECE /*("EU")*/,
+ GREENLAND /*("EU")*/,
+ GUINEA /*("EU")*/,
+ GUINEA_BISSAU /*("EU")*/,
+ GUYANA /*("EU")*/,
+ HUNGARY /*("EU")*/,
+ ICELAND /*("EU")*/,
+ IRAN /*("EU")*/,
+ IRAQ /*("EU")*/,
+ IRELAND /*("EU")*/,
+ ISLE_OF_MAN /*("EU")*/,
+ ISRAEL /*("EU")*/,
+ ITALY /*("EU")*/,
+ IVORY_COAST /*("EU")*/,
+ JERSEY /*("EU")*/,
+ JORDAN /*("EU")*/,
+ KAZAKHSTAN /*("EU")*/,
+ KENYA /*("EU")*/,
+ KUWAIT /*("EU")*/,
+ KYRGYZSTAN /*("EU")*/,
+ LATVIA /*("EU")*/,
+ LEBANON /*("EU")*/,
+ LESOTHO /*("EU")*/,
+ LIBERIA /*("EU")*/,
+ LIBYA /*("EU")*/,
+ LIECHTENSTEIN /*("EU")*/,
+ LITHUANIA /*("EU")*/,
+ LUXEMBOURG /*("EU")*/,
+ MACEDONIA /*("EU")*/,
+ MADAGASCAR /*("EU")*/,
+ MALAWI /*("EU")*/,
+ MALDIVES /*("EU")*/,
+ MALI /*("EU")*/,
+ MALTA /*("EU")*/,
+ MARSHALL_ISLAND /*("EU")*/,
+ MAURITANIA /*("EU")*/,
+ MAURITIUS /*("EU")*/,
+ MAYOTTE /*("EU")*/,
+ MOLDOVA /*("EU")*/,
+ MONACO /*("EU")*/,
+ MOROCCO /*("EU")*/,
+ MOZAMBIQUE /*("EU")*/,
+ NAMIBIA /*("EU")*/,
+ NETHERLANDS /*("EU")*/,
+ NIGER_REPUBLIC /*("EU")*/,
+ NIGERIA /*("EU")*/,
+ NORWAY /*("EU")*/,
+ OMAN /*("EU")*/,
+ PALESTINE /*("EU")*/,
+ POLAND /*("EU")*/,
+ PORTUGAL /*("EU")*/,
+ QATAR /*("EU")*/,
+ REUNION /*("EU")*/,
+ ROMANIA /*("EU")*/,
+ RUSSIA /*("EU")*/,
+ RWANDA /*("EU")*/,
+ SAN_MARINO /*("EU")*/,
+ SAO_TOME /*("EU")*/,
+ SAUDI_ARABIA /*("EU")*/,
+ SENEGAL /*("EU")*/,
+ SERBIA /*("EU")*/,
+ SEYCHELLES /*("EU")*/,
+ SEIRRA_LEONE /*("EU")*/,
+ SLOVAKIA /*("EU")*/,
+ SLOVENIA /*("EU")*/,
+ SOMALIA /*("EU")*/,
+ SOUTH_AFRICA /*("EU")*/,
+ SPAIN /*("EU")*/,
+ ST_HELENA /*("EU")*/,
+ SUDAN /*("EU")*/,
+ SURINAME /*("EU")*/,
+ SVALBARD /*("EU")*/,
+ SWAZILAND /*("EU")*/,
+ SWEDEN /*("EU")*/,
+ SWITZERLAND /*("EU")*/,
+ SYRIA /*("EU")*/,
+ TAJIKSTAN /*("EU")*/,
+ TANZANIA /*("EU")*/,
+ TOGO /*("EU")*/,
+ TUNISIA /*("EU")*/,
+ TURKEY /*("EU")*/,
+ TURKMENISTAN /*("EU")*/,
+ UAE /*("EU")*/,
+ UGANDA /*("EU")*/,
+ UKRAINE /*("EU")*/,
+ UZBEKISTAN /*("EU")*/,
+ VATICAN_CITY /*("EU")*/,
+ WESTERN_SAHARA /*("EU")*/,
+ YEMEN /*("EU")*/,
+ ZAMBIA /*("EU")*/,
+ ZIMBABWE /*("EU")*/;
+
+} \ No newline at end of file
diff --git a/test/files/pos/t6942/t6942.scala b/test/files/pos/t6942/t6942.scala
new file mode 100644
index 0000000000..77963d2634
--- /dev/null
+++ b/test/files/pos/t6942/t6942.scala
@@ -0,0 +1,64 @@
+// not a peep out of the pattern matcher's unreachability analysis
+// its budget should suffice for these simple matches (they do have a large search space)
+class Test {
+ import foo.Bar // a large enum
+ def exhaustUnreachabilitysStack_ENUM_STYLE = (null: Bar) match {
+ case Bar.BULGARIA =>
+ case _ =>
+ }
+
+ // lots of strings
+ def exhaustUnreachabilitysStack_StringStyle = "foo" match {
+ case "a" =>
+ case "b" =>
+ case "c" =>
+ case "d" =>
+ case "e" =>
+ case "f" =>
+ case "aa" =>
+ case "ba" =>
+ case "ca" =>
+ case "da" =>
+ case "ea" =>
+ case "f1a" =>
+ case "a1a" =>
+ case "b1a" =>
+ case "c1a" =>
+ case "d1a" =>
+ case "e1a" =>
+ case "f1a2" =>
+ case "f1a0" =>
+ case "a1a2" =>
+ case "b1a2" =>
+ case "c1a2" =>
+ case "d1a2" =>
+ case "e1a2" =>
+ case "f1a3" =>
+ case "_a" =>
+ case "_b" =>
+ case "_c" =>
+ case "_d" =>
+ case "_e" =>
+ case "_f" =>
+ case "_aa" =>
+ case "_ba" =>
+ case "_ca" =>
+ case "_da" =>
+ case "_ea" =>
+ case "_f1a" =>
+ case "_a1a" =>
+ case "_b1a" =>
+ case "_c1a" =>
+ case "_d1a" =>
+ case "_e1a" =>
+ case "_f1a0" =>
+ case "_f1a2" =>
+ case "_a1a2" =>
+ case "_b1a2" =>
+ case "_c1a2" =>
+ case "_d1a2" =>
+ case "_e1a2" =>
+ case "_f1a3" =>
+ case _ =>
+ }
+}
diff --git a/test/files/pos/t6976/Exts_1.scala b/test/files/pos/t6976/Exts_1.scala
new file mode 100644
index 0000000000..9b3a69edd9
--- /dev/null
+++ b/test/files/pos/t6976/Exts_1.scala
@@ -0,0 +1,10 @@
+object Exts {
+ implicit class AnyExts[T](val o: T) extends AnyVal {
+ def moo = "moo!"
+ }
+}
+
+trait Exts {
+ import language.implicitConversions
+ implicit def AnyExts[T](o: T) = Exts.AnyExts(o)
+}
diff --git a/test/files/pos/t6976/ImplicitBug_1.scala b/test/files/pos/t6976/ImplicitBug_1.scala
new file mode 100644
index 0000000000..c9031bab2e
--- /dev/null
+++ b/test/files/pos/t6976/ImplicitBug_1.scala
@@ -0,0 +1,27 @@
+// This one is weird and nasty. Not sure if this is scalac or sbt
+// (tried with 0.12 & 0.12.2-RC2) bug.
+//
+// A level of indirection is required to trigger this bug.
+// Exts seems to need to be defined in separate file.
+//
+// Steps to reproduce:
+// 1. sbt clean
+// 2. sbt run (it works)
+// 3. Comment A & uncomment B.
+// 4. sbt run (it fails)
+// 5. Switch it back & sbt run. It still fails.
+//
+// In this project sbt clean helps. However in a large project where this
+// bug was found compiler crashed even after doing sbt clean. The only
+// way to work around this was to reference Exts object explicitly (C) in
+// the source file using its implicit classes.
+
+// Lets suppose this is a mega-trait combining all sorts of helper
+// functionality.
+trait Support extends Exts
+
+object ImplicitsBug extends App with Support { // A
+// object ImplicitsBug extends App with Exts { // B
+ //Exts // C) this reference helped in the large project.
+ println(3.moo)
+}
diff --git a/test/files/pos/t6976/ImplicitBug_2.scala b/test/files/pos/t6976/ImplicitBug_2.scala
new file mode 100644
index 0000000000..2fea5e2993
--- /dev/null
+++ b/test/files/pos/t6976/ImplicitBug_2.scala
@@ -0,0 +1,7 @@
+trait Support extends Exts
+
+// object ImplicitsBug extends App with Support { // A
+object ImplicitsBug extends App with Exts { // B
+ //Exts // C) this reference helped in the large project.
+ println(3.moo)
+}
diff --git a/test/files/pos/t6994.flags b/test/files/pos/t6994.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/pos/t6994.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t6994.scala b/test/files/pos/t6994.scala
new file mode 100644
index 0000000000..d707196423
--- /dev/null
+++ b/test/files/pos/t6994.scala
@@ -0,0 +1,8 @@
+object Test {
+ object NF {
+ def unapply(t: Throwable): Option[Throwable] = None
+ }
+ val x = (try { None } catch { case NF(ex) => None }) getOrElse 0
+ // Was emitting a spurious warning post typer:
+ // "This catches all Throwables. If this is really intended, use `case ex6 : Throwable` to clear this warning."
+}
diff --git a/test/files/pos/t7011.flags b/test/files/pos/t7011.flags
new file mode 100644
index 0000000000..a4c161553e
--- /dev/null
+++ b/test/files/pos/t7011.flags
@@ -0,0 +1 @@
+-Ydebug -Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t7011.scala b/test/files/pos/t7011.scala
new file mode 100644
index 0000000000..539f662bc0
--- /dev/null
+++ b/test/files/pos/t7011.scala
@@ -0,0 +1,7 @@
+object bar {
+ def foo {
+ lazy val x = 42
+
+ {()=>x}
+ }
+} \ No newline at end of file
diff --git a/test/files/run/existentials-in-compiler.check b/test/files/run/existentials-in-compiler.check
index 0d7a9298b4..b0d852865d 100644
--- a/test/files/run/existentials-in-compiler.check
+++ b/test/files/run/existentials-in-compiler.check
@@ -8,22 +8,22 @@ abstract trait BippyLike[A <: AnyRef, B <: List[A], This <: extest.BippyLike[A,B
extest.BippyLike[A,B,This] forSome { A <: AnyRef; B <: List[A]; This <: extest.BippyLike[A,B,This] with extest.Bippy[A,B] }
abstract trait Contra[-A >: AnyRef, -B] extends AnyRef
- extest.Contra[_ >: AnyRef, _]
+ extest.Contra[AnyRef, _]
abstract trait ContraLike[-A >: AnyRef, -B >: List[A]] extends AnyRef
extest.ContraLike[A,B] forSome { -A >: AnyRef; -B >: List[A] }
abstract trait Cov01[+A <: AnyRef, +B] extends AnyRef
- extest.Cov01[_ <: AnyRef, _]
+ extest.Cov01[AnyRef,Any]
abstract trait Cov02[+A <: AnyRef, B] extends AnyRef
- extest.Cov02[_ <: AnyRef, _]
+ extest.Cov02[AnyRef, _]
abstract trait Cov03[+A <: AnyRef, -B] extends AnyRef
- extest.Cov03[_ <: AnyRef, _]
+ extest.Cov03[AnyRef, _]
abstract trait Cov04[A <: AnyRef, +B] extends AnyRef
- extest.Cov04[_ <: AnyRef, _]
+ extest.Cov04[_ <: AnyRef, Any]
abstract trait Cov05[A <: AnyRef, B] extends AnyRef
extest.Cov05[_ <: AnyRef, _]
@@ -32,7 +32,7 @@ abstract trait Cov06[A <: AnyRef, -B] extends AnyRef
extest.Cov06[_ <: AnyRef, _]
abstract trait Cov07[-A <: AnyRef, +B] extends AnyRef
- extest.Cov07[_ <: AnyRef, _]
+ extest.Cov07[_ <: AnyRef, Any]
abstract trait Cov08[-A <: AnyRef, B] extends AnyRef
extest.Cov08[_ <: AnyRef, _]
@@ -41,16 +41,16 @@ abstract trait Cov09[-A <: AnyRef, -B] extends AnyRef
extest.Cov09[_ <: AnyRef, _]
abstract trait Cov11[+A <: AnyRef, +B <: List[_]] extends AnyRef
- extest.Cov11[_ <: AnyRef, _ <: List[_]]
+ extest.Cov11[AnyRef,List[_]]
abstract trait Cov12[+A <: AnyRef, B <: List[_]] extends AnyRef
- extest.Cov12[_ <: AnyRef, _ <: List[_]]
+ extest.Cov12[AnyRef, _ <: List[_]]
abstract trait Cov13[+A <: AnyRef, -B <: List[_]] extends AnyRef
- extest.Cov13[_ <: AnyRef, _ <: List[_]]
+ extest.Cov13[AnyRef, _ <: List[_]]
abstract trait Cov14[A <: AnyRef, +B <: List[_]] extends AnyRef
- extest.Cov14[_ <: AnyRef, _ <: List[_]]
+ extest.Cov14[_ <: AnyRef, List[_]]
abstract trait Cov15[A <: AnyRef, B <: List[_]] extends AnyRef
extest.Cov15[_ <: AnyRef, _ <: List[_]]
@@ -59,7 +59,7 @@ abstract trait Cov16[A <: AnyRef, -B <: List[_]] extends AnyRef
extest.Cov16[_ <: AnyRef, _ <: List[_]]
abstract trait Cov17[-A <: AnyRef, +B <: List[_]] extends AnyRef
- extest.Cov17[_ <: AnyRef, _ <: List[_]]
+ extest.Cov17[_ <: AnyRef, List[_]]
abstract trait Cov18[-A <: AnyRef, B <: List[_]] extends AnyRef
extest.Cov18[_ <: AnyRef, _ <: List[_]]
@@ -68,16 +68,16 @@ abstract trait Cov19[-A <: AnyRef, -B <: List[_]] extends AnyRef
extest.Cov19[_ <: AnyRef, _ <: List[_]]
abstract trait Cov21[+A, +B] extends AnyRef
- extest.Cov21[_, _]
+ extest.Cov21[Any,Any]
abstract trait Cov22[+A, B] extends AnyRef
- extest.Cov22[_, _]
+ extest.Cov22[Any, _]
abstract trait Cov23[+A, -B] extends AnyRef
- extest.Cov23[_, _]
+ extest.Cov23[Any, _]
abstract trait Cov24[A, +B] extends AnyRef
- extest.Cov24[_, _]
+ extest.Cov24[_, Any]
abstract trait Cov25[A, B] extends AnyRef
extest.Cov25[_, _]
@@ -86,7 +86,7 @@ abstract trait Cov26[A, -B] extends AnyRef
extest.Cov26[_, _]
abstract trait Cov27[-A, +B] extends AnyRef
- extest.Cov27[_, _]
+ extest.Cov27[_, Any]
abstract trait Cov28[-A, B] extends AnyRef
extest.Cov28[_, _]
@@ -122,16 +122,16 @@ abstract trait Cov39[-A, -B, C <: Tuple2[_, _]] extends AnyRef
extest.Cov39[_, _, _ <: Tuple2[_, _]]
abstract trait Cov41[+A >: Null, +B] extends AnyRef
- extest.Cov41[_ >: Null, _]
+ extest.Cov41[Any,Any]
abstract trait Cov42[+A >: Null, B] extends AnyRef
- extest.Cov42[_ >: Null, _]
+ extest.Cov42[Any, _]
abstract trait Cov43[+A >: Null, -B] extends AnyRef
- extest.Cov43[_ >: Null, _]
+ extest.Cov43[Any, _]
abstract trait Cov44[A >: Null, +B] extends AnyRef
- extest.Cov44[_ >: Null, _]
+ extest.Cov44[_ >: Null, Any]
abstract trait Cov45[A >: Null, B] extends AnyRef
extest.Cov45[_ >: Null, _]
@@ -140,7 +140,7 @@ abstract trait Cov46[A >: Null, -B] extends AnyRef
extest.Cov46[_ >: Null, _]
abstract trait Cov47[-A >: Null, +B] extends AnyRef
- extest.Cov47[_ >: Null, _]
+ extest.Cov47[_ >: Null, Any]
abstract trait Cov48[-A >: Null, B] extends AnyRef
extest.Cov48[_ >: Null, _]
@@ -149,7 +149,7 @@ abstract trait Cov49[-A >: Null, -B] extends AnyRef
extest.Cov49[_ >: Null, _]
abstract trait Covariant[+A <: AnyRef, +B] extends AnyRef
- extest.Covariant[_ <: AnyRef, _]
+ extest.Covariant[AnyRef,Any]
abstract trait CovariantLike[+A <: AnyRef, +B <: List[A], +This <: extest.CovariantLike[A,B,This] with extest.Covariant[A,B]] extends AnyRef
extest.CovariantLike[A,B,This] forSome { +A <: AnyRef; +B <: List[A]; +This <: extest.CovariantLike[A,B,This] with extest.Covariant[A,B] }
diff --git a/test/files/run/reify_magicsymbols.check b/test/files/run/reify_magicsymbols.check
index e2aa46a364..c9d892d793 100644
--- a/test/files/run/reify_magicsymbols.check
+++ b/test/files/run/reify_magicsymbols.check
@@ -10,4 +10,4 @@ List[Null]
List[Nothing]
AnyRef{def foo(x: Int): Int}
Int* => Unit
-=> Int => Unit
+(=> Int) => Unit
diff --git a/test/files/run/t2577.check b/test/files/run/t2577.check
new file mode 100644
index 0000000000..4a584e4989
--- /dev/null
+++ b/test/files/run/t2577.check
@@ -0,0 +1 @@
+Nothing
diff --git a/test/files/run/t2577.scala b/test/files/run/t2577.scala
new file mode 100644
index 0000000000..6d836a3996
--- /dev/null
+++ b/test/files/run/t2577.scala
@@ -0,0 +1,17 @@
+case class annot[T]() extends scala.annotation.StaticAnnotation
+
+// type inference should infer @annot[Nothing] instead of @annot[T]
+// note the T is not in scope here!
+class Foo[@annot U]
+
+object Test {
+ import scala.reflect.runtime.universe._
+ val x = new Foo
+
+ def main(args: Array[String]): Unit = {
+ val targ = typeOf[x.type].widen match {
+ case TypeRef(_, _, arg :: _) => arg
+ }
+ println(targ)
+ }
+}
diff --git a/test/files/run/t4859.check b/test/files/run/t4859.check
new file mode 100644
index 0000000000..d329744ca0
--- /dev/null
+++ b/test/files/run/t4859.check
@@ -0,0 +1,8 @@
+Inner
+Inner.i
+About to reference Inner.i
+Outer
+Inner.i
+About to reference O.N
+About to reference O.N
+About to reference O.N.apply()
diff --git a/test/files/run/t4859.scala b/test/files/run/t4859.scala
new file mode 100644
index 0000000000..3c20cea983
--- /dev/null
+++ b/test/files/run/t4859.scala
@@ -0,0 +1,29 @@
+object O {
+ case class N()
+ object P
+}
+
+object Outer {
+ println("Outer")
+ object Inner {
+ println("Inner")
+ def i {
+ println("Inner.i")
+ }
+ }
+}
+
+object Test {
+ def main(args: Array[String]) {
+ Outer.Inner.i // we still don't initialize Outer here (but should we?)
+
+ {println("About to reference Inner.i"); Outer}.Inner.i // Outer will be initialized.
+
+ {println("About to reference O.N" ); O}.N
+
+ {println("About to reference O.N" ); O}.N
+
+ {println("About to reference O.N.apply()"); O}.N.apply()
+ }
+}
+
diff --git a/test/files/run/t5568.check b/test/files/run/t5568.check
new file mode 100644
index 0000000000..67aaf16e07
--- /dev/null
+++ b/test/files/run/t5568.check
@@ -0,0 +1,9 @@
+void
+int
+class scala.runtime.BoxedUnit
+class scala.runtime.BoxedUnit
+class java.lang.Integer
+class java.lang.Integer
+5
+5
+5
diff --git a/test/files/run/t5568.scala b/test/files/run/t5568.scala
new file mode 100644
index 0000000000..14599d9ed2
--- /dev/null
+++ b/test/files/run/t5568.scala
@@ -0,0 +1,16 @@
+object Test {
+ def main(args: Array[String]): Unit = {
+ // these should give unboxed results
+ println(().getClass)
+ println(5.getClass)
+ // these should give boxed results
+ println(().asInstanceOf[AnyRef with Unit].getClass)
+ println(().asInstanceOf[Unit with AnyRef].getClass)
+ println(5.asInstanceOf[AnyRef with Int].getClass)
+ println(5.asInstanceOf[Int with AnyRef].getClass)
+ //make sure ## wasn't broken
+ println(5.##)
+ println((5.asInstanceOf[AnyRef]).##)
+ println((5:Any).##)
+ }
+}
diff --git a/test/files/run/t6011c.scala b/test/files/run/t6011c.scala
new file mode 100644
index 0000000000..0647e3f81a
--- /dev/null
+++ b/test/files/run/t6011c.scala
@@ -0,0 +1,13 @@
+object Test extends App {
+ // A variation of SI-6011, which eluded the fix
+ // in 2.10.0.
+ //
+ // duplicate keys in SWITCH, can't pick arbitrarily one of them to evict, see SI-6011.
+ // at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:50)
+ // at scala.tools.nsc.Global.abort(Global.scala:249)
+ // at scala.tools.nsc.backend.jvm.GenASM$JPlainBuilder$jcode$.emitSWITCH(GenASM.scala:1850)
+ ((1: Byte): @unchecked @annotation.switch) match {
+ case 1 => 2
+ case 1 => 3 // crash
+ }
+}
diff --git a/test/files/run/t6028.check b/test/files/run/t6028.check
index 42921ae2f5..942f3d5f0c 100644
--- a/test/files/run/t6028.check
+++ b/test/files/run/t6028.check
@@ -15,7 +15,7 @@ package <empty> {
}
};
def bar(barParam: Int): Object = {
- @volatile var MethodLocalObject$module: runtime.VolatileObjectRef = new runtime.VolatileObjectRef(<empty>);
+ @volatile var MethodLocalObject$module: runtime.VolatileObjectRef = new runtime.VolatileObjectRef(null);
T.this.MethodLocalObject$1(barParam, MethodLocalObject$module)
};
def tryy(tryyParam: Int): Function0 = {
diff --git a/test/files/run/t6434.check b/test/files/run/t6434.check
new file mode 100644
index 0000000000..f898b6b781
--- /dev/null
+++ b/test/files/run/t6434.check
@@ -0,0 +1,10 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala> def f(x: => Int): Int = x
+f: (x: => Int)Int
+
+scala> f _
+res0: (=> Int) => Int = <function1>
+
+scala>
diff --git a/test/files/run/t6434.scala b/test/files/run/t6434.scala
new file mode 100644
index 0000000000..e4a4579613
--- /dev/null
+++ b/test/files/run/t6434.scala
@@ -0,0 +1,8 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ def code =
+"""def f(x: => Int): Int = x
+f _
+"""
+}
diff --git a/test/files/run/t6439.check b/test/files/run/t6439.check
new file mode 100644
index 0000000000..3f5f7dc8a4
--- /dev/null
+++ b/test/files/run/t6439.check
@@ -0,0 +1,77 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> class A
+defined class A
+
+scala> object A // warn
+defined object A
+warning: previously defined class A is not a companion to object A.
+Companions must be defined together; you may wish to use :paste mode for this.
+
+scala> trait B
+defined trait B
+
+scala> object B // warn
+defined object B
+warning: previously defined trait B is not a companion to object B.
+Companions must be defined together; you may wish to use :paste mode for this.
+
+scala> object C
+defined object C
+
+scala> object Bippy
+defined object Bippy
+
+scala> class C // warn
+defined class C
+warning: previously defined object C is not a companion to class C.
+Companions must be defined together; you may wish to use :paste mode for this.
+
+scala> class D
+defined class D
+
+scala> def D = 0 // no warn
+D: Int
+
+scala> val D = 0 // no warn
+D: Int = 0
+
+scala> object E
+defined object E
+
+scala> var E = 0 // no warn
+E: Int = 0
+
+scala> object F
+defined object F
+
+scala> type F = Int // no warn
+defined type alias F
+
+scala> :power
+** Power User mode enabled - BEEP WHIR GYVE **
+** :phase has been set to 'typer'. **
+** scala.tools.nsc._ has been imported **
+** global._, definitions._ also imported **
+** Try :help, :vals, power.<tab> **
+
+scala> object lookup {
+ import intp._
+ def apply(name: String): Symbol = types(name) orElse terms(name)
+ def types(name: String): Symbol = replScope lookup (name: TypeName) orElse getClassIfDefined(name)
+ def terms(name: String): Symbol = replScope lookup (name: TermName) orElse getModuleIfDefined(name)
+ def types[T: global.TypeTag] : Symbol = typeOf[T].typeSymbol
+ def terms[T: global.TypeTag] : Symbol = typeOf[T].termSymbol
+ def apply[T: global.TypeTag] : Symbol = typeOf[T].typeSymbol
+}
+defined object lookup
+
+scala> lookup("F") // this now works as a result of changing .typeSymbol to .typeSymbolDirect in IMain#Request#definedSymbols
+res0: $r.intp.global.Symbol = type F
+
+scala>
+
+scala>
diff --git a/test/files/run/t6439.scala b/test/files/run/t6439.scala
new file mode 100644
index 0000000000..175a1d134f
--- /dev/null
+++ b/test/files/run/t6439.scala
@@ -0,0 +1,32 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+
+ def code = """
+class A
+object A // warn
+trait B
+object B // warn
+object C
+object Bippy
+class C // warn
+class D
+def D = 0 // no warn
+val D = 0 // no warn
+object E
+var E = 0 // no warn
+object F
+type F = Int // no warn
+:power
+object lookup {
+ import intp._
+ def apply(name: String): Symbol = types(name) orElse terms(name)
+ def types(name: String): Symbol = replScope lookup (name: TypeName) orElse getClassIfDefined(name)
+ def terms(name: String): Symbol = replScope lookup (name: TermName) orElse getModuleIfDefined(name)
+ def types[T: global.TypeTag] : Symbol = typeOf[T].typeSymbol
+ def terms[T: global.TypeTag] : Symbol = typeOf[T].termSymbol
+ def apply[T: global.TypeTag] : Symbol = typeOf[T].typeSymbol
+}
+lookup("F") // this now works as a result of changing .typeSymbol to .typeSymbolDirect in IMain#Request#definedSymbols
+ """
+}
diff --git a/test/files/run/t6860.check b/test/files/run/t6860.check
new file mode 100644
index 0000000000..c96331f540
--- /dev/null
+++ b/test/files/run/t6860.check
@@ -0,0 +1,4 @@
+Bippy[String]
+Bippy[String]
+throws[Nothing]
+throws[RuntimeException]
diff --git a/test/files/run/t6860.scala b/test/files/run/t6860.scala
new file mode 100644
index 0000000000..2dcc2a67f7
--- /dev/null
+++ b/test/files/run/t6860.scala
@@ -0,0 +1,20 @@
+class Bippy[T](val value: T) extends annotation.StaticAnnotation
+
+class A {
+ @Bippy("hi") def f1: Int = 1
+ @Bippy[String]("hi") def f2: Int = 2
+
+ @throws("what do I throw?") def f3 = throw new RuntimeException
+ @throws[RuntimeException]("that's good to know!") def f4 = throw new RuntimeException
+}
+
+object Test {
+ import scala.reflect.runtime.universe._
+
+ def main(args: Array[String]): Unit = {
+ val members = typeOf[A].declarations.toList
+ val tpes = members flatMap (_.annotations) map (_.tpe)
+
+ tpes.map(_.toString).sorted foreach println
+ }
+}
diff --git a/test/files/run/t6956.check b/test/files/run/t6956.check
new file mode 100644
index 0000000000..0cfbf08886
--- /dev/null
+++ b/test/files/run/t6956.check
@@ -0,0 +1 @@
+2
diff --git a/test/files/run/t6956.scala b/test/files/run/t6956.scala
new file mode 100644
index 0000000000..4a6583ca45
--- /dev/null
+++ b/test/files/run/t6956.scala
@@ -0,0 +1,26 @@
+import scala.tools.partest.IcodeTest
+
+class Switches {
+ private[this] final val ONE = 1
+
+ def switchBad(i: Byte): Int = i match {
+ case ONE => 1
+ case 2 => 2
+ case 3 => 3
+ case _ => 0
+ }
+
+ def switchOkay(i: Byte): Int = i match {
+ case 1 => 1
+ case 2 => 2
+ case 3 => 3
+ case _ => 0
+ }
+}
+
+object Test extends IcodeTest {
+ // ensure we get two switches out of this -- ignore the rest of the output for robustness
+ // exclude the constant we emit for the "SWITCH ..." string below (we get the icode for all the code you see in this file)
+ override def show() = println(collectIcode("").filter(x => x.indexOf("SWITCH ...") >= 0 && x.indexOf("CONSTANT(") == -1).size)
+}
+
diff --git a/test/files/run/t6969.check b/test/files/run/t6969.check
new file mode 100644
index 0000000000..78297812c9
--- /dev/null
+++ b/test/files/run/t6969.check
@@ -0,0 +1 @@
+All threads completed.
diff --git a/test/files/run/t6969.scala b/test/files/run/t6969.scala
new file mode 100644
index 0000000000..8cfc28c1e5
--- /dev/null
+++ b/test/files/run/t6969.scala
@@ -0,0 +1,28 @@
+object Test {
+ private type Clearable = { def clear(): Unit }
+ private def choke() = {
+ try new Array[Object]((Runtime.getRuntime().maxMemory min Int.MaxValue).toInt)
+ catch {
+ case _: OutOfMemoryError => // what do you mean, out of memory?
+ case t: Throwable => println(t)
+ }
+ }
+ private def f(x: Clearable) = x.clear()
+ class Choker(id: Int) extends Thread {
+ private def g(iteration: Int) = {
+ val map = scala.collection.mutable.Map[Int, Int](1 -> 2)
+ try f(map) catch { case t: NullPointerException => println(s"Failed at $id/$iteration") ; throw t }
+ choke()
+ }
+ override def run() {
+ 1 to 50 foreach g
+ }
+ }
+
+ def main(args: Array[String]): Unit = {
+ val threads = 1 to 3 map (id => new Choker(id))
+ threads foreach (_.start())
+ threads foreach (_.join())
+ println("All threads completed.")
+ }
+}
diff --git a/test/partest b/test/partest
index 6d9fc01cd5..2bd8ce94f3 100755
--- a/test/partest
+++ b/test/partest
@@ -83,8 +83,8 @@ fi
# last arg wins, so if JAVA_OPTS already contains -Xmx or -Xms the
# supplied argument will be used.
JAVA_OPTS="-Xmx1024M -Xms64M $JAVA_OPTS"
-# the ant task doesn't supply any options by default,
-# so don't to that here either -- note that you may want to pass -optimise
+# the ant task doesn't supply any options by default,
+# so don't to that here either -- note that you may want to pass -optimise
# to mimic what happens during nightlies
# [ -n "$SCALAC_OPTS" ] || SCALAC_OPTS="-deprecation"
diff --git a/test/pending/pos/those-kinds-are-high.scala b/test/pending/pos/those-kinds-are-high.scala
index 434e64cefb..78367cb746 100644
--- a/test/pending/pos/those-kinds-are-high.scala
+++ b/test/pending/pos/those-kinds-are-high.scala
@@ -4,18 +4,18 @@ class A {
class C1[T] extends Template[C1] with Container[T]
class C2[T] extends Template[C2] with Container[T]
-
+
/** Target expression:
* List(new C1[String], new C2[String])
*/
-
+
// Here's what would ideally be inferred.
//
// scala> :type List[Template[Container] with Container[String]](new C1[String], new C2[String])
// List[Template[Container] with Container[java.lang.String]]
//
// Here's what it does infer.
- //
+ //
// scala> :type List(new C1[String], new C2[String])
// <console>:8: error: type mismatch;
// found : C1[String]
@@ -43,11 +43,54 @@ class A {
// def fFail = List(new C1[String], new C2[String])
// ^
// two errors found
-
+
/** Working version explicitly typed.
*/
def fExplicit = List[Template[Container] with Container[String]](new C1[String], new C2[String])
-
+
// nope
def fFail = List(new C1[String], new C2[String])
}
+
+
+trait Other {
+ trait GenBar[+A]
+ trait Bar[+A] extends GenBar[A]
+ trait Templ[+A, +CC[X] <: GenBar[X]]
+
+ abstract class CC1[+A] extends Templ[A, CC1] with Bar[A]
+ abstract class CC2[+A] extends Templ[A, CC2] with Bar[A]
+
+ // Compiles
+ class A1 {
+ abstract class BarFactory[CC[X] <: Bar[X]]
+
+ def f(x: Boolean) = if (x) (null: BarFactory[CC1]) else (null: BarFactory[CC2])
+ }
+
+ // Fails - only difference is CC covariant.
+ class A2 {
+ abstract class BarFactory[+CC[X] <: Bar[X]]
+
+ def f(x: Boolean) = if (x) (null: BarFactory[CC1]) else (null: BarFactory[CC2])
+ // c.scala:23: error: kinds of the type arguments (Bar with Templ[Any,Bar]) do not conform to the expected kinds of the type parameters (type CC) in class BarFactory.
+ // Bar with Templ[Any,Bar]'s type parameters do not match type CC's expected parameters:
+ // <empty> has no type parameters, but type CC has one
+ // def f(x: Boolean) = if (x) (null: BarFactory[CC1]) else (null: BarFactory[CC2])
+ // ^
+ // one error found
+ }
+
+ // Compiles - CC contravariant.
+ class A3 {
+ abstract class BarFactory[-CC[X] <: Bar[X]] // with Templ[X, CC]]
+
+ def f(x: Boolean) = if (x) (null: BarFactory[CC1]) else (null: BarFactory[CC2])
+ // c.scala:23: error: kinds of the type arguments (Bar with Templ[Any,Bar]) do not conform to the expected kinds of the type parameters (type CC) in class BarFactory.
+ // Bar with Templ[Any,Bar]'s type parameters do not match type CC's expected parameters:
+ // <empty> has no type parameters, but type CC has one
+ // def f(x: Boolean) = if (x) (null: BarFactory[CC1]) else (null: BarFactory[CC2])
+ // ^
+ // one error found
+ }
+}