Skip to content

Use new extension syntax in library #9336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
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/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ class Definitions {
@tu lazy val Compiletime_error : Symbol = CompiletimePackageObject.requiredMethod(nme.error)
@tu lazy val Compiletime_constValue : Symbol = CompiletimePackageObject.requiredMethod("constValue")
@tu lazy val Compiletime_constValueOpt: Symbol = CompiletimePackageObject.requiredMethod("constValueOpt")
@tu lazy val Compiletime_code : Symbol = CompiletimePackageObject.requiredMethod("code")
@tu lazy val Compiletime_code : Symbol = CompiletimePackageObject.requiredMethod("extension_code")
@tu lazy val Compiletime_summonFrom : Symbol = CompiletimePackageObject.requiredMethod("summonFrom")
@tu lazy val CompiletimeTestingPackageObject: Symbol = ctx.requiredModule("scala.compiletime.testing.package")
@tu lazy val CompiletimeTesting_typeChecks: Symbol = CompiletimeTestingPackageObject.requiredMethod("typeChecks")
Expand Down
136 changes: 68 additions & 68 deletions library/src/scala/IArray.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,242 +19,242 @@ object opaques:
* @param n the index of the element to select
* @return the element of the array at the given index
*/
def (arr: IArray[Byte]) apply(n: Int): Byte = arr.asInstanceOf[Array[Byte]].apply(n)
def (arr: IArray[Short]) apply(n: Int): Short = arr.asInstanceOf[Array[Short]].apply(n)
def (arr: IArray[Char]) apply(n: Int): Char = arr.asInstanceOf[Array[Char]].apply(n)
def (arr: IArray[Int]) apply(n: Int): Int = arr.asInstanceOf[Array[Int]].apply(n)
def (arr: IArray[Long]) apply(n: Int): Long = arr.asInstanceOf[Array[Long]].apply(n)
def (arr: IArray[Float]) apply(n: Int): Float = arr.asInstanceOf[Array[Float]].apply(n)
def (arr: IArray[Double]) apply(n: Int): Double = arr.asInstanceOf[Array[Double]].apply(n)
def [T <: Object](arr: IArray[T]) apply (n: Int): T = arr.asInstanceOf[Array[T]].apply(n)
def [T](arr: IArray[T]) apply (n: Int): T = arr.asInstanceOf[Array[T]].apply(n)
extension (arr: IArray[Byte]) def apply(n: Int): Byte = arr.asInstanceOf[Array[Byte]].apply(n)
extension (arr: IArray[Short]) def apply(n: Int): Short = arr.asInstanceOf[Array[Short]].apply(n)
extension (arr: IArray[Char]) def apply(n: Int): Char = arr.asInstanceOf[Array[Char]].apply(n)
extension (arr: IArray[Int]) def apply(n: Int): Int = arr.asInstanceOf[Array[Int]].apply(n)
extension (arr: IArray[Long]) def apply(n: Int): Long = arr.asInstanceOf[Array[Long]].apply(n)
extension (arr: IArray[Float]) def apply(n: Int): Float = arr.asInstanceOf[Array[Float]].apply(n)
extension (arr: IArray[Double]) def apply(n: Int): Double = arr.asInstanceOf[Array[Double]].apply(n)
extension [T <: Object](arr: IArray[T]) def apply (n: Int): T = arr.asInstanceOf[Array[T]].apply(n)
extension [T](arr: IArray[T]) def apply (n: Int): T = arr.asInstanceOf[Array[T]].apply(n)

/** The number of elements in an immutable array
* @param arr the immutable array
*/
def (arr: IArray[Byte]) length: Int = arr.asInstanceOf[Array[Byte]].length
def (arr: IArray[Short]) length: Int = arr.asInstanceOf[Array[Short]].length
def (arr: IArray[Char]) length: Int = arr.asInstanceOf[Array[Char]].length
def (arr: IArray[Int]) length: Int = arr.asInstanceOf[Array[Int]].length
def (arr: IArray[Long]) length: Int = arr.asInstanceOf[Array[Long]].length
def (arr: IArray[Float]) length: Int = arr.asInstanceOf[Array[Float]].length
def (arr: IArray[Double]) length: Int = arr.asInstanceOf[Array[Double]].length
def (arr: IArray[Object]) length: Int = arr.asInstanceOf[Array[Object]].length
def [T](arr: IArray[T]) length: Int = arr.asInstanceOf[Array[T]].length
extension (arr: IArray[Byte]) def length: Int = arr.asInstanceOf[Array[Byte]].length
extension (arr: IArray[Short]) def length: Int = arr.asInstanceOf[Array[Short]].length
extension (arr: IArray[Char]) def length: Int = arr.asInstanceOf[Array[Char]].length
extension (arr: IArray[Int]) def length: Int = arr.asInstanceOf[Array[Int]].length
extension (arr: IArray[Long]) def length: Int = arr.asInstanceOf[Array[Long]].length
extension (arr: IArray[Float]) def length: Int = arr.asInstanceOf[Array[Float]].length
extension (arr: IArray[Double]) def length: Int = arr.asInstanceOf[Array[Double]].length
extension (arr: IArray[Object]) def length: Int = arr.asInstanceOf[Array[Object]].length
extension [T](arr: IArray[T]) def length: Int = arr.asInstanceOf[Array[T]].length

/** Returns this array concatenated with the given array. */
def [T, U >: T: ClassTag](arr: IArray[T]) ++(that: IArray[U]): IArray[U] =
extension [T, U >: T: ClassTag](arr: IArray[T]) def ++(that: IArray[U]): IArray[U] =
genericArrayOps(arr) ++ that

/** Tests whether this array contains a given value as an element. */
def [T](arr: IArray[T]) contains(elem: T): Boolean =
extension [T](arr: IArray[T]) def contains(elem: T): Boolean =
// `genericArrayOps(arr).contains(elem)` does not work because `elem` does not have type `arr.T`
// but we can use `exists` instead, which is how `ArrayOps#contains` itself is implemented:
genericArrayOps(arr).exists(_ == elem)

/** Counts the number of elements in this array which satisfy a predicate */
def [T](arr: IArray[T]) count(p: T => Boolean): Int =
extension [T](arr: IArray[T]) def count(p: T => Boolean): Int =
genericArrayOps(arr).count(p)

/** The rest of the array without its `n` first elements. */
def [T](arr: IArray[T]) drop(n: Int): IArray[T] =
extension [T](arr: IArray[T]) def drop(n: Int): IArray[T] =
genericArrayOps(arr).drop(n)

/** The rest of the array without its `n` last elements. */
def [T](arr: IArray[T]) dropRight(n: Int): IArray[T] =
extension [T](arr: IArray[T]) def dropRight(n: Int): IArray[T] =
genericArrayOps(arr).dropRight(n)

/** Drops longest prefix of elements that satisfy a predicate. */
def [T](arr: IArray[T]) dropWhile(p: T => Boolean): IArray[T] =
extension [T](arr: IArray[T]) def dropWhile(p: T => Boolean): IArray[T] =
genericArrayOps(arr).dropWhile(p)

/** Tests whether a predicate holds for at least one element of this array. */
def [T](arr: IArray[T]) exists(p: T => Boolean): Boolean =
extension [T](arr: IArray[T]) def exists(p: T => Boolean): Boolean =
genericArrayOps(arr).exists(p)

/** Selects all elements of this array which satisfy a predicate. */
def [T](arr: IArray[T]) filter(p: T => Boolean): IArray[T] =
extension [T](arr: IArray[T]) def filter(p: T => Boolean): IArray[T] =
genericArrayOps(arr).filter(p)

/** Selects all elements of this array which do not satisfy a predicate. */
def [T](arr: IArray[T]) filterNot(p: T => Boolean): IArray[T] =
extension [T](arr: IArray[T]) def filterNot(p: T => Boolean): IArray[T] =
genericArrayOps(arr).filterNot(p)

/** Finds the first element of the array satisfying a predicate, if any. */
def [T](arr: IArray[T]) find(p: T => Boolean): Option[T] =
extension [T](arr: IArray[T]) def find(p: T => Boolean): Option[T] =
genericArrayOps(arr).find(p)

/** Builds a new array by applying a function to all elements of this array
* and using the elements of the resulting collections. */
def [T, U: ClassTag](arr: IArray[T]) flatMap(f: T => IterableOnce[U]): IArray[U] =
extension [T, U: ClassTag](arr: IArray[T]) def flatMap(f: T => IterableOnce[U]): IArray[U] =
genericArrayOps(arr).flatMap(f)

/** Flattens a two-dimensional array by concatenating all its rows
* into a single array. */
def [T, U: ClassTag](arr: IArray[T]) flatten(using T => Iterable[U]): IArray[U] =
extension [T, U: ClassTag](arr: IArray[T]) def flatten(using T => Iterable[U]): IArray[U] =
genericArrayOps(arr).flatten

/** Folds the elements of this array using the specified associative binary operator. */
def [T, U >: T: ClassTag](arr: IArray[T]) fold(z: U)(op: (U, U) => U): U =
extension [T, U >: T: ClassTag](arr: IArray[T]) def fold(z: U)(op: (U, U) => U): U =
genericArrayOps(arr).fold(z)(op)

/** Applies a binary operator to a start value and all elements of this array,
* going left to right. */
def [T, U: ClassTag](arr: IArray[T]) foldLeft(z: U)(op: (U, T) => U): U =
extension [T, U: ClassTag](arr: IArray[T]) def foldLeft(z: U)(op: (U, T) => U): U =
genericArrayOps(arr).foldLeft(z)(op)

/** Applies a binary operator to all elements of this array and a start value,
* going right to left. */
def [T, U: ClassTag](arr: IArray[T]) foldRight(z: U)(op: (T, U) => U): U =
extension [T, U: ClassTag](arr: IArray[T]) def foldRight(z: U)(op: (T, U) => U): U =
genericArrayOps(arr).foldRight(z)(op)

/** Tests whether a predicate holds for all elements of this array. */
def [T](arr: IArray[T]) forall(p: T => Boolean): Boolean =
extension [T](arr: IArray[T]) def forall(p: T => Boolean): Boolean =
genericArrayOps(arr).forall(p)

/** Apply `f` to each element for its side effects. */
def [T, U](arr: IArray[T]) foreach(f: T => U): Unit =
extension [T, U](arr: IArray[T]) def foreach(f: T => U): Unit =
genericArrayOps(arr).foreach(f)

/** Selects the first element of this array. */
def [T](arr: IArray[T]) head: T =
extension [T](arr: IArray[T]) def head: T =
genericArrayOps(arr).head

/** Optionally selects the first element. */
def [T](arr: IArray[T]) headOption: Option[T] =
extension [T](arr: IArray[T]) def headOption: Option[T] =
genericArrayOps(arr).headOption

/** Finds index of first occurrence of some value in this array after or at some start index. */
def [T](arr: IArray[T]) indexOf(elem: T, from: Int = 0): Int =
extension [T](arr: IArray[T]) def indexOf(elem: T, from: Int = 0): Int =
// `asInstanceOf` needed because `elem` does not have type `arr.T`
// We could use `arr.iterator.indexOf(elem, from)` or `arr.indexWhere(_ == elem, from)`
// but these would incur some overhead.
genericArrayOps(arr).indexOf(elem.asInstanceOf, from)

/** Finds index of the first element satisfying some predicate after or at some start index. */
def [T](arr: IArray[T]) indexWhere(p: T => Boolean, from: Int = 0): Int =
extension [T](arr: IArray[T]) def indexWhere(p: T => Boolean, from: Int = 0): Int =
genericArrayOps(arr).indexWhere(p, from)

/** Produces the range of all indices of this sequence. */
def [T](arr: IArray[T]) indices: Range =
extension [T](arr: IArray[T]) def indices: Range =
genericArrayOps(arr).indices

/** The initial part of the array without its last element. */
def [T](arr: IArray[T]) init: IArray[T] =
extension [T](arr: IArray[T]) def init: IArray[T] =
genericArrayOps(arr).init

/** Tests whether the array is empty. */
def [T](arr: IArray[T]) isEmpty: Boolean =
extension [T](arr: IArray[T]) def isEmpty: Boolean =
genericArrayOps(arr).isEmpty

/** An iterator yielding the elemenst of this array. */
def [T](arr: IArray[T]) iterator: Iterator[T] =
extension [T](arr: IArray[T]) def iterator: Iterator[T] =
genericArrayOps(arr).iterator

/** Selects the last element. */
def [T](arr: IArray[T]) last: T =
extension [T](arr: IArray[T]) def last: T =
genericArrayOps(arr).last

/** Optionally selects the last element. */
def [T](arr: IArray[T]) lastOption: Option[T] =
extension [T](arr: IArray[T]) def lastOption: Option[T] =
genericArrayOps(arr).lastOption

/** Finds index of last occurrence of some value in this array before or at a given end index. */
def [T](arr: IArray[T]) lastIndexOf(elem: T, end: Int = arr.length - 1): Int =
extension [T](arr: IArray[T]) def lastIndexOf(elem: T, end: Int = arr.length - 1): Int =
// see: same issue in `indexOf`
genericArrayOps(arr).lastIndexOf(elem.asInstanceOf, end)

/** Finds index of last element satisfying some predicate before or at given end index. */
def [T](arr: IArray[T]) lastIndexWhere(p: T => Boolean, end: Int = arr.length - 1): Int =
extension [T](arr: IArray[T]) def lastIndexWhere(p: T => Boolean, end: Int = arr.length - 1): Int =
genericArrayOps(arr).lastIndexWhere(p, end)

/** Builds a new array by applying a function to all elements of this array. */
def [T, U: ClassTag](arr: IArray[T]) map(f: T => U): IArray[U] =
extension [T, U: ClassTag](arr: IArray[T]) def map(f: T => U): IArray[U] =
genericArrayOps(arr).map(f)

/** Tests whether the array is not empty. */
def [T](arr: IArray[T]) nonEmpty: Boolean =
extension [T](arr: IArray[T]) def nonEmpty: Boolean =
genericArrayOps(arr).nonEmpty

/** A pair of, first, all elements that satisfy predicate `p` and, second, all elements that do not. */
def [T](arr: IArray[T]) partition(p: T => Boolean): (IArray[T], IArray[T]) =
extension [T](arr: IArray[T]) def partition(p: T => Boolean): (IArray[T], IArray[T]) =
genericArrayOps(arr).partition(p)

/** Returns a new array with the elements in reversed order. */
def [T](arr: IArray[T]) reverse: IArray[T] =
extension [T](arr: IArray[T]) def reverse: IArray[T] =
genericArrayOps(arr).reverse

/** Computes a prefix scan of the elements of the array. */
def [T, U >: T: ClassTag](arr: IArray[T]) scan(z: U)(op: (U, U) => U): IArray[U] =
extension [T, U >: T: ClassTag](arr: IArray[T]) def scan(z: U)(op: (U, U) => U): IArray[U] =
genericArrayOps(arr).scan(z)(op)

/** Produces an array containing cumulative results of applying the binary
* operator going left to right. */
def [T, U: ClassTag](arr: IArray[T]) scanLeft(z: U)(op: (U, T) => U): IArray[U] =
extension [T, U: ClassTag](arr: IArray[T]) def scanLeft(z: U)(op: (U, T) => U): IArray[U] =
genericArrayOps(arr).scanLeft(z)(op)

/** Produces an array containing cumulative results of applying the binary
* operator going right to left. */
def [T, U: ClassTag](arr: IArray[T]) scanRight(z: U)(op: (T, U) => U): IArray[U] =
extension [T, U: ClassTag](arr: IArray[T]) def scanRight(z: U)(op: (T, U) => U): IArray[U] =
genericArrayOps(arr).scanRight(z)(op)

/** The size of this array. */
def [T](arr: IArray[T]) size: Int =
extension [T](arr: IArray[T]) def size: Int =
arr.length

/** Selects the interval of elements between the given indices. */
def [T](arr: IArray[T]) slice(from: Int, until: Int): IArray[T] =
extension [T](arr: IArray[T]) def slice(from: Int, until: Int): IArray[T] =
genericArrayOps(arr).slice(from, until)

/** Sorts this array according to the Ordering which results from transforming
* an implicitly given Ordering with a transformation function. */
def [T, U: ClassTag](arr: IArray[T]) sortBy(f: T => U)(using math.Ordering[U]): IArray[T] =
extension [T, U: ClassTag](arr: IArray[T]) def sortBy(f: T => U)(using math.Ordering[U]): IArray[T] =
genericArrayOps(arr).sortBy(f)

/** Sorts this array according to a comparison function. */
def [T](arr: IArray[T]) sortWith(f: (T, T) => Boolean): IArray[T] =
extension [T](arr: IArray[T]) def sortWith(f: (T, T) => Boolean): IArray[T] =
genericArrayOps(arr).sortWith(f)

/** Sorts this array according to an Ordering. */
def [T](arr: IArray[T]) sorted(using math.Ordering[T]): IArray[T] =
extension [T](arr: IArray[T]) def sorted(using math.Ordering[T]): IArray[T] =
genericArrayOps(arr).sorted

/** Splits this array into a prefix/suffix pair according to a predicate. */
def [T](arr: IArray[T]) span(p: T => Boolean): (IArray[T], IArray[T]) =
extension [T](arr: IArray[T]) def span(p: T => Boolean): (IArray[T], IArray[T]) =
genericArrayOps(arr).span(p)

/** Splits this array into two at a given position. */
def [T](arr: IArray[T]) splitAt(n: Int): (IArray[T], IArray[T]) =
extension [T](arr: IArray[T]) def splitAt(n: Int): (IArray[T], IArray[T]) =
genericArrayOps(arr).splitAt(n)

/** Tests whether this array starts with the given array. */
def [T, U >: T: ClassTag](arr: IArray[T]) startsWith(that: IArray[U], offset: Int = 0): Boolean =
extension [T, U >: T: ClassTag](arr: IArray[T]) def startsWith(that: IArray[U], offset: Int = 0): Boolean =
genericArrayOps(arr).startsWith(that)

/** The rest of the array without its first element. */
def [T](arr: IArray[T]) tail: IArray[T] =
extension [T](arr: IArray[T]) def tail: IArray[T] =
genericArrayOps(arr).tail

/** An array containing the first `n` elements of this array. */
def [T](arr: IArray[T]) take(n: Int): IArray[T] =
extension [T](arr: IArray[T]) def take(n: Int): IArray[T] =
genericArrayOps(arr).take(n)

/** An array containing the last `n` elements of this array. */
def [T](arr: IArray[T]) takeRight(n: Int): IArray[T] =
extension [T](arr: IArray[T]) def takeRight(n: Int): IArray[T] =
genericArrayOps(arr).takeRight(n)

/** Takes longest prefix of elements that satisfy a predicate. */
def [T](arr: IArray[T]) takeWhile(p: T => Boolean): IArray[T] =
extension [T](arr: IArray[T]) def takeWhile(p: T => Boolean): IArray[T] =
genericArrayOps(arr).takeWhile(p)

/** Converts an array of pairs into an array of first elements and an array of second elements. */
def [U: ClassTag, V: ClassTag](arr: IArray[(U, V)]) unzip: (IArray[U], IArray[V]) =
extension [U: ClassTag, V: ClassTag](arr: IArray[(U, V)]) def unzip: (IArray[U], IArray[V]) =
genericArrayOps(arr).unzip

/** Returns an array formed from this array and another iterable collection
* by combining corresponding elements in pairs.
* If one of the two collections is longer than the other, its remaining elements are ignored. */
def [T, U: ClassTag](arr: IArray[T]) zip(that: IArray[U]): IArray[(T, U)] =
extension [T, U: ClassTag](arr: IArray[T]) def zip(that: IArray[U]): IArray[(T, U)] =
genericArrayOps(arr).zip(that)
}
end opaques
Expand Down
38 changes: 20 additions & 18 deletions library/src/scala/compiletime/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,26 @@ package object compiletime {
*/
inline def error(inline msg: String): Nothing = ???

/** Returns the string representation of interpolated elaborated code:
*
* ```scala
* inline def logged(p1: => Any) = {
* val c = code"code: $p1"
* val res = p1
* (c, p1)
* }
* logged(identity("foo"))
* // above is equivalent to:
* // ("code: scala.Predef.identity("foo")", identity("foo"))
* ```
*
* @note only by-name arguments will be displayed as "code".
* Other values may display unintutively.
*/
transparent inline def (inline self: StringContext) code (inline args: Any*): String =
${ dotty.internal.CompileTimeMacros.codeExpr('self, 'args) }
extension (inline self: StringContext):
/** Returns the string representation of interpolated elaborated code:
*
* ```scala
* inline def logged(p1: => Any) = {
* val c = code"code: $p1"
* val res = p1
* (c, p1)
* }
* logged(identity("foo"))
* // above is equivalent to:
* // ("code: scala.Predef.identity("foo")", identity("foo"))
* ```
*
* @note only by-name arguments will be displayed as "code".
* Other values may display unintutively.
*/
transparent inline def code (inline args: Any*): String =
${ dotty.internal.CompileTimeMacros.codeExpr('self, 'args) }
end extension

/** Same as `constValue` but returns a `None` if a constant value
* cannot be constructed from the provided type. Otherwise returns
Expand Down
Loading