Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/utils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import scala.io.Source
import scala.jdk.StreamConverters._
import scala.reflect.ClassTag
import scala.util.Using.{Releasable, resource}
import scala.util.chaining.given
import scala.util.chaining.*
import scala.util.control.{ControlThrowable, NonFatal}

import dotc.config.CommandLineParser
Expand Down
13 changes: 7 additions & 6 deletions library/src/scala/util/ChainingOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ package util
import scala.language.`2.13`
import scala.language.implicitConversions

@deprecated(message = "ChainingSyntax will be removed in the future. Refer to `scala.util.chaining` instead.",
since = "3.10.0")
trait ChainingSyntax {
@inline implicit final def scalaUtilChainingOps[A](a: A): ChainingOps[A] = new ChainingOps(a)
@deprecated(message = "Use extension methods in `scala.util.chaining` instead.", since = "3.10.0")
@inline final def scalaUtilChainingOps[A](a: A): ChainingOps[A] = new ChainingOps(a)
}

/** Adds chaining methods `tap` and `pipe` to every type.
*/
@deprecated(message = "Use extension methods in `scala.util.chaining` instead.", since = "3.10.0")
final class ChainingOps[A](private val self: A) extends AnyVal {
/** Applies `f` to the value for its side effects, and returns the original value.
*
Expand All @@ -37,10 +41,7 @@ final class ChainingOps[A](private val self: A) extends AnyVal {
* @tparam U the result type of the function `f`.
* @return the original value `self`.
*/
def tap[U](f: A => U): A = {
f(self)
self
}
def tap[U](f: A => U): A = scala.util.chaining.tap(self)(x => f(x))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def tap[U](f: A => U): A = scala.util.chaining.tap(self)(x => f(x))
def tap[U](f: A => U): A = scala.util.chaining.tap(self)(f)

But it is blocked by #24726


/** Converts the value by applying the function `f`.
*
Expand All @@ -62,5 +63,5 @@ final class ChainingOps[A](private val self: A) extends AnyVal {
* @return a new value resulting from applying the given function
* `f` to this value.
*/
def pipe[B](f: A => B): B = f(self)
def pipe[B](f: A => B): B = scala.util.chaining.pipe(self)(f)
}
11 changes: 9 additions & 2 deletions library/src/scala/util/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,16 @@ package scala

import scala.language.`2.13`

import scala.annotation.nowarn

package object util {
/**
* Adds chaining methods `tap` and `pipe` to every type. See [[ChainingOps]].
* Adds chaining methods `tap` and `pipe` to every type.
*/
object chaining extends ChainingSyntax
@nowarn("msg=ChainingSyntax will be removed in the future")
object chaining extends ChainingSyntax:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question for me: Can we move this object to be outside the package object util?

extension[A](x: A)
inline def tap(inline f: A => Unit): x.type = { f(x); x }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The signature here differs from the one we used to have in scala.util.ChainingOps. First, we return a more precise type: x.type. Second, we do not need to have a second type variable and specify that f: A => B since we adapt the body of the lambda after the eta-expansion. This code will compile because of the adaptation for example:

def foo(x: String): String = "()"
val x: String => Unit = foo

def bar(f: String => Unit) = ()
bar(foo)
bar(x)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you don't want to break imports like import scala.util.chaining.given then you can put these in a given AnyRef:

inline def pipe[B](inline f: A => B): B = f(x)
inline infix def |> [B](inline f: A => B): B = x.pipe(f)
}
2 changes: 1 addition & 1 deletion repl/test/dotty/tools/repl/StackTraceTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package dotty.tools.repl
import scala.language.unsafeNulls

import scala.util.{Failure, Success, Try}
import scala.util.chaining.given
import scala.util.chaining.*

import org.junit.Assert.{assertEquals, assertTrue}
import org.junit.Test
Expand Down
1 change: 0 additions & 1 deletion tests/neg/i15998.check
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
| import scala.math.BigDecimal.int2bigDecimal
| import scala.math.BigInt.int2bigInt
| import scala.math.Ordered.orderingToOrdered
| import scala.util.chaining.scalaUtilChainingOps
|
|
| longer explanation available when compiling with `-explain`
Expand Down
2 changes: 1 addition & 1 deletion tests/run/i10889.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import scala.annotation.tailrec
import scala.util.chaining.given
import scala.util.chaining.*

object Test {
class Ctx
Expand Down
2 changes: 1 addition & 1 deletion tests/run/i11571.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import util.chaining.scalaUtilChainingOps
import util.chaining.*
object Test extends App {
def x = 42.tap(println(_))
def y = 27.tap(println(_))
Expand Down
Loading