summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/files/instrumented/inline-in-constructors.flags2
-rw-r--r--test/files/jvm/constant-optimization/Foo_1.flags2
-rw-r--r--test/files/jvm/innerClassAttribute.check30
-rw-r--r--test/files/jvm/innerClassAttribute/Classes_1.scala30
-rw-r--r--test/files/jvm/innerClassAttribute/Test.scala49
-rw-r--r--test/files/jvm/javaReflection/Classes_1.scala18
-rw-r--r--test/files/jvm/patmat_opt_ignore_underscore.flags2
-rw-r--r--test/files/jvm/patmat_opt_no_nullcheck.flags2
-rw-r--r--test/files/jvm/patmat_opt_primitive_typetest.flags2
-rw-r--r--test/files/jvm/t7006/Foo_1.flags2
-rw-r--r--test/files/neg/inlineMaxSize.check4
-rw-r--r--test/files/neg/inlineMaxSize.scala2
-rw-r--r--test/files/neg/t3234.flags2
-rw-r--r--test/files/neg/t7623.check24
-rw-r--r--test/files/neg/t7623.scala8
-rw-r--r--test/files/neg/t9286a.check7
-rw-r--r--test/files/neg/t9286a.scala13
-rw-r--r--test/files/neg/t9286b.check7
-rw-r--r--test/files/neg/t9286b.scala5
-rw-r--r--test/files/neg/t9286c.check7
-rw-r--r--test/files/neg/t9286c.scala14
-rw-r--r--test/files/pos/t9321.scala10
-rw-r--r--test/files/run/function-null-unbox.scala8
-rw-r--r--test/files/run/indylambda-boxing/VC.scala2
-rw-r--r--test/files/run/indylambda-boxing/test.scala29
-rw-r--r--test/files/run/lambda-serialization-gc.scala40
-rw-r--r--test/files/run/lambda-serialization.scala35
-rw-r--r--test/files/run/private-inline.flags2
-rw-r--r--test/files/run/synchronized.check5
-rw-r--r--test/files/run/synchronized.scala3
-rw-r--r--test/files/run/t6102.check5
-rw-r--r--test/files/run/t8601-closure-elim.flags2
-rw-r--r--test/files/scalacheck/redblacktree.scala2
-rw-r--r--test/junit/scala/collection/IteratorTest.scala10
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala231
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala16
-rw-r--r--test/scaladoc/run/SI-8210.check1
-rw-r--r--test/scaladoc/run/SI-8210.scala24
38 files changed, 559 insertions, 98 deletions
diff --git a/test/files/instrumented/inline-in-constructors.flags b/test/files/instrumented/inline-in-constructors.flags
index 068318e8ac..d1ebc4c940 100644
--- a/test/files/instrumented/inline-in-constructors.flags
+++ b/test/files/instrumented/inline-in-constructors.flags
@@ -1 +1 @@
--optimise -Ydelambdafy:inline
+-optimise -Ydelambdafy:inline -Ybackend:GenASM
diff --git a/test/files/jvm/constant-optimization/Foo_1.flags b/test/files/jvm/constant-optimization/Foo_1.flags
index 86f52af447..67a1dbe8da 100644
--- a/test/files/jvm/constant-optimization/Foo_1.flags
+++ b/test/files/jvm/constant-optimization/Foo_1.flags
@@ -1 +1 @@
--Ynooptimise -Yconst-opt \ No newline at end of file
+-Ynooptimise -Yconst-opt -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/jvm/innerClassAttribute.check b/test/files/jvm/innerClassAttribute.check
index bb532e4f36..41448f359b 100644
--- a/test/files/jvm/innerClassAttribute.check
+++ b/test/files/jvm/innerClassAttribute.check
@@ -14,27 +14,27 @@ A19 / null / null
A19 / null / null
A19 / null / null
-- A20 --
-A20$$anonfun$6 / null / null / 17
+A20$$anonfun$4 / null / null / 17
fun1: attribute for itself and the two child closures `() => ()` and `() => () => 1`
-A20$$anonfun$6 / null / null / 17
-A20$$anonfun$6$$anonfun$apply$1 / null / null / 17
-A20$$anonfun$6$$anonfun$apply$3 / null / null / 17
+A20$$anonfun$4 / null / null / 17
+A20$$anonfun$4$$anonfun$apply$1 / null / null / 17
+A20$$anonfun$4$$anonfun$apply$2 / null / null / 17
fun2 () => (): itself and the outer closure
-A20$$anonfun$6 / null / null / 17
-A20$$anonfun$6$$anonfun$apply$1 / null / null / 17
+A20$$anonfun$4 / null / null / 17
+A20$$anonfun$4$$anonfun$apply$1 / null / null / 17
fun3 () => () => (): itself, the outer closure and its child closure
-A20$$anonfun$6 / null / null / 17
-A20$$anonfun$6$$anonfun$apply$3 / null / null / 17
-A20$$anonfun$6$$anonfun$apply$3$$anonfun$apply$2 / null / null / 17
+A20$$anonfun$4 / null / null / 17
+A20$$anonfun$4$$anonfun$apply$2 / null / null / 17
+A20$$anonfun$4$$anonfun$apply$2$$anonfun$apply$3 / null / null / 17
fun4: () => 1: itself and the two outer closures
-A20$$anonfun$6 / null / null / 17
-A20$$anonfun$6$$anonfun$apply$3 / null / null / 17
-A20$$anonfun$6$$anonfun$apply$3$$anonfun$apply$2 / null / null / 17
+A20$$anonfun$4 / null / null / 17
+A20$$anonfun$4$$anonfun$apply$2 / null / null / 17
+A20$$anonfun$4$$anonfun$apply$2$$anonfun$apply$3 / null / null / 17
enclosing: nested closures have outer class defined, but no outer method
A20 / null / null
-A20$$anonfun$6 / null / null
-A20$$anonfun$6 / null / null
-A20$$anonfun$6$$anonfun$apply$3 / null / null
+A20$$anonfun$4 / null / null
+A20$$anonfun$4 / null / null
+A20$$anonfun$4$$anonfun$apply$2 / null / null
#partest -Ydelambdafy:method
-- A4 --
null / null / null
diff --git a/test/files/jvm/innerClassAttribute/Classes_1.scala b/test/files/jvm/innerClassAttribute/Classes_1.scala
index fb1f32aa3d..62c7d94d90 100644
--- a/test/files/jvm/innerClassAttribute/Classes_1.scala
+++ b/test/files/jvm/innerClassAttribute/Classes_1.scala
@@ -12,8 +12,8 @@ object A3 {
}
class A4 {
- def f(l: List[Int]): List[Int] = {
- l map (_ + 1)
+ def f(l: List[String]): List[String] = {
+ l map (_ + "1")
}
}
@@ -114,21 +114,21 @@ class A18 {
}
class A19 {
- ((x: Int) => x + 3)
+ ((x: String) => x + "3")
val x = {
- ((x: Int) => x + 1)
+ ((x: String) => x + "1")
}
{
- ((x: Int) => x + 2)
+ ((x: String) => x + "2")
}
}
class A20 {
- () => {
- {() => ()}
- {() => () => 1}
+ (s: String) => {
+ {(s: String) => ()}
+ {(s: String) => (s: String) => 1}
}
}
@@ -189,13 +189,13 @@ trait A24 extends A24Base {
class SI_9105 {
// the EnclosingMethod attributes depend on the delambdafy strategy (inline vs method)
- // outerClass-inline enclMeth-inline outerClass-method enclMeth-method
- val fun = () => {
+ // outerClass-inline enclMeth-inline outerClass-method enclMeth-method
+ val fun = (s: String) => {
class A // closure null (*) SI_9105 null
def m: Object = { class B; new B } // closure m$1 SI_9105 m$1
val f: Object = { class C; new C } // closure null (*) SI_9105 null
}
- def met = () => {
+ def met = (s: String) => {
class D // closure null (*) SI_9105 met
def m: Object = { class E; new E } // closure m$1 SI_9105 m$1
val f: Object = { class F; new F } // closure null (*) SI_9105 met
@@ -210,17 +210,19 @@ class SI_9105 {
// So using `null` looks more like the situation in the source code: C / F are nested classes of the anon-fun, and
// there's no method in between.
- def byName[T](op: => T) = 0
+ def byName(op: => Any) = 0
val bnV = byName {
class G // closure null (*) SI_9105 null
def m: Object = { class H; new H } // closure m$1 SI_9105 m$1
val f: Object = { class I; new I } // closure null (*) SI_9105 null
+ ""
}
def bnM = byName {
class J // closure null (*) SI_9105 bnM
def m: Object = { class K; new K } // closure m$1 SI_9105 m$1
val f: Object = { class L; new L } // closure null (*) SI_9105 bnM
+ ""
}
}
@@ -283,8 +285,8 @@ object NestedInValueClass {
class A(val arg: String) extends AnyVal {
// A has InnerClass entries for the two closures (and for A and A$). not for B / C
def f = {
- def g = List().map(x => (() => x)) // outer class A, no outer method (g is moved to the companion, doesn't exist in A)
- g.map(x => (() => x)) // outer class A, outer method f
+ def g = List().map(x => ((s: String) => x)) // outer class A, no outer method (g is moved to the companion, doesn't exist in A)
+ g.map(x => ((s: String) => x)) // outer class A, outer method f
}
// statements and field declarations are not allowed in value classes
}
diff --git a/test/files/jvm/innerClassAttribute/Test.scala b/test/files/jvm/innerClassAttribute/Test.scala
index bc9aa2376a..376b3c895b 100644
--- a/test/files/jvm/innerClassAttribute/Test.scala
+++ b/test/files/jvm/innerClassAttribute/Test.scala
@@ -5,11 +5,14 @@ import asm.{Opcodes => Flags}
import scala.collection.JavaConverters._
object Test extends BytecodeTest {
+ // Helpful for debugging the test:
+ // println(new java.io.File(classpath.asURLs.head.toURI).list().sorted.mkString("\n"))
+
def assertSame(a: Any, b: Any) = {
assert(a == b, s"\na: $a\nb: $b")
}
- val publicStatic = Flags.ACC_PUBLIC | Flags.ACC_STATIC
+ val publicStatic = Flags.ACC_PUBLIC | Flags.ACC_STATIC
val publicAbstractInterface = Flags.ACC_PUBLIC | Flags.ACC_ABSTRACT | Flags.ACC_INTERFACE
def innerClassNodes(className: String): List[InnerClassNode] = {
@@ -266,10 +269,10 @@ object Test extends BytecodeTest {
printInnerClassNodes("A20")
- val fun1 = lambdaClass("A20$$anonfun$6", "A20$lambda$1")
- val fun2 = lambdaClass("A20$$anonfun$6$$anonfun$apply$1", "A20$lambda$$$nestedInAnonfun$5$1")
- val fun3 = lambdaClass("A20$$anonfun$6$$anonfun$apply$3", "A20$lambda$$$nestedInAnonfun$5$2")
- val fun4 = lambdaClass("A20$$anonfun$6$$anonfun$apply$3$$anonfun$apply$2", "A20$lambda$$$nestedInAnonfun$7$1")
+ val fun1 = lambdaClass("A20$$anonfun$4", "A20$lambda$1")
+ val fun2 = lambdaClass("A20$$anonfun$4$$anonfun$apply$1", "A20$lambda$$$nestedInAnonfun$5$1")
+ val fun3 = lambdaClass("A20$$anonfun$4$$anonfun$apply$2", "A20$lambda$$$nestedInAnonfun$5$2")
+ val fun4 = lambdaClass("A20$$anonfun$4$$anonfun$apply$2$$anonfun$apply$3", "A20$lambda$$$nestedInAnonfun$7$1")
println("fun1: attribute for itself and the two child closures `() => ()` and `() => () => 1`")
printInnerClassNodes(fun1)
@@ -339,9 +342,9 @@ object Test extends BytecodeTest {
assertEnclosingMethod ("SI_9105$A$3" , "SI_9105", null , null)
assertEnclosingMethod ("SI_9105$B$5" , "SI_9105", "m$1", "()Ljava/lang/Object;")
assertEnclosingMethod ("SI_9105$C$1" , "SI_9105", null , null)
- assertEnclosingMethod ("SI_9105$D$1" , "SI_9105", "met", "()Lscala/Function0;")
+ assertEnclosingMethod ("SI_9105$D$1" , "SI_9105", "met", "()Lscala/Function1;")
assertEnclosingMethod ("SI_9105$E$1" , "SI_9105", "m$3", "()Ljava/lang/Object;")
- assertEnclosingMethod ("SI_9105$F$1" , "SI_9105", "met", "()Lscala/Function0;")
+ assertEnclosingMethod ("SI_9105$F$1" , "SI_9105", "met", "()Lscala/Function1;")
assertNoEnclosingMethod("SI_9105$lambda$$met$1")
assertNoEnclosingMethod("SI_9105$lambda$1")
assertNoEnclosingMethod("SI_9105")
@@ -366,35 +369,35 @@ object Test extends BytecodeTest {
assert(innerClassNodes("SI_9105").length == 12) // the 12 local classes
} else {
// comment in innerClassAttribute/Classes_1.scala explains the difference between A / C and D / F.
- assertEnclosingMethod ("SI_9105$$anonfun$4$A$3" , "SI_9105$$anonfun$4" , null , null)
- assertEnclosingMethod ("SI_9105$$anonfun$4$B$5" , "SI_9105$$anonfun$4" , "m$1" , "()Ljava/lang/Object;")
- assertEnclosingMethod ("SI_9105$$anonfun$4$C$1" , "SI_9105$$anonfun$4" , null , null)
+ assertEnclosingMethod ("SI_9105$$anonfun$5$A$3" , "SI_9105$$anonfun$5" , null , null)
+ assertEnclosingMethod ("SI_9105$$anonfun$5$B$5" , "SI_9105$$anonfun$5" , "m$1" , "()Ljava/lang/Object;")
+ assertEnclosingMethod ("SI_9105$$anonfun$5$C$1" , "SI_9105$$anonfun$5" , null , null)
assertEnclosingMethod ("SI_9105$$anonfun$met$1$D$1", "SI_9105$$anonfun$met$1", null , null)
assertEnclosingMethod ("SI_9105$$anonfun$met$1$E$1", "SI_9105$$anonfun$met$1", "m$3" , "()Ljava/lang/Object;")
assertEnclosingMethod ("SI_9105$$anonfun$met$1$F$1", "SI_9105$$anonfun$met$1", null , null)
- assertEnclosingMethod ("SI_9105$$anonfun$4" , "SI_9105" , null , null)
- assertEnclosingMethod ("SI_9105$$anonfun$met$1" , "SI_9105" , "met" , "()Lscala/Function0;")
+ assertEnclosingMethod ("SI_9105$$anonfun$5" , "SI_9105" , null , null)
+ assertEnclosingMethod ("SI_9105$$anonfun$met$1" , "SI_9105" , "met" , "()Lscala/Function1;")
assertNoEnclosingMethod("SI_9105")
- assertLocal(ownInnerClassNode("SI_9105$$anonfun$4$A$3"), "SI_9105$$anonfun$4$A$3" , "A$3")
- assertLocal(ownInnerClassNode("SI_9105$$anonfun$4$B$5"), "SI_9105$$anonfun$4$B$5" , "B$5")
- assertLocal(ownInnerClassNode("SI_9105$$anonfun$4$C$1"), "SI_9105$$anonfun$4$C$1" , "C$1")
+ assertLocal(ownInnerClassNode("SI_9105$$anonfun$5$A$3"), "SI_9105$$anonfun$5$A$3" , "A$3")
+ assertLocal(ownInnerClassNode("SI_9105$$anonfun$5$B$5"), "SI_9105$$anonfun$5$B$5" , "B$5")
+ assertLocal(ownInnerClassNode("SI_9105$$anonfun$5$C$1"), "SI_9105$$anonfun$5$C$1" , "C$1")
assertLocal(ownInnerClassNode("SI_9105$$anonfun$met$1$D$1"), "SI_9105$$anonfun$met$1$D$1", "D$1")
assertLocal(ownInnerClassNode("SI_9105$$anonfun$met$1$E$1"), "SI_9105$$anonfun$met$1$E$1", "E$1")
assertLocal(ownInnerClassNode("SI_9105$$anonfun$met$1$F$1"), "SI_9105$$anonfun$met$1$F$1", "F$1")
// by-name
- assertEnclosingMethod("SI_9105$$anonfun$5$G$1", "SI_9105$$anonfun$5", null, null)
- assertEnclosingMethod("SI_9105$$anonfun$5$H$1", "SI_9105$$anonfun$5", "m$2", "()Ljava/lang/Object;")
- assertEnclosingMethod("SI_9105$$anonfun$5$I$1", "SI_9105$$anonfun$5", null, null)
+ assertEnclosingMethod("SI_9105$$anonfun$6$G$1", "SI_9105$$anonfun$6", null, null)
+ assertEnclosingMethod("SI_9105$$anonfun$6$H$1", "SI_9105$$anonfun$6", "m$2", "()Ljava/lang/Object;")
+ assertEnclosingMethod("SI_9105$$anonfun$6$I$1", "SI_9105$$anonfun$6", null, null)
assertEnclosingMethod("SI_9105$$anonfun$bnM$1$J$1", "SI_9105$$anonfun$bnM$1", null, null)
assertEnclosingMethod("SI_9105$$anonfun$bnM$1$K$2", "SI_9105$$anonfun$bnM$1", "m$4", "()Ljava/lang/Object;")
assertEnclosingMethod("SI_9105$$anonfun$bnM$1$L$1", "SI_9105$$anonfun$bnM$1", null, null)
- assertAnonymous(ownInnerClassNode("SI_9105$$anonfun$4"), "SI_9105$$anonfun$4")
+ assertAnonymous(ownInnerClassNode("SI_9105$$anonfun$5"), "SI_9105$$anonfun$5")
assertAnonymous(ownInnerClassNode("SI_9105$$anonfun$met$1"), "SI_9105$$anonfun$met$1")
- assert(innerClassNodes("SI_9105$$anonfun$4").length == 4) // itself and three of the local classes
+ assert(innerClassNodes("SI_9105$$anonfun$5").length == 4) // itself and three of the local classes
assert(innerClassNodes("SI_9105$$anonfun$met$1").length == 4) // itself and three of the local classes
assert(innerClassNodes("SI_9105").length == 4) // the four anon funs
}
@@ -474,7 +477,7 @@ object Test extends BytecodeTest {
testInner("ImplClassesAreTopLevel$B2$1$class", b2)
testInner("ImplClassesAreTopLevel$B3$1$class", b3)
testInner("ImplClassesAreTopLevel$B4$class", b4)
-
+
testInner("ImplClassesAreTopLevel$B1", b1)
testInner("ImplClassesAreTopLevel$B2$1", b2)
testInner("ImplClassesAreTopLevel$B3$1", b3)
@@ -533,13 +536,13 @@ object Test extends BytecodeTest {
"NestedInValueClass$A$lambda$$g$2$1",
"NestedInValueClass$A$lambda$$f$extension$1",
"NestedInValueClass$A$lambda$$$nestedInAnonfun$13$1",
- "NestedInValueClass$A$lambda$$$nestedInAnonfun$15$1").foreach(assertNoEnclosingMethod)
+ "NestedInValueClass$A$lambda$$NestedInValueClass$A$$$nestedInAnonfun$15$1").foreach(assertNoEnclosingMethod)
testInner("NestedInValueClass$A", a, am)
testInner("NestedInValueClass$A$", a, am, b, c)
testInner("NestedInValueClass$A$lambda$$g$2$1", am)
testInner("NestedInValueClass$A$lambda$$f$extension$1", am)
testInner("NestedInValueClass$A$lambda$$$nestedInAnonfun$13$1", am)
- testInner("NestedInValueClass$A$lambda$$$nestedInAnonfun$15$1", am)
+ testInner("NestedInValueClass$A$lambda$$NestedInValueClass$A$$$nestedInAnonfun$15$1", am)
} else {
assertEnclosingMethod("NestedInValueClass$A$$anonfun$g$2$1" , "NestedInValueClass$A" , null, null)
assertEnclosingMethod("NestedInValueClass$A$$anonfun$g$2$1$$anonfun$apply$4" , "NestedInValueClass$A$$anonfun$g$2$1" , null, null)
diff --git a/test/files/jvm/javaReflection/Classes_1.scala b/test/files/jvm/javaReflection/Classes_1.scala
index 11963e2770..e9cd4f756a 100644
--- a/test/files/jvm/javaReflection/Classes_1.scala
+++ b/test/files/jvm/javaReflection/Classes_1.scala
@@ -13,7 +13,7 @@ class A {
trait C
object D
new T { }
- (() => -1)
+ (() => "-1")
def f = { class KB }
}
@@ -21,21 +21,21 @@ class A {
new T { }
// anonymous function, not a member
- (() => 1)
+ (() => "1")
def f = {
class E
trait F
object G
new T { }
- (() => 2)
+ (() => "2")
if (new Object().hashCode == 1) {
class H
trait I
object J
new T { }
- (() => 3)
+ (() => "3")
} else {
()
}
@@ -46,7 +46,7 @@ class A {
trait L
object M
new T { }
- (() => 4)
+ (() => "4")
}
val x = {
@@ -54,7 +54,7 @@ class A {
trait O
object P
new T { }
- (() => 5)
+ (() => "5")
}
def this(x: Int) {
@@ -63,7 +63,7 @@ class A {
trait R
object S
new T { }
- (() => () => 5)
+ (() => () => "5")
}
}
@@ -72,7 +72,7 @@ object AO {
trait C
object D
new T { }
- (() => 1)
+ (() => "1")
}
trait AT {
@@ -80,5 +80,5 @@ trait AT {
trait C
object D
new T { }
- (() => 1)
+ (() => "1")
}
diff --git a/test/files/jvm/patmat_opt_ignore_underscore.flags b/test/files/jvm/patmat_opt_ignore_underscore.flags
index 1182725e86..2cd4b38726 100644
--- a/test/files/jvm/patmat_opt_ignore_underscore.flags
+++ b/test/files/jvm/patmat_opt_ignore_underscore.flags
@@ -1 +1 @@
--optimize \ No newline at end of file
+-optimize -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/jvm/patmat_opt_no_nullcheck.flags b/test/files/jvm/patmat_opt_no_nullcheck.flags
index 1182725e86..2cd4b38726 100644
--- a/test/files/jvm/patmat_opt_no_nullcheck.flags
+++ b/test/files/jvm/patmat_opt_no_nullcheck.flags
@@ -1 +1 @@
--optimize \ No newline at end of file
+-optimize -Ybackend:GenASM \ No newline at end of file
diff --git a/test/files/jvm/patmat_opt_primitive_typetest.flags b/test/files/jvm/patmat_opt_primitive_typetest.flags
index 49d036a887..b9bb09167e 100644
--- a/test/files/jvm/patmat_opt_primitive_typetest.flags
+++ b/test/files/jvm/patmat_opt_primitive_typetest.flags
@@ -1 +1 @@
--optimize
+-optimize -Ybackend:GenASM
diff --git a/test/files/jvm/t7006/Foo_1.flags b/test/files/jvm/t7006/Foo_1.flags
index 37b2116413..29a9d424f0 100644
--- a/test/files/jvm/t7006/Foo_1.flags
+++ b/test/files/jvm/t7006/Foo_1.flags
@@ -1 +1 @@
--optimise -Ydebug -Xfatal-warnings
+-optimise -Ydebug -Xfatal-warnings -Ybackend:GenASM
diff --git a/test/files/neg/inlineMaxSize.check b/test/files/neg/inlineMaxSize.check
index d218a8b6e2..9d790e154c 100644
--- a/test/files/neg/inlineMaxSize.check
+++ b/test/files/neg/inlineMaxSize.check
@@ -2,8 +2,8 @@ inlineMaxSize.scala:7: warning: C::i()I is annotated @inline but could not be in
The size of the callsite method C::j()I
would exceed the JVM method size limit after inlining C::i()I.
- @inline final def j = i + i
- ^
+ @inline final def j = i + i + i
+ ^
error: No warnings can be incurred under -Xfatal-warnings.
one warning found
one error found
diff --git a/test/files/neg/inlineMaxSize.scala b/test/files/neg/inlineMaxSize.scala
index 16dc0d9538..9d2db1a357 100644
--- a/test/files/neg/inlineMaxSize.scala
+++ b/test/files/neg/inlineMaxSize.scala
@@ -4,5 +4,5 @@ class C {
@inline final def g = f + f + f + f + f + f + f + f + f + f
@inline final def h = g + g + g + g + g + g + g + g + g + g
@inline final def i = h + h + h + h + h + h + h + h + h + h
- @inline final def j = i + i
+ @inline final def j = i + i + i
}
diff --git a/test/files/neg/t3234.flags b/test/files/neg/t3234.flags
index cc3d9fb6f0..406231bd96 100644
--- a/test/files/neg/t3234.flags
+++ b/test/files/neg/t3234.flags
@@ -1 +1 @@
--Yinline -Yinline-warnings -Xfatal-warnings
+-Yinline -Yinline-warnings -Xfatal-warnings -Ybackend:GenASM
diff --git a/test/files/neg/t7623.check b/test/files/neg/t7623.check
index db368dd369..de35023664 100644
--- a/test/files/neg/t7623.check
+++ b/test/files/neg/t7623.check
@@ -1,21 +1,15 @@
-t7623.scala:19: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).
- def f = "" match { case X(s) => }
+t7623.scala:21: warning: A repeated case parameter or extracted sequence is not matched by a sequence wildcard (_*), and may fail at runtime.
+ def g = "" match { case X(s, t) => } // warn
^
-t7623.scala:21: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).
- def g = "" match { case X(s, t) => }
+t7623.scala:23: warning: Sequence wildcard (_*) does not align with repeated case parameter or extracted sequence; the result may be unexpected.
+ def h = "" match { case X(s, t, u @ _*) => } // warn
^
-t7623.scala:23: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).
- def h = "" match { case X(s, t, u @ _*) => }
- ^
-t7623.scala:9: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).
- def f = C("") match { case C(s) => }
- ^
-t7623.scala:11: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).
- def g = C("") match { case C(s, t) => }
+t7623.scala:11: warning: A repeated case parameter or extracted sequence is not matched by a sequence wildcard (_*), and may fail at runtime.
+ def g = C("") match { case C(s, t) => } // warn
^
-t7623.scala:13: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).
- def h = C("") match { case C(s, t, u @ _*) => }
+t7623.scala:13: warning: Sequence wildcard (_*) does not align with repeated case parameter or extracted sequence; the result may be unexpected.
+ def h = C("") match { case C(s, t, u @ _*) => } // warn
^
error: No warnings can be incurred under -Xfatal-warnings.
-6 warnings found
+four warnings found
one error found
diff --git a/test/files/neg/t7623.scala b/test/files/neg/t7623.scala
index 5c40f37bc1..5334cc5f69 100644
--- a/test/files/neg/t7623.scala
+++ b/test/files/neg/t7623.scala
@@ -8,9 +8,9 @@ object X { def unapplySeq(a: Any): Option[(String, Seq[Int])] = Some("", List(1,
trait Ctest {
def f = C("") match { case C(s) => }
- def g = C("") match { case C(s, t) => }
+ def g = C("") match { case C(s, t) => } // warn
- def h = C("") match { case C(s, t, u @ _*) => }
+ def h = C("") match { case C(s, t, u @ _*) => } // warn
def ok = C("") match { case C(s, u @ _*) => }
}
@@ -18,9 +18,9 @@ trait Ctest {
trait Xtest {
def f = "" match { case X(s) => }
- def g = "" match { case X(s, t) => }
+ def g = "" match { case X(s, t) => } // warn
- def h = "" match { case X(s, t, u @ _*) => }
+ def h = "" match { case X(s, t, u @ _*) => } // warn
def ok = "" match { case X(s, u @ _*) => }
}
diff --git a/test/files/neg/t9286a.check b/test/files/neg/t9286a.check
new file mode 100644
index 0000000000..2bc7c0cf15
--- /dev/null
+++ b/test/files/neg/t9286a.check
@@ -0,0 +1,7 @@
+t9286a.scala:6: error: name clash between defined and inherited member:
+def foo(o: (String,)): Unit in class T and
+private def foo(o: (Any,)): Unit at line 6
+have same type after erasure: (o: Tuple1)Unit
+ private def foo(o: Tuple1[Any]) = ()
+ ^
+one error found
diff --git a/test/files/neg/t9286a.scala b/test/files/neg/t9286a.scala
new file mode 100644
index 0000000000..0375ac591f
--- /dev/null
+++ b/test/files/neg/t9286a.scala
@@ -0,0 +1,13 @@
+class T {
+ def foo(o: Tuple1[String]) = ()
+}
+
+class U extends T {
+ private def foo(o: Tuple1[Any]) = ()
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ new U().foo(null) // IllegalAccessError: tried to access method U.foo(Lscala/Tuple1;)V from class Test$
+ }
+}
diff --git a/test/files/neg/t9286b.check b/test/files/neg/t9286b.check
new file mode 100644
index 0000000000..89a191bfee
--- /dev/null
+++ b/test/files/neg/t9286b.check
@@ -0,0 +1,7 @@
+t9286b.scala:2: error: name clash between defined and inherited member:
+def foo: Int in class C and
+private def foo[A]: Int at line 2
+have same type after erasure: ()Int
+class D extends C { private def foo[A] = 0 }
+ ^
+one error found
diff --git a/test/files/neg/t9286b.scala b/test/files/neg/t9286b.scala
new file mode 100644
index 0000000000..5c23075426
--- /dev/null
+++ b/test/files/neg/t9286b.scala
@@ -0,0 +1,5 @@
+class C { def foo = 0 }
+class D extends C { private def foo[A] = 0 }
+
+class E { private def foo = 0 }
+class F extends E { def foo[A] = 0 } // okay
diff --git a/test/files/neg/t9286c.check b/test/files/neg/t9286c.check
new file mode 100644
index 0000000000..785cb3f937
--- /dev/null
+++ b/test/files/neg/t9286c.check
@@ -0,0 +1,7 @@
+t9286c.scala:8: error: name clash between defined and inherited member:
+def foo(m: M[_ >: String]): Int in trait T and
+private def foo(m: M[_ >: Any]): Int at line 8
+have same type after erasure: (m: M)Int
+ def foo(m: M[_ >: Any]) = 0 // Expected: "same type after erasure"
+ ^
+one error found
diff --git a/test/files/neg/t9286c.scala b/test/files/neg/t9286c.scala
new file mode 100644
index 0000000000..3df08dcfe6
--- /dev/null
+++ b/test/files/neg/t9286c.scala
@@ -0,0 +1,14 @@
+class M[_]
+trait T {
+ def foo(m: M[_ >: String]) = 42
+}
+
+object Test {
+ def t: T = new T {
+ def foo(m: M[_ >: Any]) = 0 // Expected: "same type after erasure"
+ }
+ def main(args: Array[String]): Unit = {
+ val m: M[String] = null
+ t.foo(m) // VeriyError: Duplicate method name&signature
+ }
+}
diff --git a/test/files/pos/t9321.scala b/test/files/pos/t9321.scala
new file mode 100644
index 0000000000..ed3a816656
--- /dev/null
+++ b/test/files/pos/t9321.scala
@@ -0,0 +1,10 @@
+object p {
+ trait A {
+ private[p] val qualifiedPrivateMember = 1
+ }
+
+ def useQualifiedPrivate(b: Mix) =
+ b.qualifiedPrivateMember // allowed
+}
+
+trait Mix extends p.A
diff --git a/test/files/run/function-null-unbox.scala b/test/files/run/function-null-unbox.scala
new file mode 100644
index 0000000000..6c0369fffd
--- /dev/null
+++ b/test/files/run/function-null-unbox.scala
@@ -0,0 +1,8 @@
+object Test {
+ def main(args: Array[String]): Unit = {
+ val i2s = (x: Int) => ""
+ assert(i2s.asInstanceOf[AnyRef => String].apply(null) == "")
+ val i2i = (x: Int) => x + 1
+ assert(i2i.asInstanceOf[AnyRef => Int].apply(null) == 1)
+ }
+}
diff --git a/test/files/run/indylambda-boxing/VC.scala b/test/files/run/indylambda-boxing/VC.scala
new file mode 100644
index 0000000000..ef867a3658
--- /dev/null
+++ b/test/files/run/indylambda-boxing/VC.scala
@@ -0,0 +1,2 @@
+
+class VC(private val i: Int) extends AnyVal
diff --git a/test/files/run/indylambda-boxing/test.scala b/test/files/run/indylambda-boxing/test.scala
new file mode 100644
index 0000000000..cc0a460640
--- /dev/null
+++ b/test/files/run/indylambda-boxing/test.scala
@@ -0,0 +1,29 @@
+class Capture
+class Test {
+ def test1 = (i: Int) => ""
+ def test2 = (i: VC) => i
+ def test3 = (i: Int) => i
+
+ def test4 = {val c = new Capture; (i: Int) => {(c, Test.this.toString); 42} }
+ def test5 = {val c = new Capture; (i: VC) => (c, Test.this.toString) }
+ def test6 = {val c = new Capture; (i: Int) => (c, Test.this.toString) }
+
+ def test7 = {val vc = new Capture; (i: Int) => vc }
+ def test8 = {val c = 42; (s: String) => (s, c)}
+ def test9 = {val c = 42; (s: String) => ()}
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val t = new Test
+ assert(t.test1.apply(42) == "")
+ assert(t.test2.apply(new VC(42)) == new VC(42))
+ assert(t.test3.apply(-1) == -1)
+ t.test4.apply(0)
+ t.test5.apply(new VC(42))
+ t.test6.apply(42)
+ t.test7.apply(0)
+ t.test8.apply("")
+ t.test9.apply("")
+ }
+}
diff --git a/test/files/run/lambda-serialization-gc.scala b/test/files/run/lambda-serialization-gc.scala
new file mode 100644
index 0000000000..8fa0b4b402
--- /dev/null
+++ b/test/files/run/lambda-serialization-gc.scala
@@ -0,0 +1,40 @@
+import java.io._
+
+import java.net.URLClassLoader
+
+class C {
+ def serializeDeserialize[T <: AnyRef](obj: T) = {
+ val buffer = new ByteArrayOutputStream
+ val out = new ObjectOutputStream(buffer)
+ out.writeObject(obj)
+ val in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray))
+ in.readObject.asInstanceOf[T]
+ }
+
+ serializeDeserialize((c: String) => c.length)
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ test()
+ }
+
+ def test(): Unit = {
+ val loader = getClass.getClassLoader.asInstanceOf[URLClassLoader]
+ val loaderCClass = classOf[C]
+ def deserializedInThrowawayClassloader = {
+ val throwawayLoader: java.net.URLClassLoader = new java.net.URLClassLoader(loader.getURLs, ClassLoader.getSystemClassLoader) {
+ val maxMemory = Runtime.getRuntime.maxMemory()
+ val junk = new Array[Byte]((maxMemory / 2).toInt)
+ }
+ val clazz = throwawayLoader.loadClass("C")
+ assert(clazz != loaderCClass)
+ clazz.newInstance()
+ }
+ (1 to 4) foreach { i =>
+ // This would OOM by the third iteration if we leaked `throwawayLoader` during
+ // deserialization.
+ deserializedInThrowawayClassloader
+ }
+ }
+}
diff --git a/test/files/run/lambda-serialization.scala b/test/files/run/lambda-serialization.scala
new file mode 100644
index 0000000000..46b26d7c5e
--- /dev/null
+++ b/test/files/run/lambda-serialization.scala
@@ -0,0 +1,35 @@
+import java.io.{ByteArrayInputStream, ObjectInputStream, ObjectOutputStream, ByteArrayOutputStream}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ roundTrip
+ }
+
+ def roundTrip(): Unit = {
+ val c = new Capture("Capture")
+ val lambda = (p: Param) => ("a", p, c)
+ val reconstituted1 = serializeDeserialize(lambda).asInstanceOf[Object => Any]
+ val p = new Param
+ assert(reconstituted1.apply(p) == ("a", p, c))
+ val reconstituted2 = serializeDeserialize(lambda).asInstanceOf[Object => Any]
+ assert(reconstituted1.getClass == reconstituted2.getClass)
+
+ val reconstituted3 = serializeDeserialize(reconstituted1)
+ assert(reconstituted3.apply(p) == ("a", p, c))
+
+ val specializedLambda = (p: Int) => List(p, c).length
+ assert(serializeDeserialize(specializedLambda).apply(42) == 2)
+ assert(serializeDeserialize(serializeDeserialize(specializedLambda)).apply(42) == 2)
+ }
+
+ def serializeDeserialize[T <: AnyRef](obj: T) = {
+ val buffer = new ByteArrayOutputStream
+ val out = new ObjectOutputStream(buffer)
+ out.writeObject(obj)
+ val in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray))
+ in.readObject.asInstanceOf[T]
+ }
+}
+
+case class Capture(s: String) extends Serializable
+class Param
diff --git a/test/files/run/private-inline.flags b/test/files/run/private-inline.flags
index 00d3643fd4..c550fdce16 100644
--- a/test/files/run/private-inline.flags
+++ b/test/files/run/private-inline.flags
@@ -1 +1 @@
--optimise -Yinline-warnings
+-optimise -Yinline-warnings -Ybackend:GenASM
diff --git a/test/files/run/synchronized.check b/test/files/run/synchronized.check
index 9add05ea0c..dd9f4ef424 100644
--- a/test/files/run/synchronized.check
+++ b/test/files/run/synchronized.check
@@ -1,8 +1,3 @@
-#partest !-Ybackend:GenBCode
-warning: there were 14 inliner warnings; re-run with -Yinline-warnings for details
-#partest -Ybackend:GenBCode
-warning: there were 14 inliner warnings; re-run with -Yopt-warnings for details
-#partest
.|. c1.f1: OK
.|. c1.fi: OK
.|... c1.fv: OK
diff --git a/test/files/run/synchronized.scala b/test/files/run/synchronized.scala
index 1f0e32992b..077e9d02e8 100644
--- a/test/files/run/synchronized.scala
+++ b/test/files/run/synchronized.scala
@@ -1,3 +1,6 @@
+/*
+ * filter: inliner warnings; re-run with
+ */
import java.lang.Thread.holdsLock
import scala.collection.mutable.StringBuilder
diff --git a/test/files/run/t6102.check b/test/files/run/t6102.check
index aa3e6cc9e2..07378f5ed4 100644
--- a/test/files/run/t6102.check
+++ b/test/files/run/t6102.check
@@ -28,5 +28,10 @@
[running phase constopt on t6102.scala]
#partest
[running phase dce on t6102.scala]
+#partest !-Ybackend:GenBCode
[running phase jvm on icode]
+#partest -Ybackend:GenBCode
+[running phase jvm on t6102.scala]
+[running phase jvm on t6102.scala]
+#partest
hello
diff --git a/test/files/run/t8601-closure-elim.flags b/test/files/run/t8601-closure-elim.flags
index 2b5fd8a7b2..9158076b71 100644
--- a/test/files/run/t8601-closure-elim.flags
+++ b/test/files/run/t8601-closure-elim.flags
@@ -1 +1 @@
--optimize -Ydelambdafy:inline
+-optimize -Ydelambdafy:inline -Ybackend:GenASM
diff --git a/test/files/scalacheck/redblacktree.scala b/test/files/scalacheck/redblacktree.scala
index 871444a4b8..4ded37b35a 100644
--- a/test/files/scalacheck/redblacktree.scala
+++ b/test/files/scalacheck/redblacktree.scala
@@ -33,7 +33,7 @@ package scala.collection.immutable.redblacktree {
def mkTree(level: Int, parentIsBlack: Boolean = false, label: String = ""): Gen[Tree[String, Int]] =
if (level == 0) {
- value(null)
+ const(null)
} else {
for {
oddOrEven <- choose(0, 2)
diff --git a/test/junit/scala/collection/IteratorTest.scala b/test/junit/scala/collection/IteratorTest.scala
index d5389afd0c..1c1e50aed9 100644
--- a/test/junit/scala/collection/IteratorTest.scala
+++ b/test/junit/scala/collection/IteratorTest.scala
@@ -154,4 +154,14 @@ class IteratorTest {
results += (Stream from 1).toIterator.drop(10).toStream.drop(10).toIterator.next()
assertSameElements(List(1,1,21), results)
}
+ // SI-9332
+ @Test def spanExhaustsLeadingIterator(): Unit = {
+ def it = Iterator.iterate(0)(_ + 1).take(6)
+ val (x, y) = it.span(_ != 1)
+ val z = x.toList
+ assertEquals(1, z.size)
+ assertFalse(x.hasNext)
+ assertEquals(1, y.next)
+ assertFalse(x.hasNext) // was true, after advancing underlying iterator
+ }
}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala
new file mode 100644
index 0000000000..3a85f03da2
--- /dev/null
+++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala
@@ -0,0 +1,231 @@
+package scala.tools.nsc
+package backend.jvm
+package analysis
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+import scala.tools.asm.Opcodes._
+import org.junit.Assert._
+
+import CodeGenTools._
+import scala.tools.asm.tree.{AbstractInsnNode, MethodNode}
+import scala.tools.nsc.backend.jvm.BTypes._
+import scala.tools.partest.ASMConverters
+import ASMConverters._
+import scala.tools.testing.ClearAfterClass
+import scala.tools.nsc.backend.jvm.opt.BytecodeUtils._
+import AsmUtils._
+
+import scala.collection.convert.decorateAsScala._
+
+object NullnessAnalyzerTest extends ClearAfterClass.Clearable {
+ var noOptCompiler = newCompiler(extraArgs = "-Ybackend:GenBCode -Yopt:l:none")
+
+ def clear(): Unit = {
+ noOptCompiler = null
+ }
+}
+
+@RunWith(classOf[JUnit4])
+class NullnessAnalyzerTest extends ClearAfterClass {
+ ClearAfterClass.stateToClear = NullnessAnalyzerTest
+ val noOptCompiler = NullnessAnalyzerTest.noOptCompiler
+
+ def newNullnessAnalyzer(methodNode: MethodNode, classInternalName: InternalName = "C"): NullnessAnalyzer = {
+ val nullnessAnalyzer = new NullnessAnalyzer
+ nullnessAnalyzer.analyze(classInternalName, methodNode)
+ nullnessAnalyzer
+ }
+
+ /**
+ * Instructions that match `query` when textified.
+ * If `query` starts with a `+`, the next instruction is returned.
+ */
+ def findInstr(method: MethodNode, query: String): List[AbstractInsnNode] = {
+ val useNext = query(0) == '+'
+ val instrPart = if (useNext) query.drop(1) else query
+ val insns = method.instructions.iterator.asScala.find(i => textify(i) contains instrPart).toList
+ if (useNext) insns.map(_.getNext) else insns
+ }
+
+ def testNullness(analyzer: NullnessAnalyzer, method: MethodNode, query: String, index: Int, nullness: Nullness): Unit = {
+ for (i <- findInstr(method, query)) {
+ val r = analyzer.frameAt(i, method).getValue(index).nullness
+ assertTrue(s"Expected: $nullness, found: $r. At instr ${textify(i)}", nullness == r)
+ }
+ }
+
+ // debug / helper for writing tests
+ def showAllNullnessFrames(analyzer: NullnessAnalyzer, method: MethodNode): String = {
+ val instrLength = method.instructions.iterator.asScala.map(textify(_).length).max
+ val lines = for (i <- method.instructions.iterator.asScala) yield {
+ val f = analyzer.frameAt(i, method)
+ val frameString = {
+ if (f == null) "null"
+ else (0 until (f.getLocals + f.getStackSize)).iterator
+ .map(f.getValue(_).toString)
+ .map(s => "%8s".format(s))
+ .zipWithIndex.map({case (s, i) => s"$i: $s"})
+ .mkString(", ")
+ }
+ ("%"+ instrLength +"s: %s").format(textify(i), frameString)
+ }
+ lines.mkString("\n")
+ }
+
+ @Test
+ def showNullnessFramesTest(): Unit = {
+ val List(m) = compileMethods(noOptCompiler)("def f = this.toString")
+
+ // NOTE: the frame for an instruction represents the state *before* executing that instr.
+ // So in the frame for `ALOAD 0`, the stack is still empty.
+
+ val res =
+ """ L0: 0: NotNull
+ | LINENUMBER 1 L0: 0: NotNull
+ | ALOAD 0: 0: NotNull
+ |INVOKEVIRTUAL java/lang/Object.toString ()Ljava/lang/String;: 0: NotNull, 1: NotNull
+ | ARETURN: 0: NotNull, 1: Unknown1
+ | L0: null""".stripMargin
+ assertEquals(showAllNullnessFrames(newNullnessAnalyzer(m), m), res)
+ }
+
+ @Test
+ def thisNonNull(): Unit = {
+ val List(m) = compileMethods(noOptCompiler)("def f = this.toString")
+ val a = newNullnessAnalyzer(m)
+ testNullness(a, m, "ALOAD 0", 0, NotNull)
+ }
+
+ @Test
+ def instanceMethodCall(): Unit = {
+ val List(m) = compileMethods(noOptCompiler)("def f(a: String) = a.trim")
+ val a = newNullnessAnalyzer(m)
+ testNullness(a, m, "INVOKEVIRTUAL java/lang/String.trim", 1, Unknown)
+ testNullness(a, m, "ARETURN", 1, NotNull)
+ }
+
+ @Test
+ def constructorCall(): Unit = {
+ val List(m) = compileMethods(noOptCompiler)("def f = { val a = new Object; a.toString }")
+ val a = newNullnessAnalyzer(m)
+
+ // for reference, the output of showAllNullnessFrames(a, m) - note that the frame represents the state *before* executing the instr.
+ // NEW java/lang/Object: 0: NotNull, 1: Unknown
+ // DUP: 0: NotNull, 1: Unknown, 2: Unknown
+ // INVOKESPECIAL java/lang/Object.<init>: 0: NotNull, 1: Unknown, 2: Unknown, 3: Unknown
+ // ASTORE 1: 0: NotNull, 1: Unknown, 2: NotNull
+ // ALOAD 1: 0: NotNull, 1: NotNull
+ // INVOKEVIRTUAL java/lang/Object.toString: 0: NotNull, 1: NotNull, 2: NotNull
+ // ARETURN: 0: NotNull, 1: NotNull, 2: Unknown
+
+ for ((insn, index, nullness) <- List(
+ ("+NEW", 2, Unknown), // new value at slot 2 on the stack
+ ("+DUP", 3, Unknown),
+ ("+INVOKESPECIAL java/lang/Object", 2, NotNull), // after calling the initializer on 3, the value at 2 becomes NotNull
+ ("ASTORE 1", 1, Unknown), // before the ASTORE 1, nullness of the value in local 1 is Unknown
+ ("+ASTORE 1", 1, NotNull), // after storing the value at 2 in local 1, the local 1 is NotNull
+ ("+ALOAD 1", 2, NotNull), // loading the value 1 puts a NotNull value on the stack (at 2)
+ ("+INVOKEVIRTUAL java/lang/Object.toString", 2, Unknown) // nullness of value returned by `toString` is Unknown
+ )) testNullness(a, m, insn, index, nullness)
+ }
+
+ @Test
+ def explicitNull(): Unit = {
+ val List(m) = compileMethods(noOptCompiler)("def f = { var a: Object = null; a }")
+ val a = newNullnessAnalyzer(m)
+ for ((insn, index, nullness) <- List(
+ ("+ACONST_NULL", 2, Null),
+ ("+ASTORE 1", 1, Null),
+ ("+ALOAD 1", 2, Null)
+ )) testNullness(a, m, insn, index, nullness)
+ }
+
+ @Test
+ def stringLiteralsNotNull(): Unit = {
+ val List(m) = compileMethods(noOptCompiler)("""def f = { val a = "hi"; a.trim }""")
+ val a = newNullnessAnalyzer(m)
+ testNullness(a, m, "+ASTORE 1", 1, NotNull)
+ }
+
+ @Test
+ def newArraynotNull() {
+ val List(m) = compileMethods(noOptCompiler)("def f = { val a = new Array[Int](2); a(0) }")
+ val a = newNullnessAnalyzer(m)
+ testNullness(a, m, "+NEWARRAY T_INT", 2, NotNull) // new array on stack
+ testNullness(a, m, "+ASTORE 1", 1, NotNull) // local var (a)
+ }
+
+ @Test
+ def aliasBranching(): Unit = {
+ val code =
+ """def f(o: Object) = {
+ | var a: Object = o // a and o are aliases
+ | var b: Object = null
+ | var c: Object = null
+ | var d: Object = o
+ | if ("".trim == "") {
+ | b = o
+ | c = o // a, o, b, aliases
+ | d = null
+ | } else {
+ | b = a // a, o, b aliases
+ | d = null
+ | }
+ | b.toString // a, o, b aliases (so they become NotNull), but not c
+ | // d is null here, assinged in both branches.
+ |}
+ """.stripMargin
+ val List(m) = compileMethods(noOptCompiler)(code)
+ val a = newNullnessAnalyzer(m)
+
+ val trim = "INVOKEVIRTUAL java/lang/String.trim"
+ val toSt = "INVOKEVIRTUAL java/lang/Object.toString"
+ val end = s"+$toSt"
+ for ((insn, index, nullness) <- List(
+ (trim, 0, NotNull), // this
+ (trim, 1, Unknown), // parameter o
+ (trim, 2, Unknown), // a
+ (trim, 3, Null), // b
+ (trim, 4, Null), // c
+ (trim, 5, Unknown), // d
+
+ (toSt, 2, Unknown), // a, still the same
+ (toSt, 3, Unknown), // b, was re-assinged in both branches to Unknown
+ (toSt, 4, Unknown), // c, was re-assigned in one branch to Unknown
+ (toSt, 5, Null), // d, was assigned to null in both branches
+
+ (end, 2, NotNull), // a, NotNull (alias of b)
+ (end, 3, NotNull), // b, receiver of toString
+ (end, 4, Unknown), // c, no change (not an alias of b)
+ (end, 5, Null) // d, no change
+ )) testNullness(a, m, insn, index, nullness)
+ }
+
+ @Test
+ def testInstanceOf(): Unit = {
+ val code =
+ """def f(a: Object) = {
+ | val x = a
+ | x.isInstanceOf[Throwable] // x and a remain unknown - INSTANCEOF doesn't throw a NPE on null
+ | x.toString // x and a are not null
+ | a.asInstanceOf[String].trim // the stack value (LOAD of local a) is still not-null after the CHECKCAST
+ |}
+ """.stripMargin
+ val List(m) = compileMethods(noOptCompiler)(code)
+ val a = newNullnessAnalyzer(m)
+
+ val instof = "+INSTANCEOF"
+ val tost = "+INVOKEVIRTUAL java/lang/Object.toString"
+ val trim = "INVOKEVIRTUAL java/lang/String.trim"
+
+ for ((insn, index, nullness) <- List(
+ (instof, 1, Unknown), // a after INSTANCEOF
+ (instof, 2, Unknown), // x after INSTANCEOF
+ (tost, 1, NotNull),
+ (tost, 2, NotNull),
+ (trim, 3, NotNull) // receiver at `trim`
+ )) testNullness(a, m, insn, index, nullness)
+ }
+}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
index 0fc3601603..b8c5f85c49 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
@@ -975,4 +975,20 @@ class InlinerTest extends ClearAfterClass {
val List(c) = compile(code)
assertInvoke(getSingleMethod(c, "t"), "java/lang/Error", "<init>")
}
+
+ @Test
+ def noRedunantNullChecks(): Unit = {
+ val code =
+ """class C {
+ | @inline final def f: String = "hai!"
+ | def t(c: C) = {c.f; c.f} // null check on the first, but not the second
+ |}
+ """.stripMargin
+
+ val List(c) = compile(code)
+ val t = getSingleMethod(c, "t").instructions
+ assertNoInvoke(t)
+ assert(2 == t.collect({case Ldc(_, "hai!") => }).size) // twice the body of f
+ assert(1 == t.collect({case Jump(IFNONNULL, _) => }).size) // one single null check
+ }
}
diff --git a/test/scaladoc/run/SI-8210.check b/test/scaladoc/run/SI-8210.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-8210.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-8210.scala b/test/scaladoc/run/SI-8210.scala
new file mode 100644
index 0000000000..3bd818473f
--- /dev/null
+++ b/test/scaladoc/run/SI-8210.scala
@@ -0,0 +1,24 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+ override def code = """
+object Foo {
+ trait Config {
+ /** The bar obviously. */
+ def bar: Int
+ }
+ class ConfigBuilder extends Config {
+ /** @inheritdoc
+ *
+ * The default value is 1234.
+ */
+ var bar: Int = 1234
+ }
+}
+ """
+
+ def scaladocSettings = ""
+
+ def testModel(root: Package) = ()
+}