Skip to content

Commit

Permalink
Fast-track deprecating auto-application
Browse files Browse the repository at this point in the history
Auto-application is dropped in Scala 3:
https://dotty.epfl.ch/docs/reference/dropped-features/auto-apply.html

So it must be deprecated in 2.13 first.

Also, AFAICT Object_clone is Java-defined:

    $ qscala
    Welcome to Scala 2.13.2-20200325-150327-bc1cad4 (OpenJDK 64-Bit Server VM, Java 11.0.6).
    Type in expressions for evaluation. Or try :help.

    scala> :power
    Power mode enabled. :phase is at typer.
    import scala.tools.nsc._, intp.global._, definitions._
    Try :help or completions for vals._ and power._

    scala> Object_clone.isJavaDefined
    val res0: Boolean = true
  • Loading branch information
dwijnand authored and SethTisue committed Jun 1, 2020
1 parent 2bea2c1 commit c900df8
Show file tree
Hide file tree
Showing 126 changed files with 513 additions and 505 deletions.
2 changes: 1 addition & 1 deletion project/GenerateFunctionConverters.scala
Expand Up @@ -348,7 +348,7 @@ object GenerateFunctionConverters {

def sameText(f: java.io.File, text: String): Boolean = {
val x = scala.io.Source.fromFile(f)
val lines = try { x.getLines.toVector } finally { x.close }
val lines = try { x.getLines().toVector } finally { x.close }
// work around scala/bug#11125
lines.iterator.filter(_.nonBlank) == Predef.augmentString(text).lines.filter(_.nonBlank)
}
Expand Down
4 changes: 2 additions & 2 deletions spec/03-types.md
Expand Up @@ -685,7 +685,7 @@ An overloaded type consisting of type alternatives $T_1 \commadots T_n (n \geq 2
###### Example
```scala
def println: Unit
def println(): Unit
def println(s: String): Unit = $\ldots$
def println(x: Float): Unit = $\ldots$
def println(x: Float, width: Int): Unit = $\ldots$
Expand All @@ -694,7 +694,7 @@ def println[A](x: A)(tostring: A => String): Unit = $\ldots$
define a single function `println` which has an overloaded
type.
```
println: => Unit $\overload$
println: () Unit $\overload$
(String) Unit $\overload$
(Float) Unit $\overload$
(Float, Int) Unit $\overload$
Expand Down
26 changes: 11 additions & 15 deletions src/compiler/scala/tools/nsc/typechecker/Typers.scala
Expand Up @@ -974,27 +974,23 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}

def matchNullaryLoosely: Boolean = {
def test(sym: Symbol) =
sym.isJavaDefined ||
sym.owner == AnyClass ||
sym == Object_clone
def test(sym: Symbol) = sym.isJavaDefined || sym.owner == AnyClass
test(meth) || meth.overrides.exists(test)
}
// (4.2) condition for auto-application by -Xsource level

// (4.2) condition for auto-application
//
// until 3.0: none (assuming condition for (4.3) was not met)
// in 3.0: `meth.isJavaDefined`
// (TODO decide -- currently the condition is more involved to give slack to Scala methods overriding Java-defined ones;
// I think we should resolve that by introducing slack in overriding e.g. a Java-defined `def toString()` by a Scala-defined `def toString`.
// This also works better for dealing with accessors overriding Java-defined methods. The current strategy in methodSig is problematic:
// > // Add a () parameter section if this overrides some method with () parameters
// > val vparamSymssOrEmptyParamsFromOverride =
// This means an accessor that overrides a Java-defined method gets a MethodType instead of a NullaryMethodType, which breaks lots of assumptions about accessors)
// Currently the condition is more involved to give slack to Scala methods overriding Java-defined ones;
// I (moors) think we should resolve that by introducing slack in overriding e.g. a Java-defined `def toString()` by a Scala-defined `def toString`.
// This also works better for dealing with accessors overriding Java-defined methods. The current strategy in methodSig is problematic:
// > // Add a () parameter section if this overrides some method with () parameters
// > val vparamSymssOrEmptyParamsFromOverride =
// This means an accessor that overrides a Java-defined method gets a MethodType instead of a NullaryMethodType, which breaks lots of assumptions about accessors)
def checkCanAutoApply(): Boolean = {
if (sourceLevel3 && !isPastTyper && !matchNullaryLoosely) {
if (!isPastTyper && !matchNullaryLoosely) {
context.deprecationWarning(tree.pos, NoSymbol, s"Auto-application to `()` is deprecated. Supply the empty argument list `()` explicitly to invoke method ${meth.decodedName},\n" +
s"or remove the empty argument list from its definition (Java-defined methods are exempt).\n"+
s"In Scala 3, an unapplied method like this will be eta-expanded into a function.", "3.0.0")
s"In Scala 3, an unapplied method like this will be eta-expanded into a function.", "2.13.3")
}
true
}
Expand Down
2 changes: 1 addition & 1 deletion src/library/scala/collection/Iterator.scala
Expand Up @@ -40,7 +40,7 @@ import scala.runtime.Statics
* {{{
* def f[A](it: Iterator[A]) = {
* if (it.hasNext) { // Safe to reuse "it" after "hasNext"
* it.next // Safe to reuse "it" after "next"
* it.next() // Safe to reuse "it" after "next"
* val remainder = it.drop(2) // it is *not* safe to use "it" again after this line!
* remainder.take(2) // it is *not* safe to use "remainder" after this line!
* } else it
Expand Down
2 changes: 1 addition & 1 deletion src/library/scala/util/control/Exception.scala
Expand Up @@ -60,7 +60,7 @@ import scala.language.implicitConversions
* def printUrl(url: String) : Unit = {
* val con = new URL(url) openConnection()
* val source = scala.io.Source.fromInputStream(con.getInputStream())
* source.getLines.foreach(println)
* source.getLines().foreach(println)
* }
*
* val badUrl = "htt/xx"
Expand Down
6 changes: 3 additions & 3 deletions src/manual/scala/tools/docutil/EmitManPage.scala
Expand Up @@ -70,9 +70,9 @@ object EmitManPage {
for (d <- definitions) {
out println ".TP"
emitText(d.term)
out.println
out.println()
emitText(d.description)
if (n > 1) { out.println; n -= 1 }
if (n > 1) { out.println(); n -= 1 }
}

case Link(label, url) =>
Expand All @@ -88,7 +88,7 @@ object EmitManPage {
case TextParagraph(text) =>
out println ".PP"
emitText(text)
out.println
out.println()

case BlockQuote(text) =>
out println ".TP"
Expand Down
Expand Up @@ -31,7 +31,7 @@ class VectorIterationBenchmark {
var i = 0
val it = value.iterator
while (i < size) {
bh.consume(it.next)
bh.consume(it.next())
i += 1
}
}
Expand Down
Expand Up @@ -27,7 +27,7 @@ class BitSetIteratorBenchmark {
@Benchmark def iterateAll(): Unit = {
var sum = 0
val it = bs.iterator
while (it.hasNext) sum += it.next
while (it.hasNext) sum += it.next()
}

}
4 changes: 2 additions & 2 deletions test/files/jvm/annotations/Test_2.scala
Expand Up @@ -120,15 +120,15 @@ object Test4 {
anns foreach printSourceAnnotation
if (anns.length > 0) {
println(target)
println
println()
}
}
def printParamSourceAnnotations(target: { def getParameterAnnotations(): Array[Array[Annotation]] }): Unit = {
val anns = target.getParameterAnnotations().flatten
anns foreach printSourceAnnotation
if (anns.length > 0) {
println(target)
println
println()
}
}
printSourceAnnotations(classOf[Foo1])
Expand Down
2 changes: 1 addition & 1 deletion test/files/jvm/console.scala
Expand Up @@ -6,7 +6,7 @@ object Test extends App {
print(true)
print(1)
print(1.0)
flush
flush()
println("..")
println(1)
printf("Argument nr. %d has value %1.2f\n",
Expand Down
2 changes: 1 addition & 1 deletion test/files/jvm/future-spec/PromiseTests.scala
Expand Up @@ -104,7 +104,7 @@ class PromiseTests extends MinimalScalaTest {
"not be completable with a completed Promise" in {
{
val p = Promise[String]().failure(new RuntimeException("unbr0ken"))
p.tryCompleteWith(Promise[String].failure(new Exception("br0ken")).future)
p.tryCompleteWith(Promise[String]().failure(new Exception("br0ken")).future)
intercept[RuntimeException] {
Await.result(p.future, defaultTimeout)
}.getMessage mustBe ("unbr0ken")
Expand Down
8 changes: 4 additions & 4 deletions test/files/jvm/scala-concurrent-tck.scala
Expand Up @@ -117,15 +117,15 @@ class FutureCallbacks extends TestBase {
}

def testThatNestedCallbacksDoNotYieldStackOverflow(): Unit = {
val promise = Promise[Int]
val promise = Promise[Int]()
(0 to 10000).map(Future(_)).foldLeft(promise.future)((pf, f) => f.flatMap(i => pf))
promise.success(-1)
}

def stressTestNumberofCallbacks(): Unit = once {
done =>
val promise = Promise[Unit]
val otherPromise = Promise[Unit]
val promise = Promise[Unit]()
val otherPromise = Promise[Unit]()
def attachMeaninglessCallbacksTo[T](f: Future[T]): Future[T] = {
(1 to 20000).foreach(_ => f.onComplete(_ => ()))
f
Expand Down Expand Up @@ -359,7 +359,7 @@ def testTransformFailure(): Unit = once {
def testFlatMapDelayed(): Unit = once {
done =>
val f = Future { 5 }
val p = Promise[Int]
val p = Promise[Int]()
val g = f flatMap { _ => p.future }
g onComplete {
case Success(x) => done(x == 10)
Expand Down
2 changes: 1 addition & 1 deletion test/files/jvm/serialization.scala
Expand Up @@ -531,6 +531,6 @@ object Test10_util {
{
val random = new Random(345)
val random2: Random = read(write(random))
rep(5) { assert(random.nextInt == random2.nextInt) }
rep(5) { assert(random.nextInt() == random2.nextInt()) }
}
}
2 changes: 1 addition & 1 deletion test/files/jvm/throws-annot-from-java.check
Expand Up @@ -17,7 +17,7 @@ scala> :paste
println("atp.typeParams.isEmpty: " + atp.typeParams.isEmpty)
println(throwsAnn)
}
println
println()

{
val method = clazz.info.member(newTermName("bar"))
Expand Down
2 changes: 1 addition & 1 deletion test/files/jvm/throws-annot-from-java/Test_3.scala
Expand Up @@ -13,7 +13,7 @@ object Test extends ReplTest {
println("atp.typeParams.isEmpty: " + atp.typeParams.isEmpty)
println(throwsAnn)
}
println
println()
{
val method = clazz.info.member(newTermName("bar"))
Expand Down
16 changes: 8 additions & 8 deletions test/files/jvm/typerep.scala
Expand Up @@ -49,7 +49,7 @@ object testPrimitives {
println(getType("abc"))
println(getType(())) // Unit
println(getType(classOf[Int])) // Class
println
println()
}

object testOptions {
Expand All @@ -62,7 +62,7 @@ object testOptions {
println(getType(None: Option[Int]))
val y: Option[Int] = None
println(getType(y))
println
println()
}

object testLists {
Expand All @@ -71,7 +71,7 @@ object testLists {
println(getType(List(List(3))))
println(getType(Nil: List[Int]))
println(getType(List(1, "abc")))
println
println()
}

object testArrays {
Expand All @@ -81,7 +81,7 @@ object testArrays {
println(getType(List(1).toArray))
println(getType(List[Int]().toArray))
println(getType(Array(3).drop(1).toArray)) // empty
println
println()
}

object testTuples {
Expand All @@ -90,7 +90,7 @@ object testTuples {
println(getType(((3, "abc"), (4, "xyz"))))
println(getType(((Some('b'), 3), (Some('a'), 4))))
//println(getType(((Some('b'), 3), (None, 4))))
println
println()
}

object testFuncs {
Expand All @@ -109,7 +109,7 @@ object testFuncs {
def f5(f: Int => Int, x: Int) = f(x)
println(getType(f5 _))
println(getType(f5(f1, 1)))
println
println()
}

class Foo {
Expand All @@ -135,12 +135,12 @@ object testClasses {
val foo2 = new Foo
println(getType(foo2))
println(getType(new foo2.Bar(1)))
println
println()
println(getType(pkg1.c1))
val c1 = new pkg1.C1
println(getType(c1))
println
println()
*/
}

Expand Down
2 changes: 1 addition & 1 deletion test/files/jvm/unittest_io_Jvm.scala
Expand Up @@ -8,7 +8,7 @@ object Test {
|it is split on several lines.
|
|isn't it?
|""".stripMargin).getLines.toList
|""".stripMargin).getLines().toList
println("lines.size = " + lines.size)
lines.foreach(println)
}
Expand Down
Empty file removed test/files/jvm/unreachable.check
Empty file.
14 changes: 7 additions & 7 deletions test/files/jvm/unreachable/Foo_1.scala
Expand Up @@ -9,14 +9,14 @@ class Foo_1 {

def unreachableIf: Int = {
return 42
if (util.Random.nextInt % 2 == 0)
if (util.Random.nextInt() % 2 == 0)
0
else
1
}

def unreachableIfBranches: Int = {
if (util.Random.nextInt % 2 == 0)
if (util.Random.nextInt() % 2 == 0)
return 42
else
return 42
Expand All @@ -25,14 +25,14 @@ class Foo_1 {
}

def unreachableOneLegIf: Int = {
if (util.Random.nextInt % 2 == 0)
if (util.Random.nextInt() % 2 == 0)
return 42

return 42
}

def unreachableLeftBranch: Int = {
val result = if (util.Random.nextInt % 2 == 0)
val result = if (util.Random.nextInt() % 2 == 0)
return 42
else
42
Expand All @@ -41,7 +41,7 @@ class Foo_1 {
}

def unreachableRightBranch: Int = {
val result = if (util.Random.nextInt % 2 == 0)
val result = if (util.Random.nextInt() % 2 == 0)
42
else
return 42
Expand Down Expand Up @@ -92,7 +92,7 @@ class Foo_1 {

def unreachableSwitch: Int = {
return 42
val x = util.Random.nextInt % 2
val x = util.Random.nextInt() % 2
x match {
case 0 => return 0
case 1 => return 1
Expand All @@ -102,7 +102,7 @@ class Foo_1 {
}

def unreachableAfterSwitch: Int = {
val x = util.Random.nextInt % 2
val x = util.Random.nextInt() % 2
x match {
case 0 => return 42
case 1 => return 41 + x
Expand Down
12 changes: 9 additions & 3 deletions test/files/neg/auto-application.check
@@ -1,10 +1,16 @@
auto-application.scala:2: error: Int does not take parameters
auto-application.scala:4: error: Int does not take parameters
("": Any).##()
^
auto-application.scala:3: error: Int does not take parameters
auto-application.scala:5: error: Int does not take parameters
("": AnyRef).##()
^
auto-application.scala:4: error: Int does not take parameters
auto-application.scala:6: error: Int does not take parameters
("": Object).##()
^
auto-application.scala:9: warning: Auto-application to `()` is deprecated. Supply the empty argument list `()` explicitly to invoke method meth,
or remove the empty argument list from its definition (Java-defined methods are exempt).
In Scala 3, an unapplied method like this will be eta-expanded into a function.
meth // warn, auto-application (of nilary methods) is deprecated
^
1 warning
3 errors
5 changes: 5 additions & 0 deletions test/files/neg/auto-application.scala
@@ -1,5 +1,10 @@
// scalac: -deprecation -Werror

class Test {
("": Any).##()
("": AnyRef).##()
("": Object).##()

def meth() = ""
meth // warn, auto-application (of nilary methods) is deprecated
}

0 comments on commit c900df8

Please sign in to comment.