From cd02a220e3578fe46150460e769a70af25679ef0 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 15 Jul 2019 17:09:21 +0200 Subject: [PATCH 1/2] Always package same-named objects and types together --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 35e62d523894..bc4a1d62ef06 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1153,17 +1153,21 @@ object desugar { * - all pattern, value and method definitions * - non-class type definitions * - implicit classes and objects - * - companion objects of opaque types + * - "companion objects" of wrapped type definitions + * (i.e. objects having the same name as a wrapped type) */ def packageDef(pdef: PackageDef)(implicit ctx: Context): PackageDef = { - val opaqueNames = pdef.stats.collect { - case stat: TypeDef if stat.mods.is(Opaque) => stat.name + def isWrappedType(stat: TypeDef): Boolean = + !stat.isClassDef || stat.mods.isOneOf(DelegateOrImplicit) + val wrappedTypeNames = pdef.stats.collect { + case stat: TypeDef if isWrappedType(stat) => stat.name } def needsObject(stat: Tree) = stat match { case _: ValDef | _: PatDef | _: DefDef | _: Export => true case stat: ModuleDef => - stat.mods.isOneOf(DelegateOrImplicit) || opaqueNames.contains(stat.name.stripModuleClassSuffix.toTypeName) - case stat: TypeDef => !stat.isClassDef || stat.mods.isOneOf(DelegateOrImplicit) + stat.mods.isOneOf(DelegateOrImplicit) || + wrappedTypeNames.contains(stat.name.stripModuleClassSuffix.toTypeName) + case stat: TypeDef => isWrappedType(stat) case _ => false } val (nestedStats, topStats) = pdef.stats.partition(needsObject) From 85c4bb3213b0a224391a6972ac58f1ca94a201ce Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 15 Jul 2019 17:10:24 +0200 Subject: [PATCH 2/2] Refactor IArray so that creation methods can be inlined With the new restrictions on inlined methods and opaque types, we need to refactor IArray if we want to inline creation methods. --- library/src-bootstrapped/scala/IArray.scala | 120 ++++++++++---------- 1 file changed, 62 insertions(+), 58 deletions(-) diff --git a/library/src-bootstrapped/scala/IArray.scala b/library/src-bootstrapped/scala/IArray.scala index 16d92077b9ad..d6f0156136f3 100644 --- a/library/src-bootstrapped/scala/IArray.scala +++ b/library/src-bootstrapped/scala/IArray.scala @@ -4,66 +4,70 @@ import reflect.ClassTag /** An immutable array. An `IArray[T]` has the same representation as an `Array[T]`, * but it cannot be updated. Unlike regular arrays, immutable arrays are covariant. */ -opaque type IArray[+T] = Array[_ <: T] - -/** Defines extension methods for immutable arrays */ -implicit object arrayOps { - - /** The selection operation on an immutable array. - * - * @param arr the immutable array - * @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 (arr: IArray[T]) apply[T <: Object] (n: Int): T = arr.asInstanceOf[Array[T]].apply(n) - def (arr: IArray[T]) apply[T] (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 (arr: IArray[T]) length[T] : Int = arr.asInstanceOf[Array[T]].length +object opaques { + opaque type IArray[+T] = Array[_ <: T] + + /** Defines extension methods for immutable arrays */ + given arrayOps { + + /** The selection operation on an immutable array. + * + * @param arr the immutable array + * @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 (arr: IArray[T]) apply[T <: Object] (n: Int): T = arr.asInstanceOf[Array[T]].apply(n) + def (arr: IArray[T]) apply[T] (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 (arr: IArray[T]) length[T] : Int = arr.asInstanceOf[Array[T]].length + } } +type IArray[+T] = opaques.IArray[T] object IArray { /** An immutable array of length 0. */ - def empty[T: ClassTag]: IArray[T] = new Array[T](0) + def empty[T: ClassTag]: IArray[T] = new Array[T](0).asInstanceOf /** An immutable array with given elements. */ - def apply[T: ClassTag](xs: T*): IArray[T] = Array(xs: _*) - def apply(x: Boolean, xs: Boolean*): IArray[Boolean] = Array(x, xs: _*) - def apply(x: Byte, xs: Byte*): IArray[Byte] = Array(x, xs: _*) - def apply(x: Short, xs: Short*): IArray[Short] = Array(x, xs: _*) - def apply(x: Char, xs: Char*): IArray[Char] = Array(x, xs: _*) - def apply(x: Int, xs: Int*): IArray[Int] = Array(x, xs: _*) - def apply(x: Long, xs: Long*): IArray[Long] = Array(x, xs: _*) - def apply(x: Float, xs: Float*): IArray[Float] = Array(x, xs: _*) - def apply(x: Double, xs: Double*): IArray[Double] = Array(x, xs: _*) - def apply(x: Unit, xs: Unit*): IArray[Unit] = Array(x, xs: _*) + def apply[T: ClassTag](xs: T*): IArray[T] = Array(xs: _*).asInstanceOf + def apply(x: Boolean, xs: Boolean*): IArray[Boolean] = Array(x, xs: _*).asInstanceOf + def apply(x: Byte, xs: Byte*): IArray[Byte] = Array(x, xs: _*).asInstanceOf + def apply(x: Short, xs: Short*): IArray[Short] = Array(x, xs: _*).asInstanceOf + def apply(x: Char, xs: Char*): IArray[Char] = Array(x, xs: _*).asInstanceOf + def apply(x: Int, xs: Int*): IArray[Int] = Array(x, xs: _*).asInstanceOf + def apply(x: Long, xs: Long*): IArray[Long] = Array(x, xs: _*).asInstanceOf + def apply(x: Float, xs: Float*): IArray[Float] = Array(x, xs: _*).asInstanceOf + def apply(x: Double, xs: Double*): IArray[Double] = Array(x, xs: _*).asInstanceOf + def apply(x: Unit, xs: Unit*): IArray[Unit] = Array(x, xs: _*).asInstanceOf /** Concatenates all arrays into a single immutable array. * * @param xss the given immutable arrays * @return the array created from concatenating `xss` */ - def concat[T: ClassTag](xss: IArray[T]*): IArray[T] = Array.concat[T](xss.asInstanceOf[Seq[Array[T]]]: _*) + def concat[T: ClassTag](xss: IArray[T]*): IArray[T] = + Array.concat[T](xss.asInstanceOf[Seq[Array[T]]]: _*).asInstanceOf /** Returns an immutable array that contains the results of some element computation a number * of times. Each element is determined by a separate computation. @@ -72,7 +76,7 @@ object IArray { * @param elem the element computation */ def fill[T: ClassTag](n: Int)(elem: => T): IArray[T] = - Array.fill(n)(elem) + Array.fill(n)(elem).asInstanceOf /** Returns a two-dimensional immutable array that contains the results of some element computation a number * of times. Each element is determined by a separate computation. @@ -82,7 +86,7 @@ object IArray { * @param elem the element computation */ def fill[T: ClassTag](n1: Int, n2: Int)(elem: => T): IArray[IArray[T]] = - Array.fill(n1, n2)(elem) + Array.fill(n1, n2)(elem).asInstanceOf /** Returns a three-dimensional immutable array that contains the results of some element computation a number * of times. Each element is determined by a separate computation. @@ -93,7 +97,7 @@ object IArray { * @param elem the element computation */ def fill[T: ClassTag](n1: Int, n2: Int, n3: Int)(elem: => T): IArray[IArray[IArray[T]]] = - Array.fill(n1, n2, n3)(elem) + Array.fill(n1, n2, n3)(elem).asInstanceOf /** Returns a four-dimensional immutable array that contains the results of some element computation a number * of times. Each element is determined by a separate computation. @@ -105,7 +109,7 @@ object IArray { * @param elem the element computation */ def fill[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => T): IArray[IArray[IArray[IArray[T]]]] = - Array.fill(n1, n2, n3, n4)(elem) + Array.fill(n1, n2, n3, n4)(elem).asInstanceOf /** Returns a five-dimensional immutable array that contains the results of some element computation a number * of times. Each element is determined by a separate computation. @@ -118,7 +122,7 @@ object IArray { * @param elem the element computation */ def fill[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => T): IArray[IArray[IArray[IArray[IArray[T]]]]] = - Array.fill(n1, n2, n3, n4, n5)(elem) + Array.fill(n1, n2, n3, n4, n5)(elem).asInstanceOf /** Returns an immutable array containing values of a given function over a range of integer * values starting from 0. @@ -127,7 +131,7 @@ object IArray { * @param f The function computing element values */ def tabulate[T: ClassTag](n: Int)(f: Int => T): IArray[T] = - Array.tabulate(n)(f) + Array.tabulate(n)(f).asInstanceOf /** Returns a two-dimensional immutable array containing values of a given function * over ranges of integer values starting from `0`. @@ -137,7 +141,7 @@ object IArray { * @param f The function computing element values */ def tabulate[T: ClassTag](n1: Int, n2: Int)(f: (Int, Int) => T): IArray[IArray[T]] = - Array.tabulate(n1, n2)(f) + Array.tabulate(n1, n2)(f).asInstanceOf /** Returns a three-dimensional immutable array containing values of a given function * over ranges of integer values starting from `0`. @@ -148,7 +152,7 @@ object IArray { * @param f The function computing element values */ def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => T): IArray[IArray[IArray[T]]] = - Array.tabulate(n1, n2, n3)(f) + Array.tabulate(n1, n2, n3)(f).asInstanceOf /** Returns a four-dimensional immutable array containing values of a given function * over ranges of integer values starting from `0`. @@ -160,7 +164,7 @@ object IArray { * @param f The function computing element values */ def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => T): IArray[IArray[IArray[IArray[T]]]] = - Array.tabulate(n1, n2, n3, n4)(f) + Array.tabulate(n1, n2, n3, n4)(f).asInstanceOf /** Returns a five-dimensional immutable array containing values of a given function * over ranges of integer values starting from `0`. @@ -173,7 +177,7 @@ object IArray { * @param f The function computing element values */ def tabulate[T: ClassTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => T): IArray[IArray[IArray[IArray[IArray[T]]]]] = - Array.tabulate(n1, n2, n3, n4, n5)(f) + Array.tabulate(n1, n2, n3, n4, n5)(f).asInstanceOf /** Returns an immutable array containing a sequence of increasing integers in a range. * @@ -182,7 +186,7 @@ object IArray { * @return the immutable array with values in range `start, start + 1, ..., end - 1` * up to, but excluding, `end`. */ - def range(start: Int, end: Int): IArray[Int] = Array.range(start, end) + def range(start: Int, end: Int): IArray[Int] = Array.range(start, end).asInstanceOf /** Returns an immutable array containing equally spaced values in some integer interval. * @@ -191,7 +195,7 @@ object IArray { * @param step the increment value of the array (may not be zero) * @return the immutable array with values in `start, start + step, ...` up to, but excluding `end` */ - def range(start: Int, end: Int, step: Int): IArray[Int] = Array.range(start, end, step) + def range(start: Int, end: Int, step: Int): IArray[Int] = Array.range(start, end, step).asInstanceOf /** Returns an immutable array containing repeated applications of a function to a start value. * @@ -200,7 +204,7 @@ object IArray { * @param f the function that is repeatedly applied * @return the immutable array returning `len` values in the sequence `start, f(start), f(f(start)), ...` */ - def iterate[T: ClassTag](start: T, len: Int)(f: T => T): IArray[T] = Array.iterate(start, len)(f) + def iterate[T: ClassTag](start: T, len: Int)(f: T => T): IArray[T] = Array.iterate(start, len)(f).asInstanceOf /** Returns a decomposition of the array into a sequence. This supports * a pattern match like `{ case IArray(x,y,z) => println('3 elements')}`.