Skip to content

Commit 64cbe13

Browse files
authored
Merge pull request scala#6001 from szeiger/merge/2.12.x-to-2.13.x-2017020
Merge/2.12.x to 2.13.x 2017020 [ci: last-only]
2 parents a75bdd7 + ce1484d commit 64cbe13

File tree

24 files changed

+207
-78
lines changed

24 files changed

+207
-78
lines changed

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ lazy val scalacheck = project.in(file("test") / "scalacheck")
542542
.settings(disableDocs)
543543
.settings(disablePublishing)
544544
.settings(
545-
fork in Test := true,
545+
fork in Test := false,
546546
javaOptions in Test += "-Xss1M",
547547
libraryDependencies ++= Seq(scalacheckDep),
548548
unmanagedSourceDirectories in Compile := Nil,

src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,10 +1360,14 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
13601360
private def visitInvokeDynamicInsnLMF(jmethod: MethodNode, samName: String, invokedType: String, samMethodType: asm.Type,
13611361
implMethodHandle: asm.Handle, instantiatedMethodType: asm.Type,
13621362
serializable: Boolean, markerInterfaces: Seq[asm.Type]) = {
1363-
import java.lang.invoke.LambdaMetafactory.{FLAG_MARKERS, FLAG_SERIALIZABLE}
1363+
import java.lang.invoke.LambdaMetafactory.{FLAG_MARKERS, FLAG_SERIALIZABLE, FLAG_BRIDGES}
1364+
// scala/bug#10334: make sure that a lambda object for `T => U` has a method `apply(T)U`, not only the `(Object)Object`
1365+
// version. Using the lambda a structural type `{def apply(t: T): U}` causes a reflective lookup for this method.
1366+
val needsBridge = samMethodType != instantiatedMethodType
1367+
val bridges = if (needsBridge) Seq(Int.box(1), instantiatedMethodType) else Nil
13641368
def flagIf(b: Boolean, flag: Int): Int = if (b) flag else 0
1365-
val flags = FLAG_MARKERS | flagIf(serializable, FLAG_SERIALIZABLE)
1366-
val bsmArgs = Seq(samMethodType, implMethodHandle, instantiatedMethodType, Int.box(flags), Int.box(markerInterfaces.length)) ++ markerInterfaces
1369+
val flags = FLAG_MARKERS | flagIf(serializable, FLAG_SERIALIZABLE) | flagIf(needsBridge, FLAG_BRIDGES)
1370+
val bsmArgs = Seq(samMethodType, implMethodHandle, instantiatedMethodType, Int.box(flags), Int.box(markerInterfaces.length)) ++ markerInterfaces ++ bridges
13671371
jmethod.visitInvokeDynamicInsn(samName, invokedType, lambdaMetaFactoryAltMetafactoryHandle, bsmArgs: _*)
13681372
}
13691373

src/library/scala/sys/process/ProcessImpl.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ private[process] trait ProcessImpl {
147147
throw err
148148
}
149149
runInterruptible {
150+
source.join()
150151
val exit1 = first.exitValue()
151152
val exit2 = second.exitValue()
152153
// Since file redirection (e.g. #>) is implemented as a piped process,

src/reflect/scala/reflect/internal/Symbols.scala

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2375,16 +2375,14 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
23752375

23762376
/** Returns all symbols overridden by this symbol. */
23772377
final def allOverriddenSymbols: List[Symbol] = {
2378-
@tailrec
2379-
def loop(xs: List[Symbol], result: List[Symbol]): List[Symbol] = xs match {
2380-
case Nil => result
2381-
case x :: xs =>
2382-
overriddenSymbol(x) match {
2383-
case NoSymbol => loop(xs, result)
2384-
case sym => loop(xs, sym :: result)
2385-
}
2386-
}
2387-
if (isOverridingSymbol) loop(owner.ancestors, Nil) else Nil
2378+
if (isOverridingSymbol) {
2379+
// performance sensitive
2380+
val builder = List.newBuilder[Symbol]
2381+
for (o <- owner.ancestors) {
2382+
overriddenSymbol(o).andAlso(builder += _)
2383+
}
2384+
builder.result()
2385+
} else Nil
23882386
}
23892387

23902388
/** Equivalent to allOverriddenSymbols.nonEmpty, but more efficient. */

test/files/run/t10334.scala

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import scala.language.reflectiveCalls
2+
3+
object Test {
4+
def main(args: Array[String]): Unit = {
5+
assert(t1 == "hi")
6+
assert(t2 == 1)
7+
t3()
8+
}
9+
10+
def t1: Object = {
11+
val f: { def apply(s: String): Object } = (x: String) => x
12+
f("hi")
13+
}
14+
15+
def t2: Int = {
16+
def byName(b: => Int): Int = b
17+
def namer[A, B](f: A => B): (A => B) { def apply(i: A): B } = f
18+
19+
val namedFunction = namer(byName _)
20+
namedFunction(1)
21+
}
22+
23+
// Not sure how to fix this one.. https://github.com/scala/bug/issues/10334
24+
def t3(): Unit = {
25+
val f1 = new T[A] {
26+
def m(x: A) = "f1-a"
27+
def m(x: B) = "f1-b"
28+
// the m(Object)Object bridge method invokes (A)Object
29+
}
30+
31+
val f2 = new T[B] {
32+
def m(x: A) = "f2-a"
33+
def m(x: B) = "f2-b"
34+
// the (Object)Object bridge method invokes (B)Object
35+
}
36+
37+
val g1: T[C] = f1
38+
val g2: T[C] = f2
39+
40+
assert(g1.m(new C) == "f1-a")
41+
assert(g2.m(new C) == "f2-b")
42+
43+
val s1: { def m(s: C): Object } = g1
44+
val s2: { def m(s: C): Object } = g2
45+
46+
// the reflective lookup doesn't find `m(C)Object`
47+
try {
48+
s1.m(new C) // should invoke `m(A)Object`
49+
throw new Error()
50+
} catch {
51+
case _: java.lang.NoSuchMethodException =>
52+
}
53+
54+
// the reflective lookup doesn't find `m(C)Object`
55+
try {
56+
s2.m(new C) // should invoke `m(B)Object`
57+
throw new Error()
58+
} catch {
59+
case _: java.lang.NoSuchMethodException =>
60+
}
61+
}
62+
}
63+
64+
class A
65+
class B extends A
66+
class C extends B
67+
68+
trait T[-A] {
69+
def m(a: A): Object
70+
}

test/files/run/t10334b/A.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public interface A<T> {
2+
public String apply(T s);
3+
public default String apply(String s) { return "hi"; }
4+
}

test/files/run/t10334b/Test.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
trait T[T] { def apply(x: Int): T }
2+
class C(val x: Int) extends AnyVal { override def toString = s"$x" }
3+
4+
object Test {
5+
def main(args: Array[String]): Unit = {
6+
{
7+
val t: A[String] = s => s
8+
assert((t: A[_]).apply("there") == "there")
9+
}
10+
{
11+
var u = 0
12+
val t: T[Unit] = x => u = x
13+
t.apply(1)
14+
assert(u == 1)
15+
}
16+
{
17+
val t: T[C] = x => new C(x)
18+
assert(t.apply(1) == new C(1))
19+
}
20+
}
21+
}

test/junit/scala/sys/process/PipedProcessTest.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import java.lang.reflect.InvocationTargetException
99
import scala.concurrent.{Await, Future}
1010
import scala.concurrent.ExecutionContext.Implicits.global
1111
import scala.util.control.Exception.ignoring
12+
import org.junit.Assert.assertEquals
1213

1314
// Each test normally ends in a moment, but for failure cases, waits two seconds.
1415
// scala/bug#7350, scala/bug#8768
@@ -94,6 +95,24 @@ class PipedProcessTest {
9495
assert(b.destroyCount == 0)
9596
}
9697

98+
@Test
99+
def shouldSyncRunAndExitValue() {
100+
val io = BasicIO(false, ProcessLogger(_ => ()))
101+
val source = new PipeSourceMock {
102+
override def run(): Unit = {
103+
Thread.sleep(5) //used to simulate the block
104+
}
105+
}
106+
val sink = new PipeSinkMock
107+
val a = new ProcessMock(error = false)
108+
val b = new ProcessMock(error = false)
109+
val p = new PipedProcesses(new ProcessBuilderMock(a, error = false), new ProcessBuilderMock(b, error = false), io, false)
110+
111+
p.callRunAndExitValue(source, sink)
112+
113+
assertEquals(false, source.isAlive)
114+
}
115+
97116
// PipedProcesses must release resources when b.run() failed
98117
@Test
99118
def bFailed() {

test/scalacheck/scala/tools/nsc/scaladoc/HtmlFactoryTest.scala

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ package scala.tools.nsc.scaladoc
22

33
import org.scalacheck._
44
import org.scalacheck.Prop._
5-
65
import java.net.{URLClassLoader, URLDecoder}
6+
import java.nio.file.{Files, Paths}
7+
78
import scala.collection.mutable
89
import scala.xml.NodeSeq
910

@@ -32,22 +33,11 @@ object HtmlFactoryTest extends Properties("HtmlFactory") {
3233
import scala.tools.nsc.doc.{DocFactory, Settings}
3334
import scala.tools.nsc.doc.html.HtmlFactory
3435

35-
def getClasspath = {
36-
// these things can be tricky
37-
// this test previously relied on the assumption that the current thread's classloader is an url classloader and contains all the classpaths
38-
// does partest actually guarantee this? to quote Leonard Nimoy: The answer, of course, is no.
39-
// this test _will_ fail again some time in the future.
40-
// Footnote: java.lang.ClassCastException: org.apache.tools.ant.loader.AntClassLoader5 cannot be cast to java.net.URLClassLoader
41-
val loader = Thread.currentThread.getContextClassLoader.asInstanceOf[URLClassLoader]
42-
val paths = loader.getURLs.map(u => URLDecoder.decode(u.getPath))
43-
paths mkString java.io.File.pathSeparator
44-
}
45-
4636
def createFactory = {
4737
val settings = new Settings({Console.err.println(_)})
4838
settings.scaladocQuietRun = true
4939
settings.nowarn.value = true
50-
settings.classpath.value = getClasspath
40+
SettingsUtil.configureClassAndSourcePath(settings)
5141
settings.docAuthor.value = true
5242

5343
val reporter = new scala.tools.nsc.reporters.ConsoleReporter(settings)
@@ -57,7 +47,8 @@ object HtmlFactoryTest extends Properties("HtmlFactory") {
5747
def createTemplates(basename: String): collection.Map[String, NodeSeq] = {
5848
val result = mutable.Map[String, NodeSeq]()
5949

60-
createFactory.makeUniverse(Left(List(RESOURCES+basename))) match {
50+
val path: String = SettingsUtil.checkoutRoot.resolve(RESOURCES).resolve(basename).toAbsolutePath.toString
51+
createFactory.makeUniverse(Left(List(path))) match {
6152
case Some(universe) => {
6253
new HtmlFactory(universe, new ScalaDocReporter(universe.settings)).writeTemplates((page) => {
6354
result += (page.absoluteLinkTo(page.path) -> page.body)
@@ -320,7 +311,7 @@ object HtmlFactoryTest extends Properties("HtmlFactory") {
320311
}
321312

322313
property("scala/bug#4421") = {
323-
createTemplate("SI_4421.scala") match {
314+
createTemplate("t4421.scala") match {
324315
case node: scala.xml.Node => {
325316
val html = node.toString
326317
html.contains(">Example:") && html.contains(">Note<")
@@ -330,7 +321,7 @@ object HtmlFactoryTest extends Properties("HtmlFactory") {
330321
}
331322

332323
property("scala/bug#4589") = {
333-
createTemplate("SI_4589.scala") match {
324+
createTemplate("t4589.scala") match {
334325
case node: scala.xml.Node => {
335326
val html = node.toString
336327
html.contains(">x0123456789: <") &&
@@ -341,7 +332,7 @@ object HtmlFactoryTest extends Properties("HtmlFactory") {
341332
}
342333

343334
property("scala/bug#4714: Should decode symbolic type alias name.") = {
344-
createTemplate("SI_4715.scala") match {
335+
createTemplate("t4715.scala") match {
345336
case node: scala.xml.Node => {
346337
val html = node.toString
347338
html.contains(">:+:<")
@@ -351,7 +342,7 @@ object HtmlFactoryTest extends Properties("HtmlFactory") {
351342
}
352343

353344
property("scala/bug#4287: Default arguments of synthesized constructor") = {
354-
val files = createTemplates("SI_4287.scala")
345+
val files = createTemplates("t4287.scala")
355346

356347
files("ClassWithSugar.html") match {
357348
case node: scala.xml.Node => {
@@ -362,53 +353,53 @@ object HtmlFactoryTest extends Properties("HtmlFactory") {
362353
}
363354

364355
property("scala/bug#4507: Default arguments of synthesized constructor") = {
365-
createTemplate("SI_4507.scala") match {
356+
createTemplate("t4507.scala") match {
366357
case node: scala.xml.Node =>
367358
! node.toString.contains("<li>returns silently when evaluating true and true</li>")
368359
case _ => false
369360
}
370361
}
371362

372363
property("scala/bug#4898: Use cases and links should not crash scaladoc") = {
373-
createTemplate("SI_4898.scala")
364+
createTemplate("t4898.scala")
374365
true
375366
}
376367

377368
property("scala/bug#5054: Use cases should override their original members") =
378-
checkText("SI_5054_q1.scala")(
369+
checkText("t5054_q1.scala")(
379370
(None,"""def test(): Int""", true)
380371
//Disabled because the full signature is now displayed
381372
//(None, """def test(implicit lost: Int): Int""", false)
382373
)
383374

384375
property("scala/bug#5054: Use cases should keep their flags - final should not be lost") =
385-
checkText("SI_5054_q2.scala")((None, """final def test(): Int""", true))
376+
checkText("t5054_q2.scala")((None, """final def test(): Int""", true))
386377

387378
property("scala/bug#5054: Use cases should keep their flags - implicit should not be lost") =
388-
checkText("SI_5054_q3.scala")((None, """implicit def test(): Int""", true))
379+
checkText("t5054_q3.scala")((None, """implicit def test(): Int""", true))
389380

390381
property("scala/bug#5054: Use cases should keep their flags - real abstract should not be lost") =
391-
checkText("SI_5054_q4.scala")((None, """abstract def test(): Int""", true))
382+
checkText("t5054_q4.scala")((None, """abstract def test(): Int""", true))
392383

393384
property("scala/bug#5054: Use cases should keep their flags - traits should not be affected") =
394-
checkText("SI_5054_q5.scala")((None, """def test(): Int""", true))
385+
checkText("t5054_q5.scala")((None, """def test(): Int""", true))
395386

396387
property("scala/bug#5054: Use cases should keep their flags - traits should not be affected") =
397-
checkText("SI_5054_q6.scala")((None, """abstract def test(): Int""", true))
388+
checkText("t5054_q6.scala")((None, """abstract def test(): Int""", true))
398389

399390
property("scala/bug#5054: Use case individual signature test") =
400-
checkText("SI_5054_q7.scala")(
391+
checkText("t5054_q7.scala")(
401392
(None, """abstract def test2(explicit: Int): Int [use case] This takes the explicit value passed.""", true),
402393
(None, """abstract def test1(): Int [use case] This takes the implicit value in scope.""", true)
403394
)
404395

405396
property("scala/bug#5287: Display correct \"Definition classes\"") =
406-
checkText("SI_5287.scala")(
397+
checkText("t5287.scala")(
407398
(None,
408399
"""def method(): Int
409400
[use case] The usecase explanation
410401
[use case] The usecase explanation
411-
Definition Classes SI_5287 SI_5287_B SI_5287_A""", true)
402+
Definition Classes t5287 t5287_B t5287_A""", true)
412403
) // the explanation appears twice, as small comment and full comment
413404

414405
property("Comment inheritance: Correct comment inheritance for overriding") =
@@ -578,31 +569,31 @@ object HtmlFactoryTest extends Properties("HtmlFactory") {
578569
property("Comment inheritance: Correct explicit inheritance in corner cases") =
579570
checkText("inheritdoc-corner-cases.scala")(
580571
(Some("D"),
581-
"""def hello1: Int
572+
"""def hello1: Int
582573
Inherited: Hello 1 comment
583574
Inherited: Hello 1 comment
584575
Definition Classes D → A
585576
""", true),
586577
(Some("D"),
587-
"""def hello2: Int
578+
"""def hello2: Int
588579
Inherited: Hello 2 comment
589580
Inherited: Hello 2 comment
590581
Definition Classes D → B
591582
""", true),
592583
(Some("G"),
593-
"""def hello1: Int
584+
"""def hello1: Int
594585
Inherited: Hello 1 comment
595586
Inherited: Hello 1 comment
596587
Definition Classes G → D → A
597588
""", true),
598589
(Some("G"),
599-
"""def hello2: Int
590+
"""def hello2: Int
600591
Inherited: Hello 2 comment
601592
Inherited: Hello 2 comment
602593
Definition Classes G → D → B
603594
""", true),
604595
(Some("I"),
605-
"""def hello1(i: Int): Unit
596+
"""def hello1(i: Int): Unit
606597
[use case] Inherited: Hello 1 comment
607598
[use case] Inherited: Hello 1 comment
608599
Definition Classes I → G → D → A

0 commit comments

Comments
 (0)