aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Petrashko <dark@d-d.me>2015-11-02 18:46:15 +0100
committerDmitry Petrashko <dark@d-d.me>2015-11-02 18:46:15 +0100
commit432689d1a38cf65da88a1e72e0c0f425850c340e (patch)
tree066f9574bc6d1665fb14d6fd7b6e6db4e210c074
parentf58acd171105487984a1d8df2646246aab43e5e1 (diff)
parent4b1d08928bd008a23fa40490d2998e58a6f06c4d (diff)
downloaddotty-432689d1a38cf65da88a1e72e0c0f425850c340e.tar.gz
dotty-432689d1a38cf65da88a1e72e0c0f425850c340e.tar.bz2
dotty-432689d1a38cf65da88a1e72e0c0f425850c340e.zip
Merge pull request #860 from dotty-staging/change-allow-ex-in-hk
Change allow ex in hk
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala6
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala66
-rw-r--r--src/dotty/tools/dotc/core/Types.scala44
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreePickler.scala35
-rw-r--r--src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala9
-rw-r--r--src/dotty/tools/dotc/transform/PostTyper.scala2
-rw-r--r--src/dotty/tools/dotc/transform/TypeTestsCasts.scala1
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala4
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala3
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala29
-rw-r--r--test/dotc/tests.scala3
-rw-r--r--tests/neg/partialApplications.scala11
-rw-r--r--tests/neg/selfreq.scala8
-rw-r--r--tests/pos/GenTraversableFactory.scala252
-rw-r--r--tests/pos/polyalias.scala6
15 files changed, 368 insertions, 111 deletions
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index 0dde5de95..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, "<trait>")
+ final val LazyOrTrait = Lazy.toCommonFlags
+
/** A value or variable accessor (getter or setter) */
final val Accessor = termFlag(11, "<accessor>")
@@ -315,6 +317,8 @@ object Flags {
/** An unpickled Scala 2.x class */
final val Scala2x = typeFlag(26, "<scala-2.x>")
+ final val SuperAccessorOrScala2x = SuperAccessor.toCommonFlags
+
/** A method that has default params */
final val DefaultParameterized = termFlag(27, "<defaultparam>")
@@ -440,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 |
- SelfNameOrImplClass
+ LazyOrTrait | SuperAccessorOrScala2x | SelfNameOrImplClass
assert(FromStartFlags.isTermFlags && FromStartFlags.isTypeFlags)
// TODO: Should check that FromStartFlags do not change in completion
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 47935f79e..7274c1f70 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
@@ -225,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/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 <this . name> , 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/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 6e405d5f8..cdb733efa 100644
--- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
+++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
@@ -451,6 +451,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)
@@ -536,7 +537,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 =
@@ -621,7 +621,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
}
@@ -687,7 +687,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/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/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._
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
}
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 4637eed51..60ecaac0b 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -851,34 +851,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 381f522cf..deea12272 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -150,14 +150,13 @@ 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)
@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/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/pos/GenTraversableFactory.scala b/tests/pos/GenTraversableFactory.scala
new file mode 100644
index 000000000..2f93ab27b
--- /dev/null
+++ b/tests/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 (/*num.mkOrderingOps*/(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/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
+
}