Skip to content

Inline traits for specialization in Scala 3 #17329

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

Closed
wants to merge 106 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
56c508b
Allow parsing of inline trait, update printer
timotheeandres Feb 24, 2023
5ffb63e
Implement phase 1 of inlining
timotheeandres Feb 28, 2023
966f12d
Implement phase 2 of inlining
timotheeandres Feb 28, 2023
3c4b310
Use inlining capabilities to inline body of defs
timotheeandres Mar 2, 2023
810dcb6
Improve inlining of traits
timotheeandres Mar 9, 2023
7531239
Add atomic tests for inline traits
timotheeandres Mar 23, 2023
f01f90d
Import Nicolas' work
timotheeandres Mar 28, 2023
567d555
Avoid generating accessor fields for inline traits
timotheeandres Mar 28, 2023
e572676
Use parent span for inlined code
timotheeandres Mar 30, 2023
61516a1
Blacklist inline trait tests due to pickling
timotheeandres Mar 30, 2023
2a077cc
Add benchmark for toy version of Numeric
timotheeandres Apr 3, 2023
8b3437f
Delete by-name parameter tests
timotheeandres Apr 4, 2023
b53f142
Revert "Use parent span for inlined code"
timotheeandres Apr 4, 2023
cd14169
Forbid var in inline traits for now
timotheeandres Apr 4, 2023
e167b96
Add override modifier to param accessors
timotheeandres Apr 4, 2023
e382e75
Forbid using/implicit parameters for now
timotheeandres Apr 4, 2023
ab2c439
Fix typo in type bound
timotheeandres Apr 4, 2023
fdfbe26
Multiple files tests, quick fix of span
timotheeandres Apr 6, 2023
e4e42ae
Improve benchmark, make adding implementations easier
timotheeandres Apr 6, 2023
5866057
Add specialized and inline trait matrices for benchmark
timotheeandres Apr 13, 2023
8c84089
Fix issue with generic type in signature
timotheeandres Apr 13, 2023
4d981af
Import modifications by Nicolas
nicolasstucki Apr 13, 2023
6b02d82
Rework and fix tests
timotheeandres Apr 14, 2023
67173de
Make fields private again
timotheeandres Apr 14, 2023
a516748
Fix type issue between untpd and tpd
timotheeandres Apr 14, 2023
f568ef8
Add tests with manual override
timotheeandres Apr 14, 2023
bd94dc6
Simplify type argument substitution in inline methods
nicolasstucki Apr 14, 2023
fd14025
Refactor creation of inlined symbols
nicolasstucki Apr 14, 2023
c06a501
Only call `inline` on rhs
nicolasstucki Apr 14, 2023
fa53620
Perform misc. changes on tests
timotheeandres Apr 17, 2023
59feb3f
Only allow override final if member is synthetic
timotheeandres Apr 17, 2023
2804dfd
Prevent generation of setters in inline traits
timotheeandres Apr 17, 2023
8b4741b
Don't generate members if they are overridden by user
timotheeandres Apr 17, 2023
59d6221
Fix type params not being replaced in RHS
timotheeandres Apr 18, 2023
b762cc9
Clean up InlineParentTrait
timotheeandres Apr 18, 2023
4bf1c76
Compute overriden symbols only once
timotheeandres Apr 20, 2023
e92c7b5
Factorize code to know what to inline from inline trait
timotheeandres Apr 21, 2023
c676689
Allow inlining of deferred defs
timotheeandres Apr 21, 2023
b9a81b1
Clean up example 4, make version without inner class
timotheeandres Apr 21, 2023
026212f
Update inner class tests
timotheeandres Apr 21, 2023
76e5e9a
Move special expansion cases in inlining methods
timotheeandres Apr 24, 2023
a4fd776
Create InlineTreeMap, make helper function for param accessors
timotheeandres Apr 24, 2023
334b5d3
Make accessor values functions tailrec
timotheeandres Apr 24, 2023
f1aa33e
Implement grandparent inline traits, fix parameters shadowing
timotheeandres Apr 24, 2023
2d20a79
Clean up code to get defs to inline
timotheeandres Apr 26, 2023
fcb2279
Start moving code from Typer
timotheeandres Apr 26, 2023
84a1682
Fix tests/pos/inline-trait-multiple-stages-generic-defs
nicolasstucki Apr 26, 2023
e13a71f
Pass overridden decls when expanding
timotheeandres Apr 26, 2023
59bee43
Remove pickling test blacklist
timotheeandres Apr 26, 2023
845c00b
Move trait inlining into Inlining phase
timotheeandres Apr 26, 2023
3d162cb
Implement ancestors inline traits without term args
timotheeandres Apr 27, 2023
50b6743
Disable test with inner class
timotheeandres Apr 27, 2023
34f77f6
Ensure inline traits have same extends precedence as normal traits
timotheeandres Apr 27, 2023
d605bc5
Partially implement inner traits
timotheeandres Apr 28, 2023
9e26b35
Use typeRef on ctx.owner
timotheeandres Apr 28, 2023
6523fcc
Split symbol inlining method by case
timotheeandres May 8, 2023
bcb6702
Improve checks in phases
timotheeandres May 10, 2023
e3e5582
Remove RHS of definitions in inline traits
timotheeandres May 10, 2023
c9ec223
Add tests with macros (unstable)
timotheeandres May 10, 2023
08e2689
Fix owner of bodies to their rightful symbols
timotheeandres May 10, 2023
5348868
Add more tests
timotheeandres May 10, 2023
060f5ab
Inline code of thisType at sole call site
timotheeandres May 10, 2023
ffe94e8
Forbid defining inline traits inside inline traits
timotheeandres May 11, 2023
67d8b1e
Enable inheritance tests
timotheeandres May 11, 2023
fde0c55
Check if owner is inline trait last
timotheeandres May 12, 2023
086f0b9
Use proper thisType, add coords to inlinedSym
timotheeandres May 12, 2023
2fc66ac
Extract param accessors code into helper class
timotheeandres May 16, 2023
686aac0
Move trait-related code to InlineParentTrait
timotheeandres May 16, 2023
78077a4
Add missing context to expandStat, refactor code
timotheeandres May 23, 2023
2172d03
Refactor Inlining for clarity
timotheeandres May 23, 2023
3f749f1
Factorize code for new inner class names
timotheeandres May 23, 2023
5570b25
Remove last refs to inline trait from Inliner
timotheeandres May 23, 2023
829f9eb
Call super before matching in Tree-/TypeMap
timotheeandres May 23, 2023
a1bc61f
Improve class symbol inlining
timotheeandres May 23, 2023
5226450
Prevent creating new accessor names for inner class' params
timotheeandres May 23, 2023
728d837
Do not add override flag to inner class-like type params
timotheeandres May 23, 2023
2392575
Remove incorrect parent, TODO add correct one
timotheeandres May 23, 2023
c4f13af
Add proper type bound to generated type
timotheeandres May 23, 2023
0b6ec5e
Register class-like symbol to be replaced by inliner
timotheeandres May 23, 2023
6075cd3
Forbid term params for inline traits
timotheeandres May 24, 2023
74aaba9
Create vals for child type and child tree
timotheeandres May 25, 2023
9514ccd
Add proper parent to inner class info
timotheeandres May 25, 2023
a5b53f8
Make function to inline just rhs
timotheeandres May 25, 2023
6fc5bd9
Handle inlining of statements in inline trait body
timotheeandres May 25, 2023
8a756d2
Add tests for inner traits
timotheeandres May 30, 2023
39e57f2
Remove FIXME along with info mapping
timotheeandres May 31, 2023
d7ada60
Add test for anonymous class extending inline trait
timotheeandres Jun 1, 2023
4b99869
Rename param for clarity
timotheeandres Jun 1, 2023
746e677
Create helper methods for inline trait rewriting
timotheeandres Jun 1, 2023
d896688
Strip parents of inner class from concrete elements
timotheeandres Jun 1, 2023
b1eec85
Add Synthetic flag to new trait and type
timotheeandres Jun 1, 2023
e13d3c4
Adapt body of child to point to inlined members
timotheeandres Jun 1, 2023
34a5567
Use wildcard for default var value in benchmark
timotheeandres Jun 5, 2023
5a0339b
Add Pair to benchmark
timotheeandres Jun 5, 2023
b1e16ab
Manual specialization, remove unused toTuple
timotheeandres Jun 6, 2023
cb95383
Add boxing benchmark for report
timotheeandres Jun 14, 2023
2784d54
Move inline trait inlining to its own phase
timotheeandres Jun 5, 2023
5c82ee0
Add simple test for inner class
timotheeandres Jun 16, 2023
6e8a489
Rework benchmark files for report
timotheeandres Jul 4, 2023
7c82e3d
Remove target name for inlined inner class
timotheeandres Jul 4, 2023
fd737ea
Restrict non-local private fields
timotheeandres Jul 4, 2023
7e2952c
Forbid user from overriding vars
timotheeandres Jul 4, 2023
f6e171b
Add tests for constructor arguments with side effects
timotheeandres Jul 4, 2023
102269e
Improve error message, remove unused method
timotheeandres Jul 4, 2023
a557940
Allow overriding opaque aliases for inline traits
timotheeandres Jul 4, 2023
17e17bc
Let compiler complain if deferred member isn't implemented
timotheeandres Jul 4, 2023
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package dotty.tools.benchmarks.inlinetraits

import org.openjdk.jmh.annotations._
import java.util.concurrent.TimeUnit.{SECONDS, MILLISECONDS}
import scala.util.Random

// @BenchmarkMode(Array(Mode.SampleTime))
@Fork(3)
@Threads(3)
@Warmup(iterations = 5, time = 10, timeUnit = SECONDS)
@Measurement(iterations = 10, time = 10, timeUnit = SECONDS)
// @OutputTimeUnit(MILLISECONDS)
@State(Scope.Benchmark)
class Boxing {
class Wrapper[T](val x: T)
class IntWrapper(val x: Int)

val numbers = 1 to 1000000
val ws = numbers.map(Wrapper(_))
val iws = numbers.map(IntWrapper(_))

@Benchmark
def noUnboxing: Int = iws.map(w => IntWrapper(w.x*w.x + 2*w.x)).foldLeft(0)(_ + _.x)

@Benchmark
def withUnboxing: Int = ws.map(w => Wrapper(w.x*w.x + 2*w.x)).foldLeft(0)(_ + _.x)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dotty.tools.benchmarks.inlinetraits

import org.openjdk.jmh.annotations._
import java.util.concurrent.TimeUnit.SECONDS
import scala.util.Random

@Fork(10)
@Threads(3)
@Warmup(iterations = 3, time = 5, timeUnit = SECONDS)
@Measurement(iterations = 5, time = 10, timeUnit = SECONDS)
@State(Scope.Benchmark)
class MatrixBenchmark {
val n: Int = 100

def intMatrixElems: List[List[Int]] =
List.tabulate(n, n)((_, _) => Random.nextInt())

@Param(Array("standard", "specialized", "inlinetrait"))
var libType: String = _

var m1: BenchmarkMatrix = _
var m2: BenchmarkMatrix = _

@Setup(Level.Trial)
def setup = {
Random.setSeed(n)

val matrixFactory = BenchmarkMatrix.ofType(libType)
m1 = matrixFactory(intMatrixElems)
m2 = matrixFactory(intMatrixElems)
}

@Benchmark
def matrixBenchmark = (m1 + m2) * m1 // O(n^3) loops
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package dotty.tools.benchmarks.inlinetraits

import standard.IntMatrixLib.{Matrix => StdIntMatrix}
import specialized.IntMatrixLib.{Matrix => SpeIntMatrix}
import inlinetrait.IntMatrixLib.{Matrix => InlIntMatrix}

trait BenchmarkMatrix:
def +(n: BenchmarkMatrix): BenchmarkMatrix
def *(n: BenchmarkMatrix): BenchmarkMatrix

object BenchmarkMatrix:
def ofType(tpe: String): Seq[Seq[Int]] => BenchmarkMatrix =
(elems: Seq[Seq[Int]]) => tpe.toLowerCase() match {
case "standard" => StdBenchmarkMatrix(StdIntMatrix(elems*))
case "specialized" => SpeBenchmarkMatrix(SpeIntMatrix(elems*))
case "inlinetrait" => InlBenchmarkMatrix(InlIntMatrix(elems*))
}

private class StdBenchmarkMatrix(val m: StdIntMatrix) extends BenchmarkMatrix:
import standard.IntMatrixLib.{+, `*`}
override def +(n: BenchmarkMatrix): StdBenchmarkMatrix = n match {
case stdN: StdBenchmarkMatrix => StdBenchmarkMatrix(this.m + stdN.m)
}
override def *(n: BenchmarkMatrix): StdBenchmarkMatrix = n match {
case stdN: StdBenchmarkMatrix => StdBenchmarkMatrix(this.m * stdN.m)
}

private class SpeBenchmarkMatrix(val m: SpeIntMatrix) extends BenchmarkMatrix:
import specialized.IntMatrixLib.{+ => plus, `*` => times}
override def +(n: BenchmarkMatrix): SpeBenchmarkMatrix = n match {
case speN: SpeBenchmarkMatrix => SpeBenchmarkMatrix(plus(this.m)(speN.m))
}
override def *(n: BenchmarkMatrix): SpeBenchmarkMatrix = n match {
case speN: SpeBenchmarkMatrix => SpeBenchmarkMatrix(times(this.m)(speN.m))
}

private class InlBenchmarkMatrix(val m: InlIntMatrix) extends BenchmarkMatrix:
import inlinetrait.IntMatrixLib.{+, `*`}
override def +(n: BenchmarkMatrix): InlBenchmarkMatrix = n match {
case inlN: InlBenchmarkMatrix => InlBenchmarkMatrix(this.m + inlN.m)
}
override def *(n: BenchmarkMatrix): InlBenchmarkMatrix = n match {
case inlN: InlBenchmarkMatrix => InlBenchmarkMatrix(this.m * inlN.m)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package dotty.tools.benchmarks.inlinetraits

import org.openjdk.jmh.annotations._
import java.util.concurrent.TimeUnit.SECONDS
import scala.util.Random

@Fork(10)
@Threads(3)
@Warmup(iterations = 3, time = 5, timeUnit = SECONDS)
@Measurement(iterations = 5, time = 10, timeUnit = SECONDS)
@State(Scope.Benchmark)
class PairsBenchmark {
val numPairs: Int = 3_000_000

def pairElems: List[(First, Second)] = List.tabulate(numPairs)(_ % 2 match {
case 0 => (Random.nextInt(), Random.nextDouble())
case 1 => (Random.nextInt(Char.MaxValue).asInstanceOf[Char], Random.nextInt(Short.MaxValue).asInstanceOf[Short])
})

@Param(Array("standard", "specialized", "inlinetrait"))
var libType: String = _

var pairs: List[BenchmarkPair] = _

@Setup(Level.Trial)
def setup = {
Random.setSeed(numPairs)

val pairFactory = (l: List[(First, Second)]) => l.map((_1, _2) => BenchmarkPair.ofType(libType)(_1, _2))
pairs = pairFactory(pairElems)
}

@Benchmark
def pairsBenchmark = pairs.foldLeft(0){ case (sum, pair) => pair match {
case BenchmarkPair(i: Int, d: Double) => 7 * i + 3 * d.toInt + sum
case BenchmarkPair(c: Char, s: Short) => 5 * c + 2 * s + sum
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package dotty.tools.benchmarks.inlinetraits

import standard.{Pair => StdPair}
import specialized.{Pair => SpePair}
import inlinetrait.{
Pair => InlPair,
IntDoublePair => IDPair,
CharShortPair => CSPair,
}

type First = Int | Char
type Second = Double | Short

class BenchmarkPair private (val _1: First, val _2: Second):
def this(p: StdPair[First, Second]) = this(p._1, p._2)
def this(p: SpePair[First, Second]) = this(p._1, p._2)
def this(p: InlPair[First, Second]) = this(p._1, p._2)

object BenchmarkPair:
def ofType(tpe: String): (First, Second) => BenchmarkPair =
(_1: First, _2: Second) => tpe.toLowerCase() match {
case "standard" => BenchmarkPair(StdPair(_1, _2))
case "specialized" =>
val concretePair: SpePair[First, Second] = (_1, _2) match {
case (_1: Int, _2: Double) => SpePair(_1, _2)
case (_1: Char, _2: Short) => SpePair(_1, _2)
case _ => ???
}
BenchmarkPair(concretePair)
case "inlinetrait" =>
val concretePair: InlPair[First, Second] = (_1, _2) match {
case (_1: Int, _2: Double) => IDPair(_1, _2)
case (_1: Char, _2: Short) => CSPair(_1, _2)
case _ => ???
}
BenchmarkPair(concretePair)
}

def unapply(p: BenchmarkPair): Option[(First, Second)] = Some(p._1, p._2)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package dotty.tools.benchmarks.inlinetraits
package inlinetrait

import scala.reflect.ClassTag

inline trait MatrixLib[T: ClassTag]:
// FIXME make Matrix opaque once inlinedTypeRef works properly
/*opaque*/ type Matrix = Array[Array[T]]

// FIXME uncomment object and remove following code when inner objects work
/*
* object Matrix:
* def apply(rows: Seq[T]*): Matrix =
* rows.map(_.toArray).toArray
*/
// ----------------------------------
def Matrix(rows: Seq[T]*): Matrix =
rows.map(_.toArray).toArray
// ----------------------------------
// end of code to remove

extension (m: Matrix)
def apply(x: Int)(y: Int): T = m(x)(y)
def rows: Int = m.length
def cols: Int = m(0).length

object IntMatrixLib extends MatrixLib[Int]:
extension (m: Matrix)
def +(n: Matrix): Matrix =
val sum =
for row <- 0 until m.rows
yield
for col <- 0 until m.cols
yield m(row)(col) + n(row)(col)
Matrix(sum*)
end +

def *(n: Matrix): Matrix =
val prod =
for i <- 0 until m.rows
yield
for j <- 0 until n.cols
yield
val mults = for k <- 0 until n.rows yield m(i)(k) * n(k)(j)
mults.fold(0)(_ + _)
Matrix(prod*)
end *
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dotty.tools.benchmarks.inlinetraits
package inlinetrait

inline trait Pair[+T1, +T2](val _1: T1, val _2: T2)

class IntDoublePair(override val _1: Int, override val _2: Double) extends Pair[Int, Double](_1, _2)
class CharShortPair(override val _1: Char, override val _2: Short) extends Pair[Char, Short](_1, _2)
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package dotty.tools.benchmarks.inlinetraits
package specialized

/*
* This implementation relies on the @specialized tag to specialize the MatrixLib.
* However, @specialized does nothing in Scala 3. Therefore, an equivalent version is
* recreated by hand further down, and the actual Scala 2 code is provided below:
*
* import scala.reflect.ClassTag
* import scala.specialized
*
* class MatrixLib[@specialized(Int) T: ClassTag] {
* type Matrix = Array[Array[T]]
*
* object Matrix {
* def apply(rows: Seq[T]*): Matrix =
* rows.map(_.toArray).toArray
* }
*
* def get(m: Matrix)(x: Int)(y: Int): T = m(x)(y)
* def rows(m: Matrix): Int = m.length
* def cols(m: Matrix): Int = m(0).length
* }
*
* object IntMatrixLib extends MatrixLib[Int] {
* def +(m: Matrix)(n: Matrix): Matrix = {
* val sum = {
* for (row <- 0 until rows(m))
* yield {
* for (col <- 0 until cols(m))
* yield m(row)(col) + n(row)(col)
* }
* }
* Matrix(sum: _*)
* }
*
* def *(m: Matrix)(n: Matrix): Matrix = {
* val prod = {
* for (i <- 0 until rows(m))
* yield {
* for (j <- 0 until cols(n))
* yield {
* val mults =
* for (k <- 0 until rows(n)) yield get(m)(i)(k) * get(n)(k)(j)
* mults.fold(0)(_ + _)
* }
* }
* }
* Matrix(prod: _*)
* }
* }
*/

import scala.reflect.ClassTag
import scala.specialized

class MatrixLib {
private[specialized] type ObjectMatrix = Array[Array[Object]]
private[specialized] type IntMatrix = Array[Array[Int]]

def get(m: ObjectMatrix)(x: Int)(y: Int): Object = m(x)(y)
def rows(m: ObjectMatrix): Int = m.length
def cols(m: ObjectMatrix): Int = m(0).length
private[specialized] def get$mcI$sp(m: IntMatrix)(x: Int)(y: Int): Int = Int.unbox(get(m.asInstanceOf[ObjectMatrix])(x)(y))
private[specialized] def rows$mcI$sp(m: IntMatrix): Int = rows(m.asInstanceOf[ObjectMatrix])
private[specialized] def cols$mcI$sp(m: IntMatrix): Int = cols(m.asInstanceOf[ObjectMatrix])
}

private class MatrixLib$mcI$sp extends MatrixLib {
override def get(m: ObjectMatrix)(x: Int)(y: Int): Object = Int.box(get(m.asInstanceOf[IntMatrix])(x)(y))
override def rows(m: ObjectMatrix): Int = rows(m.asInstanceOf[IntMatrix])
override def cols(m: ObjectMatrix): Int = cols(m.asInstanceOf[IntMatrix])
def get(m: IntMatrix)(x: Int)(y: Int): Int = get$mcI$sp(m)(x)(y)
def rows(m: IntMatrix): Int = rows$mcI$sp(m)
def cols(m: IntMatrix): Int = cols$mcI$sp(m)
override private[specialized] def get$mcI$sp(m: IntMatrix)(x: Int)(y: Int): Int = m(x)(y)
override private[specialized] def rows$mcI$sp(m: IntMatrix): Int = m.length
override private[specialized] def cols$mcI$sp(m: IntMatrix): Int = m(0).length
}

object IntMatrixLib extends MatrixLib$mcI$sp {
type Matrix = IntMatrix
object Matrix {
def apply(rows: Seq[Int]*): IntMatrix =
rows.map(_.toArray).toArray
}

def +(m: Matrix)(n: Matrix): Matrix = {
val sum = {
for (row <- 0 until rows(m))
yield {
for (col <- 0 until cols(m))
yield m(row)(col) + n(row)(col)
}
}
Matrix(sum: _*)
}

def *(m: Matrix)(n: Matrix): Matrix = {
val prod = {
for (i <- 0 until rows(m))
yield {
for (j <- 0 until cols(n))
yield {
val mults =
for (k <- 0 until rows(n)) yield get(m)(i)(k) * get(n)(k)(j)
mults.fold(0)(_ + _)
}
}
}
Matrix(prod: _*)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package dotty.tools.benchmarks.inlinetraits
package specialized

/*
* This implementation relies on the @specialized tag to specialize Pair.
* However, @specialized does nothing in Scala 3. Therefore, an equivalent version is
* recreated by hand further down, and the actual Scala 2 code is provided below:
*
* import scala.specialized
*
* class Pair[@specialized(Int, Char) +T1, @specialized(Double, Short) +T2](_1: T1, _2: T2) {}
*/

class Pair[+T1, +T2] protected (val _1: T1, val _2: T2)

object Pair {
def apply(_1: Int, _2: Double): Pair[Int, Double] = new Pair$mcID$sp(_1, _2)
def apply(_1: Int, _2: Short): Pair[Int, Short] = new Pair$mcIS$sp(_1, _2)
def apply(_1: Char, _2: Double): Pair[Char, Double] = new Pair$mcCD$sp(_1, _2)
def apply(_1: Char, _2: Short): Pair[Char, Short] = new Pair$mcCS$sp(_1, _2)
}

private class Pair$mcID$sp(protected[this] val _1$mcI$sp: Int, protected[this] val _2$mcD$sp: Double) extends Pair[Int, Double](_1$mcI$sp, _2$mcD$sp)
private class Pair$mcIS$sp(protected[this] val _1$mcI$sp: Int, protected[this] val _2$mcS$sp: Short) extends Pair[Int, Short](_1$mcI$sp, _2$mcS$sp)
private class Pair$mcCD$sp(protected[this] val _1$mcC$sp: Char, protected[this] val _2$mcD$sp: Double) extends Pair[Char, Double](_1$mcC$sp, _2$mcD$sp)
private class Pair$mcCS$sp(protected[this] val _1$mcC$sp: Char, protected[this] val _2$mcS$sp: Short) extends Pair[Char, Short](_1$mcC$sp, _2$mcS$sp)
Loading