From e1ef43db377be401353fcec56c578c6704bbcfd2 Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Thu, 30 Mar 2017 09:57:47 +0200 Subject: [PATCH 01/11] Minor formating changes --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 2 +- .../tools/dotc/config/CompilerCommand.scala | 1 - .../src/dotty/tools/dotc/core/Definitions.scala | 9 ++++----- .../src/dotty/tools/dotc/core/Denotations.scala | 2 +- compiler/src/dotty/tools/dotc/core/Flags.scala | 4 ++-- .../src/dotty/tools/dotc/core/TypeErasure.scala | 2 +- .../src/dotty/tools/dotc/transform/Erasure.scala | 16 +++++----------- .../tools/dotc/transform/PatternMatcher.scala | 8 ++------ library/src/dotty/runtime/Arrays.scala | 2 +- 9 files changed, 17 insertions(+), 29 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 013516cd5c89..264b1b2f4623 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -764,7 +764,7 @@ object desugar { val param = makeSyntheticParameter() def selector(n: Int) = Select(refOfDef(param), nme.selectorName(n)) val vdefs = - params.zipWithIndex.map{ + params.zipWithIndex.map { case (param, idx) => DefDef(param.name, Nil, Nil, TypeTree(), selector(idx)).withPos(param.pos) } diff --git a/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala b/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala index c2301a3aa252..24cfd0f7780a 100644 --- a/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala +++ b/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala @@ -1,4 +1,3 @@ - package dotty.tools.dotc package config diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 4abaf3bc788c..baf79984e437 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -382,7 +382,6 @@ class Definitions { lazy val ArrayModuleType = ctx.requiredModuleRef("scala.Array") def ArrayModule(implicit ctx: Context) = ArrayModuleType.symbol.moduleClass.asClass - lazy val UnitType: TypeRef = valueTypeRef("scala.Unit", BoxedUnitType, java.lang.Void.TYPE, UnitEnc) def UnitClass(implicit ctx: Context) = UnitType.symbol.asClass lazy val BooleanType = valueTypeRef("scala.Boolean", BoxedBooleanType, java.lang.Boolean.TYPE, BooleanEnc) @@ -773,7 +772,7 @@ class Definitions { */ def erasedFunctionClass(cls: Symbol): Symbol = { val arity = scalaClassName(cls).functionArity - if (arity > 22) defn.FunctionXXLClass + if (arity > MaxImplementedFunctionArity) defn.FunctionXXLClass else if (arity >= 0) defn.FunctionClass(arity) else NoSymbol } @@ -787,7 +786,7 @@ class Definitions { */ def erasedFunctionType(cls: Symbol): Type = { val arity = scalaClassName(cls).functionArity - if (arity > 22) defn.FunctionXXLType + if (arity > MaxImplementedFunctionArity) defn.FunctionXXLType else if (arity >= 0) defn.FunctionType(arity) else NoType } @@ -805,8 +804,8 @@ class Definitions { ) val PredefImportFns = List[() => TermRef]( - () => ScalaPredefModuleRef, - () => DottyPredefModuleRef + () => ScalaPredefModuleRef, + () => DottyPredefModuleRef ) lazy val RootImportFns = diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index ffc58f2e8d2f..ac4509367751 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -1225,4 +1225,4 @@ object Denotations { util.Stats.record("stale symbol") override def getMessage() = msg } -} \ No newline at end of file +} diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index c1929d882b21..a9c594527a90 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -237,7 +237,7 @@ object Flags { final val AccessorOrSealed = Accessor.toCommonFlags - /** A mutable var */ + /** A mutable var */ final val Mutable = termFlag(12, "mutable") /** Symbol is local to current class (i.e. private[this] or protected[this] @@ -252,7 +252,7 @@ object Flags { final val TermParamAccessor = ParamAccessor.toTermFlags final val TypeParamAccessor = ParamAccessor.toTypeFlags - /** A value or class implementing a module */ + /** A value or class implementing a module */ final val Module = commonFlag(15, "module") final val ModuleVal = Module.toTermFlags final val ModuleClass = Module.toTypeFlags diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index 1eb90b8ebe48..a2a7e200dc8d 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -347,7 +347,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean * - For any other uncurried method type (Fs)T, (|Fs|)|T|. * - For a curried method type (Fs1)(Fs2)T, (|Fs1|,Es2)ET where (Es2)ET = |(Fs2)T|. * - For a polymorphic type [Ts](Ps)T, |(Ps)T| - * _ For a polymorphic type [Ts]T where T is not a method type, ()|T| + * - For a polymorphic type [Ts]T where T is not a method type, ()|T| * - For the class info type of java.lang.Object, the same type without any parents. * - For a class info type of a value class, the same type without any parents. * - For any other class info type with parents Ps, the same type with diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 245b153ba9a6..93a82129da21 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -135,7 +135,7 @@ class Erasure extends Phase with DenotTransformer { thisTransformer => i"The type $tp - ${tp.toString} of class ${tp.getClass} of tree $tree : ${tree.tpe} / ${tree.getClass} is illegal after erasure, phase = ${ctx.phase.prev}") } -object Erasure extends TypeTestsCasts{ +object Erasure extends TypeTestsCasts { import tpd._ @@ -344,7 +344,6 @@ object Erasure extends TypeTestsCasts{ * e.m -> e.[]m if `m` is an array operation other than `clone`. */ override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = { - def mapOwner(sym: Symbol): Symbol = { def recur(owner: Symbol): Symbol = if ((owner eq defn.AnyClass) || (owner eq defn.AnyValClass)) { @@ -362,14 +361,9 @@ object Erasure extends TypeTestsCasts{ val sym = if (owner eq origSym.owner) origSym else owner.info.decl(origSym.name).symbol assert(sym.exists, origSym.showLocated) - def select(qual: Tree, sym: Symbol): Tree = { - val name = tree.typeOpt match { - case tp: NamedType if tp.name.is(ShadowedName) => sym.name.derived(ShadowedName) - case _ => sym.name - } + def select(qual: Tree, sym: Symbol): Tree = untpd.cpy.Select(tree)(qual, sym.name) .withType(NamedType.withFixedSym(qual.tpe, sym)) - } def selectArrayMember(qual: Tree, erasedPre: Type): Tree = if (erasedPre isRef defn.ObjectClass) @@ -447,9 +441,9 @@ object Erasure extends TypeTestsCasts{ } } - /** Besides normal typing, this method collects all arguments - * to a compacted function into a single argument of array type. - */ + /** Besides normal typing, this method collects all arguments + * to a compacted function into a single argument of array type. + */ override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = { val Apply(fun, args) = tree if (fun.symbol == defn.cbnArg) diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 447a003e7d1f..69d8b372ca81 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -31,11 +31,7 @@ import dotty.tools.dotc.util.Positions.Position import dotty.tools.dotc.core.Decorators._ import dotty.tools.dotc.core.Flags -/** This transform eliminates patterns. Right now it's a dummy. - * Awaiting the real pattern matcher. - * elimRepeated is required - * TODO: outer tests are not generated yet. - */ +/** Translates pattern matching. */ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { import dotty.tools.dotc.ast.tpd._ @@ -141,7 +137,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { // the force is needed mainly to deal with the GADT typing hack (we can't detect it otherwise as tp nor pt need contain an abstract type, we're just casting wildly) def _asInstanceOf(b: Symbol, tp: Type): Tree = ref(b).ensureConforms(tp) // andType here breaks t1048 - def _isInstanceOf(b: Symbol, tp: Type): Tree = ref(b).select(defn.Any_isInstanceOf).appliedToType(tp) + def _isInstanceOf(b: Symbol, tp: Type): Tree = ref(b).isInstance(tp) } } diff --git a/library/src/dotty/runtime/Arrays.scala b/library/src/dotty/runtime/Arrays.scala index 9ec5512ad86b..ce0acf2c11d2 100644 --- a/library/src/dotty/runtime/Arrays.scala +++ b/library/src/dotty/runtime/Arrays.scala @@ -19,7 +19,7 @@ object Arrays { /** Convert a sequence to a Java array with element type given by `clazz`. */ def seqToArray[T](xs: Seq[T], clazz: Class[_]): Array[T] = { - val arr = java.lang.reflect.Array.newInstance(clazz, xs.length).asInstanceOf[Array[T]] + val arr = jlr.Array.newInstance(clazz, xs.length).asInstanceOf[Array[T]] xs.copyToArray(arr) arr } From 00044b6f1ae4d6473ca6f68bafd639d671898e85 Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Thu, 30 Mar 2017 14:22:19 +0200 Subject: [PATCH 02/11] Implement HList based Tuples Changes are as follows: - New types for tuples in dotty library: Tuple = Unit | TupleCons Head Tail <: Tuple - Desugaring uses this structure instead of the scala.TupleN for types and expressions - New TupleRewrites phase does rewrites the HList structure into scala.TupleN like case classes (for small arities) or a case class wrapping an Array (for large arities) --- compiler/src/dotty/tools/dotc/Compiler.scala | 3 +- .../src/dotty/tools/dotc/ast/Desugar.scala | 30 ++- .../dotty/tools/dotc/core/Definitions.scala | 37 +-- .../src/dotty/tools/dotc/core/StdNames.scala | 1 + .../tools/dotc/printing/RefinedPrinter.scala | 2 +- .../dotc/reporting/diagnostic/messages.scala | 16 -- .../tools/dotc/transform/TupleRewrites.scala | 215 ++++++++++++++++++ .../src/dotty/tools/dotc/typer/Typer.scala | 14 +- library/src/dotty/tuples.scala | 95 ++++++++ 9 files changed, 364 insertions(+), 49 deletions(-) create mode 100644 compiler/src/dotty/tools/dotc/transform/TupleRewrites.scala create mode 100644 library/src/dotty/tuples.scala diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index 8ee016117de3..5901db40fa63 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -48,7 +48,8 @@ class Compiler { List(new Pickler), // Generate TASTY info List(new FirstTransform, // Some transformations to put trees into a canonical form new CheckReentrant), // Internal use only: Check that compiled program has no data races involving global vars - List(new CheckStatic, // Check restrictions that apply to @static members + List(new TupleRewrites, // Rewrite tuple apply and unapply + new CheckStatic, // Check restrictions that apply to @static members new ElimRepeated, // Rewrite vararg parameters and arguments new RefChecks, // Various checks mostly related to abstract members and overriding new NormalizeFlags, // Rewrite some definition flags diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 264b1b2f4623..a586d59ff1f5 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -414,10 +414,10 @@ object desugar { } } - // Above MaxTupleArity we extend Product instead of ProductN, in this + // Above MaxImplementedTupleArity we extend Product instead of ProductN, in this // case we need to synthesise productElement & productArity. def largeProductMeths = - if (arity > Definitions.MaxTupleArity) productElement :: productArity :: Nil + if (arity > Definitions.MaxImplementedTupleArity) productElement :: productArity :: Nil else Nil if (isCaseClass) @@ -432,7 +432,7 @@ object desugar { if (targs.isEmpty) tycon else AppliedTypeTree(tycon, targs) } def product = - if (arity > Definitions.MaxTupleArity) scalaDot(str.Product.toTypeName) + if (arity > Definitions.MaxImplementedTupleArity) scalaDot(str.Product.toTypeName) else productConstr(arity) // Case classes and case objects get Product/ProductN parents @@ -1068,14 +1068,22 @@ object desugar { t case Tuple(ts) => val arity = ts.length - def tupleTypeRef = defn.TupleType(arity) - if (arity > Definitions.MaxTupleArity) { - ctx.error(TupleTooLong(ts), tree.pos) - unitLiteral - } else if (arity == 1) ts.head - else if (ctx.mode is Mode.Type) AppliedTypeTree(ref(tupleTypeRef), ts) - else if (arity == 0) unitLiteral - else Apply(ref(tupleTypeRef.classSymbol.companionModule.valRef), ts) + arity match { + case 0 => unitLiteral + case _ if ctx.mode is Mode.Type => + // Transforming Tuple types: (T1, T2) → TupleCons[T1, TupleCons[T2, Unit]] + val nil: Tree = TypeTree(defn.UnitType) + def hconsType(l: Tree, r: Tree): Tree = + AppliedTypeTree(ref(defn.TupleConsType), l :: r :: Nil) + ts.foldRight(nil)(hconsType) + case _ => + // Transforming Tuple trees: (T1, T2, ..., TN) → TupleCons(T1, TupleCons(T2, ... (TupleCons(TN, ()))) + val nil: Tree = unitLiteral + val cons = defn.TupleConsType.classSymbol.companionModule.valRef + def consTree(l: Tree, r: Tree): Tree = + Apply(ref(cons), l :: r :: Nil) + ts.foldRight(nil)(consTree) + } case WhileDo(cond, body) => // {