From a415ca1ab713f92788262057d9810d937dc7499a Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 20 Oct 2015 09:47:21 +0200 Subject: Allow existential types in hk types --- src/dotty/tools/dotc/core/Types.scala | 44 +++++++++++++++++++------- src/dotty/tools/dotc/transform/PostTyper.scala | 2 +- src/dotty/tools/dotc/typer/TypeAssigner.scala | 3 +- src/dotty/tools/dotc/typer/Typer.scala | 29 +---------------- test/dotc/tests.scala | 1 - tests/neg/partialApplications.scala | 11 ------- tests/pos/polyalias.scala | 6 ++++ 7 files changed, 41 insertions(+), 55 deletions(-) delete mode 100644 tests/neg/partialApplications.scala diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 58a6d226d..3fe5afb33 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -846,14 +846,16 @@ object Types { * (*) normalizes means: follow instantiated typevars and aliases. */ def lookupRefined(name: Name)(implicit ctx: Context): Type = { - def loop(pre: Type, resolved: List[Name]): Type = pre.stripTypeVar match { + def loop(pre: Type): Type = pre.stripTypeVar match { case pre: RefinedType => object instantiate extends TypeMap { var isSafe = true def apply(tp: Type): Type = tp match { case TypeRef(RefinedThis(`pre`), name) if name.isLambdaArgName => - val TypeAlias(alias) = member(name).info - alias + member(name).info match { + case TypeAlias(alias) => alias + case _ => isSafe = false; tp + } case tp: TypeVar if !tp.inst.exists => isSafe = false tp @@ -861,23 +863,37 @@ object Types { mapOver(tp) } } - def betaReduce(tp: Type) = { - val lam = pre.parent.LambdaClass(forcing = false) - if (lam.exists && lam.typeParams.forall(tparam => resolved.contains(tparam.name))) { - val reduced = instantiate(tp) + def instArg(tp: Type): Type = tp match { + case tp @ TypeAlias(TypeRef(RefinedThis(`pre`), name)) if name.isLambdaArgName => + member(name).info match { + case TypeAlias(alias) => tp.derivedTypeAlias(alias) // needed to keep variance + case bounds => bounds + } + case _ => + instantiate(tp) + } + def instTop(tp: Type): Type = tp.stripTypeVar match { + case tp: RefinedType => + tp.derivedRefinedType(instTop(tp.parent), tp.refinedName, instArg(tp.refinedInfo)) + case _ => + instantiate(tp) + } + /** Reduce rhs of $hkApply to make it stand alone */ + def betaReduce(tp: Type) = + if (pre.parent.isSafeLambda) { + val reduced = instTop(tp) if (instantiate.isSafe) reduced else NoType } else NoType - } pre.refinedInfo match { case TypeAlias(alias) => - if (pre.refinedName ne name) loop(pre.parent, pre.refinedName :: resolved) + if (pre.refinedName ne name) loop(pre.parent) else if (!pre.refinementRefersToThis) alias else alias match { case TypeRef(RefinedThis(`pre`), aliasName) => lookupRefined(aliasName) // (1) case _ => if (name == tpnme.hkApply) betaReduce(alias) else NoType // (2) } - case _ => loop(pre.parent, resolved) + case _ => loop(pre.parent) } case RefinedThis(binder) => binder.lookupRefined(name) @@ -887,14 +903,14 @@ object Types { WildcardType case pre: TypeRef => pre.info match { - case TypeAlias(alias) => loop(alias, resolved) + case TypeAlias(alias) => loop(alias) case _ => NoType } case _ => NoType } - loop(this, Nil) + loop(this) } /** The type , reduced if possible */ @@ -1886,6 +1902,10 @@ object Types { s"variance mismatch for $this, $cls, ${cls.typeParams}, ${cls.typeParams.apply(refinedName.LambdaArgIndex).variance}, ${refinedInfo.variance}") case _ => } + if (Config.checkProjections && + (refinedName == tpnme.hkApply || refinedName.isLambdaArgName) && + parent.noHK) + assert(false, s"illegal refinement of first-order type: $this") this } diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala index 7a25a9870..fc4427277 100644 --- a/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/src/dotty/tools/dotc/transform/PostTyper.scala @@ -71,7 +71,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran /** Check bounds of AppliedTypeTrees. * Replace type trees with TypeTree nodes. * Replace constant expressions with Literal nodes. - * Note: Demanding idempotency instead of purityin literalize is strictly speaking too loose. + * Note: Demanding idempotency instead of purity in literalize is strictly speaking too loose. * Example * * object O { final val x = 42; println("43") } diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala index 7225ede14..25030012c 100644 --- a/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -344,10 +344,9 @@ trait TypeAssigner { def assignType(tree: untpd.Return)(implicit ctx: Context) = tree.withType(defn.NothingType) - def assignType(tree: untpd.Try, expr: Tree, cases: List[CaseDef])(implicit ctx: Context) = { + def assignType(tree: untpd.Try, expr: Tree, cases: List[CaseDef])(implicit ctx: Context) = if (cases.isEmpty) tree.withType(expr.tpe) else tree.withType(ctx.typeComparer.lub(expr.tpe :: cases.tpes)) - } def assignType(tree: untpd.SeqLiteral, elems: List[Tree])(implicit ctx: Context) = tree match { case tree: JavaSeqLiteral => diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 6510ba35b..745eee8f8 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -848,34 +848,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } val args1 = args.zipWithConserve(tparams)(typedArg(_, _)).asInstanceOf[List[Tree]] // check that arguments conform to bounds is done in phase PostTyper - val tree1 = assignType(cpy.AppliedTypeTree(tree)(tpt1, args1), tpt1, args1) - if (tree1.tpe.isHKApply) - for (arg @ TypeBoundsTree(_, _) <- args1) - ctx.error("illegal wildcard type argument; does not correspond to type parameter of a class", arg.pos) - // The reason for outlawing such arguments is illustrated by the following example. - // Say we have - // - // type RMap[A, B] = Map[B, A] - // - // Then - // - // Rmap[_, Int] - // - // translates to - // - // Lambda$I { type hk$0; type hk$1 = Int; type $apply = Map[$hk1, $hk0] } # $apply - // - // Let's call the last type T. You would expect that - // - // Map[Int, String] <: RMap[_, Int] - // - // But that's not the case given the standard subtyping rules. In fact, the rhs reduces to - // - // Map[Int, T # $hk0] - // - // That means the second argument to `Map` is unknown and String is certainly not a subtype of it. - // To avoid the surprise we outlaw problematic wildcard arguments from the start. - tree1 + assignType(cpy.AppliedTypeTree(tree)(tpt1, args1), tpt1, args1) } } diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 337285c04..aaf3e6c4e 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -156,7 +156,6 @@ class tests extends CompilerTest { @Test def neg_traitParamsMixin = compileFile(negDir, "traitParamsMixin", xerrors = 2) @Test def neg_firstError = compileFile(negDir, "firstError", xerrors = 3) @Test def neg_implicitLowerBound = compileFile(negDir, "implicit-lower-bound", xerrors = 1) - @Test def neg_partialApplications = compileFile(negDir, "partialApplications", xerrors = 8) @Test def neg_validate = compileFile(negDir, "validate", xerrors = 18) @Test def neg_validateParsing = compileFile(negDir, "validate-parsing", xerrors = 7) @Test def neg_validateRefchecks = compileFile(negDir, "validate-refchecks", xerrors = 2) diff --git a/tests/neg/partialApplications.scala b/tests/neg/partialApplications.scala deleted file mode 100644 index 67f6cf059..000000000 --- a/tests/neg/partialApplications.scala +++ /dev/null @@ -1,11 +0,0 @@ -object Test { - - type RMap[X, Y] = Map[Y, X] - val m = Map[Int, String]() - val ts: RMap[_, Int] = m // erorr // error - val us: RMap[String, _] = m // error // error - val vs: RMap[_, _] = m // error // error // error - val zz: RMap = m // error - -} - diff --git a/tests/pos/polyalias.scala b/tests/pos/polyalias.scala index 6ce0e3230..c9d4e0426 100644 --- a/tests/pos/polyalias.scala +++ b/tests/pos/polyalias.scala @@ -23,4 +23,10 @@ object Test { val rm: RMap[Int, String] = Map[String, Int]() val rrm: RRMap[Int, String] = Map[Int, String]() + val zz: RMap[_, Int] = Map[Int, String]() + val m = Map[Int, String]() + val ts: RMap[_, Int] = m + val us: RMap[String, _] = m + val vs: RMap[_, _] = m + } -- cgit v1.2.3 From 396df3b7bb954c674911b8e144ba0e1c77ffab00 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 20 Oct 2015 09:52:57 +0200 Subject: Add test case --- tests/pending/pos/GenTraversableFactory.scala | 252 ++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 tests/pending/pos/GenTraversableFactory.scala diff --git a/tests/pending/pos/GenTraversableFactory.scala b/tests/pending/pos/GenTraversableFactory.scala new file mode 100644 index 000000000..2092c0c5f --- /dev/null +++ b/tests/pending/pos/GenTraversableFactory.scala @@ -0,0 +1,252 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + + +package scala +package collection +package generic + +import scala.language.higherKinds + +/** A template for companion objects of `Traversable` and subclasses thereof. + * This class provides a set of operations to create `$Coll` objects. + * It is typically inherited by companion objects of subclasses of `Traversable`. + * + * @since 2.8 + * + * @define coll collection + * @define Coll `Traversable` + * @define factoryInfo + * This object provides a set of operations to create `$Coll` values. + * @author Martin Odersky + * @version 2.8 + * @define canBuildFromInfo + * The standard `CanBuildFrom` instance for $Coll objects. + * @see CanBuildFrom + * @define genericCanBuildFromInfo + * The standard `CanBuildFrom` instance for $Coll objects. + * The created value is an instance of class `GenericCanBuildFrom`, + * which forwards calls to create a new builder to the + * `genericBuilder` method of the requesting collection. + * @see CanBuildFrom + * @see GenericCanBuildFrom + */ +abstract class GenTraversableFactory[CC[X] <: GenTraversable[X] with GenericTraversableTemplate[X, CC]] +extends GenericCompanion[CC] { + + private[this] val ReusableCBFInstance: GenericCanBuildFrom[Nothing] = new GenericCanBuildFrom[Nothing] { + override def apply() = newBuilder[Nothing] + } + def ReusableCBF: GenericCanBuildFrom[Nothing] = ReusableCBFInstance + + /** A generic implementation of the `CanBuildFrom` trait, which forwards + * all calls to `apply(from)` to the `genericBuilder` method of + * $coll `from`, and which forwards all calls of `apply()` to the + * `newBuilder` method of this factory. + */ + class GenericCanBuildFrom[A] extends CanBuildFrom[CC[_], A, CC[A]] { + /** Creates a new builder on request of a collection. + * @param from the collection requesting the builder to be created. + * @return the result of invoking the `genericBuilder` method on `from`. + */ + def apply(from: Coll) = from.genericBuilder[A] + + /** Creates a new builder from scratch + * @return the result of invoking the `newBuilder` method of this factory. + */ + def apply() = newBuilder[A] + } + + /** Concatenates all argument collections into a single $coll. + * + * @param xss the collections that are to be concatenated. + * @return the concatenation of all the collections. + */ + def concat[A](xss: Traversable[A]*): CC[A] = { + val b = newBuilder[A] + // At present we're using IndexedSeq as a proxy for "has a cheap size method". + if (xss forall (_.isInstanceOf[IndexedSeq[_]])) + b.sizeHint(xss.map(_.size).sum) + + for (xs <- xss.seq) b ++= xs + b.result() + } + + /** Produces a $coll containing the results of some element computation a number of times. + * @param n the number of elements contained in the $coll. + * @param elem the element computation + * @return A $coll that contains the results of `n` evaluations of `elem`. + */ + def fill[A](n: Int)(elem: => A): CC[A] = { + val b = newBuilder[A] + b.sizeHint(n) + var i = 0 + while (i < n) { + b += elem + i += 1 + } + b.result() + } + + /** Produces a two-dimensional $coll containing the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param elem the element computation + * @return A $coll that contains the results of `n1 x n2` evaluations of `elem`. + */ + def fill[A](n1: Int, n2: Int)(elem: => A): CC[CC[A]] = + tabulate(n1)(_ => fill(n2)(elem)) + + /** Produces a three-dimensional $coll containing the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param elem the element computation + * @return A $coll that contains the results of `n1 x n2 x n3` evaluations of `elem`. + */ + def fill[A](n1: Int, n2: Int, n3: Int)(elem: => A): CC[CC[CC[A]]] = + tabulate(n1)(_ => fill(n2, n3)(elem)) + + /** Produces a four-dimensional $coll containing the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param elem the element computation + * @return A $coll that contains the results of `n1 x n2 x n3 x n4` evaluations of `elem`. + */ + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => A): CC[CC[CC[CC[A]]]] = + tabulate(n1)(_ => fill(n2, n3, n4)(elem)) + + /** Produces a five-dimensional $coll containing the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param n5 the number of elements in the 5th dimension + * @param elem the element computation + * @return A $coll that contains the results of `n1 x n2 x n3 x n4 x n5` evaluations of `elem`. + */ + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => A): CC[CC[CC[CC[CC[A]]]]] = + tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem)) + + /** Produces a $coll containing values of a given function over a range of integer values starting from 0. + * @param n The number of elements in the $coll + * @param f The function computing element values + * @return A $coll consisting of elements `f(0), ..., f(n -1)` + */ + def tabulate[A](n: Int)(f: Int => A): CC[A] = { + val b = newBuilder[A] + b.sizeHint(n) + var i = 0 + while (i < n) { + b += f(i) + i += 1 + } + b.result() + } + + /** Produces a two-dimensional $coll containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param f The function computing element values + * @return A $coll consisting of elements `f(i1, i2)` + * for `0 <= i1 < n1` and `0 <= i2 < n2`. + */ + def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[CC[A]] = + tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) + + /** Produces a three-dimensional $coll containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param f The function computing element values + * @return A $coll consisting of elements `f(i1, i2, i3)` + * for `0 <= i1 < n1`, `0 <= i2 < n2`, and `0 <= i3 < n3`. + */ + def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]]] = + tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _))) + + /** Produces a four-dimensional $coll containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param f The function computing element values + * @return A $coll consisting of elements `f(i1, i2, i3, i4)` + * for `0 <= i1 < n1`, `0 <= i2 < n2`, `0 <= i3 < n3`, and `0 <= i4 < n4`. + */ + def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => A): CC[CC[CC[CC[A]]]] = + tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _))) + + /** Produces a five-dimensional $coll containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param n5 the number of elements in the 5th dimension + * @param f The function computing element values + * @return A $coll consisting of elements `f(i1, i2, i3, i4, i5)` + * for `0 <= i1 < n1`, `0 <= i2 < n2`, `0 <= i3 < n3`, `0 <= i4 < n4`, and `0 <= i5 < n5`. + */ + def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => A): CC[CC[CC[CC[CC[A]]]]] = + tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) + + /** Produces a $coll containing a sequence of increasing of integers. + * + * @param start the first element of the $coll + * @param end the end value of the $coll (the first value NOT contained) + * @return a $coll with values `start, start + 1, ..., end - 1` + */ + def range[T: Integral](start: T, end: T): CC[T] = range(start, end, implicitly[Integral[T]].one) + + /** Produces a $coll containing equally spaced values in some integer interval. + * @param start the start value of the $coll + * @param end the end value of the $coll (the first value NOT contained) + * @param step the difference between successive elements of the $coll (must be positive or negative) + * @return a $coll with values `start, start + step, ...` up to, but excluding `end` + */ + def range[T: Integral](start: T, end: T, step: T): CC[T] = { + val num = implicitly[Integral[T]] + import num._ + + if (step == zero) throw new IllegalArgumentException("zero step") + val b = newBuilder[T] + b sizeHint immutable.NumericRange.count(start, end, step, isInclusive = false) + var i = start + while (if (step < zero) end < i else i < end) { + b += i + i += step + } + b.result() + } + + /** Produces a $coll containing repeated applications of a function to a start value. + * + * @param start the start value of the $coll + * @param len the number of elements contained inthe $coll + * @param f the function that's repeatedly applied + * @return a $coll with `len` values in the sequence `start, f(start), f(f(start)), ...` + */ + def iterate[A](start: A, len: Int)(f: A => A): CC[A] = { + val b = newBuilder[A] + if (len > 0) { + b.sizeHint(len) + var acc = start + var i = 1 + b += acc + + while (i < len) { + acc = f(acc) + i += 1 + b += acc + } + } + b.result() + } +} -- cgit v1.2.3 From 308e637dd35ba8c5e46c1bacf309ad2d82cd93bd Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 24 Oct 2015 12:31:46 +0200 Subject: Revise typeParams to account for existential hk types --- src/dotty/tools/dotc/core/TypeApplications.scala | 64 +++++++++++++--------- .../tools/dotc/transform/TypeTestsCasts.scala | 1 - 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index 47935f79e..f63005d8a 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -48,33 +48,43 @@ class TypeApplications(val self: Type) extends AnyVal { * For a typeref referring to a class, the type parameters of the class. * For a typeref referring to a Lambda class, the type parameters of * its right hand side or upper bound. - * For a refinement type, the type parameters of its parent, unless the refinement - * re-binds the type parameter with a type-alias. - * For any other non-singleton type proxy, the type parameters of its underlying type. - * For any other type, the empty list. + * For a refinement type, the type parameters of its parent, dropping + * any type parameter that is-rebound by the refinement. "Re-bind" means: + * The refinement contains a TypeAlias for the type parameter, or + * it introduces bounds for the type parameter, and we are not in the + * special case of a type Lambda, where a LambdaTrait gets refined + * with the bounds on its hk args. See `LambdaAbstract`, where these + * types get introduced, and see `isBoundedLambda` below for the test. */ final def typeParams(implicit ctx: Context): List[TypeSymbol] = /*>|>*/ track("typeParams") /*<|<*/ { self match { - case tp: ClassInfo => - tp.cls.typeParams - case tp: TypeRef => - val tsym = tp.typeSymbol + case self: ClassInfo => + self.cls.typeParams + case self: TypeRef => + val tsym = self.typeSymbol if (tsym.isClass) tsym.typeParams - else if (tsym.isAliasType) tp.underlying.typeParams + else if (tsym.isAliasType) self.underlying.typeParams else { val lam = LambdaClass(forcing = false) if (lam.exists) lam.typeParams else Nil } - case tp: RefinedType => - val tparams = tp.parent.typeParams - tp.refinedInfo match { - case rinfo: TypeAlias => tparams.filterNot(_.name == tp.refinedName) - case _ => tparams + case self: RefinedType => + def isBoundedLambda(tp: Type): Boolean = tp match { + case tp: TypeRef => tp.typeSymbol.isLambdaTrait + case tp: RefinedType => tp.refinedName.isLambdaArgName && isBoundedLambda(tp.parent) + case _ => false + } + val tparams = self.parent.typeParams + self.refinedInfo match { + case rinfo: TypeBounds if rinfo.isAlias || isBoundedLambda(self) => + tparams.filterNot(_.name == self.refinedName) + case _ => + tparams } - case tp: SingletonType => + case self: SingletonType => Nil - case tp: TypeProxy => - tp.underlying.typeParams + case self: TypeProxy => + self.underlying.typeParams case _ => Nil } @@ -91,23 +101,23 @@ class TypeApplications(val self: Type) extends AnyVal { */ final def rawTypeParams(implicit ctx: Context): List[TypeSymbol] = { self match { - case tp: ClassInfo => - tp.cls.typeParams - case tp: TypeRef => - val tsym = tp.typeSymbol + case self: ClassInfo => + self.cls.typeParams + case self: TypeRef => + val tsym = self.typeSymbol if (tsym.isClass) tsym.typeParams - else if (tsym.isAliasType) tp.underlying.rawTypeParams + else if (tsym.isAliasType) self.underlying.rawTypeParams else Nil case _: BoundType | _: SingletonType => Nil - case tp: TypeProxy => - tp.underlying.rawTypeParams + case self: TypeProxy => + self.underlying.rawTypeParams case _ => Nil } } - /** If type `tp` is equal, aliased-to, or upperbounded-by a type of the form + /** If type `self` is equal, aliased-to, or upperbounded-by a type of the form * `LambdaXYZ { ... }`, the class symbol of that type, otherwise NoSymbol. * symbol of that type, otherwise NoSymbol. * @param forcing if set, might force completion. If not, never forces @@ -125,7 +135,7 @@ class TypeApplications(val self: Type) extends AnyVal { NoSymbol }} - /** Is type `tp` equal, aliased-to, or upperbounded-by a type of the form + /** Is type `self` equal, aliased-to, or upperbounded-by a type of the form * `LambdaXYZ { ... }`? */ def isLambda(implicit ctx: Context): Boolean = @@ -137,7 +147,7 @@ class TypeApplications(val self: Type) extends AnyVal { def isSafeLambda(implicit ctx: Context): Boolean = LambdaClass(forcing = false).exists - /** Is type `tp` a Lambda with all hk$i fields fully instantiated? */ + /** Is type `self` a Lambda with all hk$i fields fully instantiated? */ def isInstantiatedLambda(implicit ctx: Context): Boolean = isSafeLambda && typeParams.isEmpty diff --git a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala index 98b8357b9..b2d45b661 100644 --- a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala +++ b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala @@ -27,7 +27,6 @@ import ValueClasses._ * Unfortunately this phase ended up being not Y-checkable unless types are erased. A cast to an ConstantType(3) or x.type * cannot be rewritten before erasure. */ - trait TypeTestsCasts { import ast.tpd._ -- cgit v1.2.3 From 4f15c103cca72a0f673bbc07025120e5308360ec Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 24 Oct 2015 16:23:12 +0200 Subject: Don't drop $apply when eliminating existentials in unpickler --- src/dotty/tools/dotc/core/TypeApplications.scala | 2 +- src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index f63005d8a..7274c1f70 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -235,7 +235,7 @@ class TypeApplications(val self: Type) extends AnyVal { } /** Same as isHK, except we classify all abstract types as HK, - * (they must be, because the are applied). This avoids some forcing and + * (they must be, because they are applied). This avoids some forcing and * CyclicReference errors of the standard isHK. */ def isKnownHK(tp: Type): Boolean = tp match { diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index af33ce3c2..e80712566 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -620,7 +620,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas tp.derivedRefinedType(parent1, name, info) } case tp @ TypeRef(pre, tpnme.hkApply) => - elim(pre) + tp.derivedSelect(elim(pre)) case _ => tp } -- cgit v1.2.3 From 538764f17ee1bb94dbfb2d2fb4241c55af3dc896 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 24 Oct 2015 17:37:29 +0200 Subject: Remove redundant tests isHK already does a dealias. --- src/dotty/tools/dotc/typer/Checking.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala index fa417beec..b8b4c89b4 100644 --- a/src/dotty/tools/dotc/typer/Checking.scala +++ b/src/dotty/tools/dotc/typer/Checking.scala @@ -398,9 +398,7 @@ trait Checking { if (tpt.tpe.isHK && !ctx.compilationUnit.isJava) { // be more lenient with missing type params in Java, // needed to make pos/java-interop/t1196 work. - val alias = tpt.tpe.dealias - if (alias.isHK) errorTree(tpt, d"missing type parameter for ${tpt.tpe}") - else tpt.withType(alias) + errorTree(tpt, d"missing type parameter for ${tpt.tpe}") } else tpt } -- cgit v1.2.3 From cdcc7e3592386fcfe0f2b9915db78a894ac92536 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 24 Oct 2015 17:48:21 +0200 Subject: Add fixed version of GenTraversableFactory. There is still an issue because math uses inner classes named Ops which shadow each other. Dotty can't handle it, so implicit search in `range` goes wrong. The new test has been modified to work around that issue. --- tests/pos/GenTraversableFactory.scala | 256 ++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 tests/pos/GenTraversableFactory.scala diff --git a/tests/pos/GenTraversableFactory.scala b/tests/pos/GenTraversableFactory.scala new file mode 100644 index 000000000..e5cba4501 --- /dev/null +++ b/tests/pos/GenTraversableFactory.scala @@ -0,0 +1,256 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + + +package scala +package collection +package generic + +import scala.language.higherKinds + +/** A template for companion objects of `Traversable` and subclasses thereof. + * This class provides a set of operations to create `$Coll` objects. + * It is typically inherited by companion objects of subclasses of `Traversable`. + * + * @since 2.8 + * + * @define coll collection + * @define Coll `Traversable` + * @define factoryInfo + * This object provides a set of operations to create `$Coll` values. + * @author Martin Odersky + * @version 2.8 + * @define canBuildFromInfo + * The standard `CanBuildFrom` instance for $Coll objects. + * @see CanBuildFrom + * @define genericCanBuildFromInfo + * The standard `CanBuildFrom` instance for $Coll objects. + * The created value is an instance of class `GenericCanBuildFrom`, + * which forwards calls to create a new builder to the + * `genericBuilder` method of the requesting collection. + * @see CanBuildFrom + * @see GenericCanBuildFrom + */ +abstract class GenTraversableFactory[CC[X] <: GenTraversable[X] with GenericTraversableTemplate[X, CC]] +extends GenericCompanion[CC] { + + private[this] val ReusableCBFInstance: GenericCanBuildFrom[Nothing] = new GenericCanBuildFrom[Nothing] { + override def apply() = newBuilder[Nothing] + } + def ReusableCBF: GenericCanBuildFrom[Nothing] = ReusableCBFInstance + + /** A generic implementation of the `CanBuildFrom` trait, which forwards + * all calls to `apply(from)` to the `genericBuilder` method of + * $coll `from`, and which forwards all calls of `apply()` to the + * `newBuilder` method of this factory. + */ + class GenericCanBuildFrom[A] extends CanBuildFrom[CC[_], A, CC[A]] { + /** Creates a new builder on request of a collection. + * @param from the collection requesting the builder to be created. + * @return the result of invoking the `genericBuilder` method on `from`. + */ + def apply(from: Coll) = from.genericBuilder[A] + + /** Creates a new builder from scratch + * @return the result of invoking the `newBuilder` method of this factory. + */ + def apply() = newBuilder[A] + } + + /** Concatenates all argument collections into a single $coll. + * + * @param xss the collections that are to be concatenated. + * @return the concatenation of all the collections. + */ + def concat[A](xss: Traversable[A]*): CC[A] = { + val b = newBuilder[A] + // At present we're using IndexedSeq as a proxy for "has a cheap size method". + if (xss forall (_.isInstanceOf[IndexedSeq[_]])) + b.sizeHint(xss.map(_.size).sum) + + for (xs <- xss.seq) b ++= xs + b.result() + } + + /** Produces a $coll containing the results of some element computation a number of times. + * @param n the number of elements contained in the $coll. + * @param elem the element computation + * @return A $coll that contains the results of `n` evaluations of `elem`. + */ + def fill[A](n: Int)(elem: => A): CC[A] = { + val b = newBuilder[A] + b.sizeHint(n) + var i = 0 + while (i < n) { + b += elem + i += 1 + } + b.result() + } + + /** Produces a two-dimensional $coll containing the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param elem the element computation + * @return A $coll that contains the results of `n1 x n2` evaluations of `elem`. + */ + def fill[A](n1: Int, n2: Int)(elem: => A): CC[CC[A]] = + tabulate(n1)(_ => fill(n2)(elem)) + + /** Produces a three-dimensional $coll containing the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param elem the element computation + * @return A $coll that contains the results of `n1 x n2 x n3` evaluations of `elem`. + */ + def fill[A](n1: Int, n2: Int, n3: Int)(elem: => A): CC[CC[CC[A]]] = + tabulate(n1)(_ => fill(n2, n3)(elem)) + + /** Produces a four-dimensional $coll containing the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param elem the element computation + * @return A $coll that contains the results of `n1 x n2 x n3 x n4` evaluations of `elem`. + */ + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => A): CC[CC[CC[CC[A]]]] = + tabulate(n1)(_ => fill(n2, n3, n4)(elem)) + + /** Produces a five-dimensional $coll containing the results of some element computation a number of times. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param n5 the number of elements in the 5th dimension + * @param elem the element computation + * @return A $coll that contains the results of `n1 x n2 x n3 x n4 x n5` evaluations of `elem`. + */ + def fill[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => A): CC[CC[CC[CC[CC[A]]]]] = + tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem)) + + /** Produces a $coll containing values of a given function over a range of integer values starting from 0. + * @param n The number of elements in the $coll + * @param f The function computing element values + * @return A $coll consisting of elements `f(0), ..., f(n -1)` + */ + def tabulate[A](n: Int)(f: Int => A): CC[A] = { + val b = newBuilder[A] + b.sizeHint(n) + var i = 0 + while (i < n) { + b += f(i) + i += 1 + } + b.result() + } + + /** Produces a two-dimensional $coll containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param f The function computing element values + * @return A $coll consisting of elements `f(i1, i2)` + * for `0 <= i1 < n1` and `0 <= i2 < n2`. + */ + def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[CC[A]] = + tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) + + /** Produces a three-dimensional $coll containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param f The function computing element values + * @return A $coll consisting of elements `f(i1, i2, i3)` + * for `0 <= i1 < n1`, `0 <= i2 < n2`, and `0 <= i3 < n3`. + */ + def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]]] = + tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _))) + + /** Produces a four-dimensional $coll containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param f The function computing element values + * @return A $coll consisting of elements `f(i1, i2, i3, i4)` + * for `0 <= i1 < n1`, `0 <= i2 < n2`, `0 <= i3 < n3`, and `0 <= i4 < n4`. + */ + def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => A): CC[CC[CC[CC[A]]]] = + tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _))) + + /** Produces a five-dimensional $coll containing values of a given function over ranges of integer values starting from 0. + * @param n1 the number of elements in the 1st dimension + * @param n2 the number of elements in the 2nd dimension + * @param n3 the number of elements in the 3nd dimension + * @param n4 the number of elements in the 4th dimension + * @param n5 the number of elements in the 5th dimension + * @param f The function computing element values + * @return A $coll consisting of elements `f(i1, i2, i3, i4, i5)` + * for `0 <= i1 < n1`, `0 <= i2 < n2`, `0 <= i3 < n3`, `0 <= i4 < n4`, and `0 <= i5 < n5`. + */ + def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => A): CC[CC[CC[CC[CC[A]]]]] = + tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) + + /** Produces a $coll containing a sequence of increasing of integers. + * + * @param start the first element of the $coll + * @param end the end value of the $coll (the first value NOT contained) + * @return a $coll with values `start, start + 1, ..., end - 1` + */ + def range[T: Integral](start: T, end: T): CC[T] = range(start, end, implicitly[Integral[T]].one) + + /** Produces a $coll containing equally spaced values in some integer interval. + * @param start the start value of the $coll + * @param end the end value of the $coll (the first value NOT contained) + * @param step the difference between successive elements of the $coll (must be positive or negative) + * @return a $coll with values `start, start + step, ...` up to, but excluding `end` + */ + def range[T: Integral](start: T, end: T, step: T): CC[T] = { + val num = implicitly[Integral[T]] + import num._ + + if (step == zero) throw new IllegalArgumentException("zero step") + val b = newBuilder[T] + b sizeHint immutable.NumericRange.count(start, end, step, isInclusive = false) + var i = start + + { + val ord: Ordering[T] = num + implicit val ops: T => ord.Ops = ord.mkOrderingOps + while (if (step < zero) end < i else i < end) { + b += i + i += step + }} + b.result() + } + + /** Produces a $coll containing repeated applications of a function to a start value. + * + * @param start the start value of the $coll + * @param len the number of elements contained inthe $coll + * @param f the function that's repeatedly applied + * @return a $coll with `len` values in the sequence `start, f(start), f(f(start)), ...` + */ + def iterate[A](start: A, len: Int)(f: A => A): CC[A] = { + val b = newBuilder[A] + if (len > 0) { + b.sizeHint(len) + var acc = start + var i = 1 + b += acc + + while (i < len) { + acc = f(acc) + i += 1 + b += acc + } + } + b.result() + } +} -- cgit v1.2.3 From 982d19cbbc058f594e79544888a3be2bfc9a4a06 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 25 Oct 2015 12:16:42 +0100 Subject: Make SuperAccessor and Scala2x "FromStart" flags. --- src/dotty/tools/dotc/core/Flags.scala | 4 +++- src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index 0dde5de95..9ff6cfd95 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -315,6 +315,8 @@ object Flags { /** An unpickled Scala 2.x class */ final val Scala2x = typeFlag(26, "") + final val Scala2xOrSuperAccessor = SuperAccessor.toCommonFlags + /** A method that has default params */ final val DefaultParameterized = termFlag(27, "") @@ -440,7 +442,7 @@ object Flags { AccessFlags | Module | Package | Deferred | Final | MethodOrHKCommon | Param | ParamAccessor | Scala2ExistentialCommon | InSuperCall | Touched | JavaStatic | CovariantOrOuter | ContravariantOrLabel | ExpandedName | AccessorOrSealed | CaseAccessorOrTypeArgument | Fresh | Frozen | Erroneous | ImplicitCommon | Permanent | - SelfNameOrImplClass + Scala2xOrSuperAccessor | SelfNameOrImplClass assert(FromStartFlags.isTermFlags && FromStartFlags.isTypeFlags) // TODO: Should check that FromStartFlags do not change in completion diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index e80712566..a746d81db 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -450,6 +450,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas } def finishSym(sym: Symbol): Symbol = { + if (sym.isClass) sym.setFlag(Scala2x) val owner = sym.owner if (owner.isClass && !( isUnpickleRoot(sym) @@ -535,7 +536,6 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas case denot: ClassDenotation => val selfInfo = if (atEnd) NoType else readTypeRef() setClassInfo(denot, tp, selfInfo) - denot setFlag Scala2x case denot => val tp1 = depoly(tp, denot) denot.info = -- cgit v1.2.3 From dbc668f074b6e121f00a6a63ea55d1a3077f7eb1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 25 Oct 2015 12:29:00 +0100 Subject: Make Lazy and Trait "From Start" flags --- src/dotty/tools/dotc/core/Flags.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index 9ff6cfd95..1271d7f6a 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -227,6 +227,8 @@ object Flags { /** A trait */ final val Trait = typeFlag(10, "") + final val LazyOrTrait = Lazy.toCommonFlags + /** A value or variable accessor (getter or setter) */ final val Accessor = termFlag(11, "") @@ -315,7 +317,7 @@ object Flags { /** An unpickled Scala 2.x class */ final val Scala2x = typeFlag(26, "") - final val Scala2xOrSuperAccessor = SuperAccessor.toCommonFlags + final val SuperAccessorOrScala2x = SuperAccessor.toCommonFlags /** A method that has default params */ final val DefaultParameterized = termFlag(27, "") @@ -442,7 +444,7 @@ object Flags { AccessFlags | Module | Package | Deferred | Final | MethodOrHKCommon | Param | ParamAccessor | Scala2ExistentialCommon | InSuperCall | Touched | JavaStatic | CovariantOrOuter | ContravariantOrLabel | ExpandedName | AccessorOrSealed | CaseAccessorOrTypeArgument | Fresh | Frozen | Erroneous | ImplicitCommon | Permanent | - Scala2xOrSuperAccessor | SelfNameOrImplClass + LazyOrTrait | SuperAccessorOrScala2x | SelfNameOrImplClass assert(FromStartFlags.isTermFlags && FromStartFlags.isTypeFlags) // TODO: Should check that FromStartFlags do not change in completion -- cgit v1.2.3 From 4b1d08928bd008a23fa40490d2998e58a6f06c4d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 25 Oct 2015 12:54:11 +0100 Subject: Represent references to Scala2 inner classes as WithFixedSym types Reason: An inner Scala2 class might be shadowed by a same-named class in a subtype. In Dotty this is disallowed butin Scala 2 it is possible. For instance, math.Numeric and math.Ordering both have an inner class "Ops". Normal TypeRef types could not select the shadowed class in Ordering is the prefix is of type Numeric. --- src/dotty/tools/dotc/core/tasty/TreePickler.scala | 35 +-- .../dotc/core/unpickleScala2/Scala2Unpickler.scala | 5 +- test/dotc/tests.scala | 2 +- tests/neg/selfreq.scala | 8 +- tests/pending/pos/GenTraversableFactory.scala | 252 --------------------- tests/pos/GenTraversableFactory.scala | 8 +- 6 files changed, 31 insertions(+), 279 deletions(-) delete mode 100644 tests/pending/pos/GenTraversableFactory.scala diff --git a/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 58697c196..86bbc893f 100644 --- a/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -148,27 +148,32 @@ class TreePickler(pickler: TastyPickler) { pickleType(tpe.info.bounds.hi) case tpe: WithFixedSym => val sym = tpe.symbol + def pickleRef() = + if (tpe.prefix == NoPrefix) { + writeByte(if (tpe.isType) TYPEREFdirect else TERMREFdirect) + pickleSymRef(sym) + } + else { + assert(tpe.symbol.isClass) + assert(tpe.symbol.is(Flags.Scala2x), tpe.symbol.showLocated) + writeByte(TYPEREF) // should be changed to a new entry that keeps track of prefix, symbol & owner + pickleName(tpe.name) + pickleType(tpe.prefix) + } if (sym.is(Flags.Package)) { writeByte(if (tpe.isType) TYPEREFpkg else TERMREFpkg) pickleName(qualifiedName(sym)) } - else { - assert(tpe.prefix == NoPrefix) - def pickleRef() = { - writeByte(if (tpe.isType) TYPEREFdirect else TERMREFdirect) - pickleSymRef(sym) - } - if (sym is Flags.BindDefinedType) { - registerDef(sym) - writeByte(BIND) - withLength { - pickleName(sym.name) - pickleType(sym.info) - pickleRef() - } + else if (sym is Flags.BindDefinedType) { + registerDef(sym) + writeByte(BIND) + withLength { + pickleName(sym.name) + pickleType(sym.info) + pickleRef() } - else pickleRef() } + else pickleRef() case tpe: TermRefWithSignature => if (tpe.symbol.is(Flags.Package)) picklePackageRef(tpe.symbol) else { diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index a746d81db..c7df3c400 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -686,7 +686,10 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas case _ => } val tycon = - if (isLocal(sym) || pre == NoPrefix) { + if (sym.isClass && sym.is(Scala2x) && !sym.owner.is(Package)) + // used fixed sym for Scala 2 inner classes, because they might be shadowed + TypeRef.withFixedSym(pre, sym.name.asTypeName, sym.asType) + else if (isLocal(sym) || pre == NoPrefix) { val pre1 = if ((pre eq NoPrefix) && (sym is TypeParam)) sym.owner.thisType else pre pre1 select sym } diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index aaf3e6c4e..700dcd494 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -149,7 +149,7 @@ class tests extends CompilerTest { @Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2) @Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8) @Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 6) - @Test def neg_selfreq = compileFile(negDir, "selfreq", xerrors = 4) + @Test def neg_selfreq = compileFile(negDir, "selfreq", xerrors = 3) @Test def neg_singletons = compileFile(negDir, "singletons", xerrors = 8) @Test def neg_shadowedImplicits = compileFile(negDir, "arrayclone-new", xerrors = 2) @Test def neg_traitParamsTyper = compileFile(negDir, "traitParamsTyper", xerrors = 5) diff --git a/tests/neg/selfreq.scala b/tests/neg/selfreq.scala index e75e03c16..ff5725bf2 100644 --- a/tests/neg/selfreq.scala +++ b/tests/neg/selfreq.scala @@ -1,8 +1,8 @@ -trait X { self: Y => +trait X { self: Y => // error: cannot resolve reference to type (Y & X)(X.this).V type T <: self.U - def foo(x: T): T + def foo(x: T): T // error: cannot resolve reference to type (Y & X)(X.this).V def foo(x: String): String } @@ -21,14 +21,14 @@ trait Z { object O { val x: X = ??? - x.foo("a") + x.foo("a") // error: cannot resolve reference to type (Y & X)(X.this).V } import scala.tools.nsc.interpreter.IMain object Test extends dotty.runtime.LegacyApp { val engine = new IMain.Factory getScriptEngine() - engine.asInstanceOf[IMain].settings.usejavacp.value = true + engine.asInstanceOf[IMain].settings.usejavacp.value = true // no longer an error since we unpickle Scala2 inner classes with fixed syms val res2 = engine.asInstanceOf[javax.script.Compilable] res2 compile "8" eval() val res5 = res2 compile """println("hello") ; 8""" diff --git a/tests/pending/pos/GenTraversableFactory.scala b/tests/pending/pos/GenTraversableFactory.scala deleted file mode 100644 index 2092c0c5f..000000000 --- a/tests/pending/pos/GenTraversableFactory.scala +++ /dev/null @@ -1,252 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala -package collection -package generic - -import scala.language.higherKinds - -/** A template for companion objects of `Traversable` and subclasses thereof. - * This class provides a set of operations to create `$Coll` objects. - * It is typically inherited by companion objects of subclasses of `Traversable`. - * - * @since 2.8 - * - * @define coll collection - * @define Coll `Traversable` - * @define factoryInfo - * This object provides a set of operations to create `$Coll` values. - * @author Martin Odersky - * @version 2.8 - * @define canBuildFromInfo - * The standard `CanBuildFrom` instance for $Coll objects. - * @see CanBuildFrom - * @define genericCanBuildFromInfo - * The standard `CanBuildFrom` instance for $Coll objects. - * The created value is an instance of class `GenericCanBuildFrom`, - * which forwards calls to create a new builder to the - * `genericBuilder` method of the requesting collection. - * @see CanBuildFrom - * @see GenericCanBuildFrom - */ -abstract class GenTraversableFactory[CC[X] <: GenTraversable[X] with GenericTraversableTemplate[X, CC]] -extends GenericCompanion[CC] { - - private[this] val ReusableCBFInstance: GenericCanBuildFrom[Nothing] = new GenericCanBuildFrom[Nothing] { - override def apply() = newBuilder[Nothing] - } - def ReusableCBF: GenericCanBuildFrom[Nothing] = ReusableCBFInstance - - /** A generic implementation of the `CanBuildFrom` trait, which forwards - * all calls to `apply(from)` to the `genericBuilder` method of - * $coll `from`, and which forwards all calls of `apply()` to the - * `newBuilder` method of this factory. - */ - class GenericCanBuildFrom[A] extends CanBuildFrom[CC[_], A, CC[A]] { - /** Creates a new builder on request of a collection. - * @param from the collection requesting the builder to be created. - * @return the result of invoking the `genericBuilder` method on `from`. - */ - def apply(from: Coll) = from.genericBuilder[A] - - /** Creates a new builder from scratch - * @return the result of invoking the `newBuilder` method of this factory. - */ - def apply() = newBuilder[A] - } - - /** Concatenates all argument collections into a single $coll. - * - * @param xss the collections that are to be concatenated. - * @return the concatenation of all the collections. - */ - def concat[A](xss: Traversable[A]*): CC[A] = { - val b = newBuilder[A] - // At present we're using IndexedSeq as a proxy for "has a cheap size method". - if (xss forall (_.isInstanceOf[IndexedSeq[_]])) - b.sizeHint(xss.map(_.size).sum) - - for (xs <- xss.seq) b ++= xs - b.result() - } - - /** Produces a $coll containing the results of some element computation a number of times. - * @param n the number of elements contained in the $coll. - * @param elem the element computation - * @return A $coll that contains the results of `n` evaluations of `elem`. - */ - def fill[A](n: Int)(elem: => A): CC[A] = { - val b = newBuilder[A] - b.sizeHint(n) - var i = 0 - while (i < n) { - b += elem - i += 1 - } - b.result() - } - - /** Produces a two-dimensional $coll containing the results of some element computation a number of times. - * @param n1 the number of elements in the 1st dimension - * @param n2 the number of elements in the 2nd dimension - * @param elem the element computation - * @return A $coll that contains the results of `n1 x n2` evaluations of `elem`. - */ - def fill[A](n1: Int, n2: Int)(elem: => A): CC[CC[A]] = - tabulate(n1)(_ => fill(n2)(elem)) - - /** Produces a three-dimensional $coll containing the results of some element computation a number of times. - * @param n1 the number of elements in the 1st dimension - * @param n2 the number of elements in the 2nd dimension - * @param n3 the number of elements in the 3nd dimension - * @param elem the element computation - * @return A $coll that contains the results of `n1 x n2 x n3` evaluations of `elem`. - */ - def fill[A](n1: Int, n2: Int, n3: Int)(elem: => A): CC[CC[CC[A]]] = - tabulate(n1)(_ => fill(n2, n3)(elem)) - - /** Produces a four-dimensional $coll containing the results of some element computation a number of times. - * @param n1 the number of elements in the 1st dimension - * @param n2 the number of elements in the 2nd dimension - * @param n3 the number of elements in the 3nd dimension - * @param n4 the number of elements in the 4th dimension - * @param elem the element computation - * @return A $coll that contains the results of `n1 x n2 x n3 x n4` evaluations of `elem`. - */ - def fill[A](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => A): CC[CC[CC[CC[A]]]] = - tabulate(n1)(_ => fill(n2, n3, n4)(elem)) - - /** Produces a five-dimensional $coll containing the results of some element computation a number of times. - * @param n1 the number of elements in the 1st dimension - * @param n2 the number of elements in the 2nd dimension - * @param n3 the number of elements in the 3nd dimension - * @param n4 the number of elements in the 4th dimension - * @param n5 the number of elements in the 5th dimension - * @param elem the element computation - * @return A $coll that contains the results of `n1 x n2 x n3 x n4 x n5` evaluations of `elem`. - */ - def fill[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => A): CC[CC[CC[CC[CC[A]]]]] = - tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem)) - - /** Produces a $coll containing values of a given function over a range of integer values starting from 0. - * @param n The number of elements in the $coll - * @param f The function computing element values - * @return A $coll consisting of elements `f(0), ..., f(n -1)` - */ - def tabulate[A](n: Int)(f: Int => A): CC[A] = { - val b = newBuilder[A] - b.sizeHint(n) - var i = 0 - while (i < n) { - b += f(i) - i += 1 - } - b.result() - } - - /** Produces a two-dimensional $coll containing values of a given function over ranges of integer values starting from 0. - * @param n1 the number of elements in the 1st dimension - * @param n2 the number of elements in the 2nd dimension - * @param f The function computing element values - * @return A $coll consisting of elements `f(i1, i2)` - * for `0 <= i1 < n1` and `0 <= i2 < n2`. - */ - def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[CC[A]] = - tabulate(n1)(i1 => tabulate(n2)(f(i1, _))) - - /** Produces a three-dimensional $coll containing values of a given function over ranges of integer values starting from 0. - * @param n1 the number of elements in the 1st dimension - * @param n2 the number of elements in the 2nd dimension - * @param n3 the number of elements in the 3nd dimension - * @param f The function computing element values - * @return A $coll consisting of elements `f(i1, i2, i3)` - * for `0 <= i1 < n1`, `0 <= i2 < n2`, and `0 <= i3 < n3`. - */ - def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]]] = - tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _))) - - /** Produces a four-dimensional $coll containing values of a given function over ranges of integer values starting from 0. - * @param n1 the number of elements in the 1st dimension - * @param n2 the number of elements in the 2nd dimension - * @param n3 the number of elements in the 3nd dimension - * @param n4 the number of elements in the 4th dimension - * @param f The function computing element values - * @return A $coll consisting of elements `f(i1, i2, i3, i4)` - * for `0 <= i1 < n1`, `0 <= i2 < n2`, `0 <= i3 < n3`, and `0 <= i4 < n4`. - */ - def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => A): CC[CC[CC[CC[A]]]] = - tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _))) - - /** Produces a five-dimensional $coll containing values of a given function over ranges of integer values starting from 0. - * @param n1 the number of elements in the 1st dimension - * @param n2 the number of elements in the 2nd dimension - * @param n3 the number of elements in the 3nd dimension - * @param n4 the number of elements in the 4th dimension - * @param n5 the number of elements in the 5th dimension - * @param f The function computing element values - * @return A $coll consisting of elements `f(i1, i2, i3, i4, i5)` - * for `0 <= i1 < n1`, `0 <= i2 < n2`, `0 <= i3 < n3`, `0 <= i4 < n4`, and `0 <= i5 < n5`. - */ - def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => A): CC[CC[CC[CC[CC[A]]]]] = - tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _))) - - /** Produces a $coll containing a sequence of increasing of integers. - * - * @param start the first element of the $coll - * @param end the end value of the $coll (the first value NOT contained) - * @return a $coll with values `start, start + 1, ..., end - 1` - */ - def range[T: Integral](start: T, end: T): CC[T] = range(start, end, implicitly[Integral[T]].one) - - /** Produces a $coll containing equally spaced values in some integer interval. - * @param start the start value of the $coll - * @param end the end value of the $coll (the first value NOT contained) - * @param step the difference between successive elements of the $coll (must be positive or negative) - * @return a $coll with values `start, start + step, ...` up to, but excluding `end` - */ - def range[T: Integral](start: T, end: T, step: T): CC[T] = { - val num = implicitly[Integral[T]] - import num._ - - if (step == zero) throw new IllegalArgumentException("zero step") - val b = newBuilder[T] - b sizeHint immutable.NumericRange.count(start, end, step, isInclusive = false) - var i = start - while (if (step < zero) end < i else i < end) { - b += i - i += step - } - b.result() - } - - /** Produces a $coll containing repeated applications of a function to a start value. - * - * @param start the start value of the $coll - * @param len the number of elements contained inthe $coll - * @param f the function that's repeatedly applied - * @return a $coll with `len` values in the sequence `start, f(start), f(f(start)), ...` - */ - def iterate[A](start: A, len: Int)(f: A => A): CC[A] = { - val b = newBuilder[A] - if (len > 0) { - b.sizeHint(len) - var acc = start - var i = 1 - b += acc - - while (i < len) { - acc = f(acc) - i += 1 - b += acc - } - } - b.result() - } -} diff --git a/tests/pos/GenTraversableFactory.scala b/tests/pos/GenTraversableFactory.scala index e5cba4501..2f93ab27b 100644 --- a/tests/pos/GenTraversableFactory.scala +++ b/tests/pos/GenTraversableFactory.scala @@ -219,14 +219,10 @@ extends GenericCompanion[CC] { val b = newBuilder[T] b sizeHint immutable.NumericRange.count(start, end, step, isInclusive = false) var i = start - - { - val ord: Ordering[T] = num - implicit val ops: T => ord.Ops = ord.mkOrderingOps - while (if (step < zero) end < i else i < end) { + while (if (/*num.mkOrderingOps*/(step) < zero) end < i else i < end) { b += i i += step - }} + } b.result() } -- cgit v1.2.3