aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-12-22 16:11:43 +0100
committerMartin Odersky <odersky@gmail.com>2013-12-22 16:12:47 +0100
commit8216688420003002449313c8a4f419b09282bf84 (patch)
treeee3ba0a2e0215bf20c4369a27e9133dc65f7fa3e /src/dotty
parent115e13b323e9ca845302a2c0ee0367e03cb8379b (diff)
downloaddotty-8216688420003002449313c8a4f419b09282bf84.tar.gz
dotty-8216688420003002449313c8a4f419b09282bf84.tar.bz2
dotty-8216688420003002449313c8a4f419b09282bf84.zip
Desugaring changes
1) Desugar type bounds containing empty trees 2) Include a productN parent for a case class, only if the case class has 2 or more parameters in its parameter section. Also, handle type bounds appearing in AppliedTypeTrees (these represent wildcard types).
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala36
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala13
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala5
3 files changed, 31 insertions, 23 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index 70c3e76f6..600409188 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -136,22 +136,14 @@ object desugar {
*/
def typeDef(tdef: TypeDef)(implicit ctx: Context): Tree = {
val TypeDef(mods, name, rhs) = tdef
- val rhs1 = rhs match {
- case TypeBoundsTree(lo, hi) =>
- val lo1 = if (lo.isEmpty) untpd.TypeTree(defn.NothingType) else lo
- val hi1 = if (hi.isEmpty) untpd.TypeTree(defn.AnyType) else hi
- cpy.TypeBoundsTree(rhs, lo1, hi1)
- case _ =>
- rhs
- }
if (mods is PrivateLocalParam) {
val tparam = cpy.TypeDef(tdef,
- mods &~ PrivateLocal | ExpandedName, name.expandedName(ctx.owner), rhs1, tdef.tparams)
+ mods &~ PrivateLocal | ExpandedName, name.expandedName(ctx.owner), rhs, tdef.tparams)
val alias = cpy.TypeDef(tdef,
Modifiers(PrivateLocalParamAccessor | Synthetic), name, refOfDef(tparam))
Thicket(tparam, alias)
}
- else cpy.TypeDef(tdef, mods, name, rhs1, tdef.tparams)
+ else cpy.TypeDef(tdef, mods, name, rhs, tdef.tparams)
}
private val synthetic = Modifiers(Synthetic)
@@ -226,18 +218,20 @@ object desugar {
else Nil
def anyRef = ref(defn.AnyRefAlias.typeRef)
- def productConstr = {
- val tycon = ref(defn.ProductNClass(vparamss.head.length).typeRef)
+ def productConstr(n: Int) = {
+ val tycon = ref(defn.ProductNClass(n).typeRef)
val targs = vparamss.head map (_.tpt)
New(AppliedTypeTree(tycon, targs), Nil)
}
// The desugared parents: AnyRef, in case parents are Nil.
// Case classes also get a ProductN parent
- val parents1 = {
- val parents0 = if (mods is Case) parents :+ productConstr else parents
- if (parents0.isEmpty) New(anyRef, Nil) :: Nil else parents0
- }
+ var parents1 = parents
+ val n = vparamss.head.length
+ if ((mods is Case) && 2 <= n && n <= Definitions.MaxTupleArity)
+ parents1 = parents1 :+ productConstr(n)
+ if (parents1.isEmpty)
+ parents1 = New(anyRef, Nil) :: Nil
// The thicket which is the desugared version of the companion object
// synthetic object C extends parentTpt { defs }
@@ -392,6 +386,16 @@ object desugar {
tree
}
+ /** EmptyTree in lower bound ==> Nothing
+ * EmptyTree in upper bounds ==> Any
+ */
+ def typeBoundsTree(tree: TypeBoundsTree)(implicit ctx: Context): TypeBoundsTree = {
+ val TypeBoundsTree(lo, hi) = tree
+ val lo1 = if (lo.isEmpty) untpd.TypeTree(defn.NothingType) else lo
+ val hi1 = if (hi.isEmpty) untpd.TypeTree(defn.AnyType) else hi
+ cpy.TypeBoundsTree(tree, lo1, hi1)
+ }
+
/** Make closure corresponding to function.
* params => body
* ==>
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 599e4b0f0..98249d8c9 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -127,11 +127,14 @@ class TypeApplications(val self: Type) extends AnyVal {
/** Turn this type, which is used as an argument for
* type parameter `tparam`, into a TypeBounds RHS
*/
- final def toBounds(tparam: Symbol)(implicit ctx: Context): TypeBounds = {
- val v = tparam.variance
- if (v > 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) TypeBounds.upper(self)
- else if (v < 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) TypeBounds.lower(self)
- else TypeAlias(self, v)
+ final def toBounds(tparam: Symbol)(implicit ctx: Context): TypeBounds = self match {
+ case self: TypeBounds => // this can happen for wildcard args
+ self
+ case _ =>
+ val v = tparam.variance
+ if (v > 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) TypeBounds.upper(self)
+ else if (v < 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) TypeBounds.lower(self)
+ else TypeAlias(self, v)
}
/** The type arguments of the base type instance wrt `base` of this type */
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 69705cfce..54a299291 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -708,8 +708,9 @@ class Typer extends Namer with Applications with Implicits {
}
def typedTypeBoundsTree(tree: untpd.TypeBoundsTree)(implicit ctx: Context): TypeBoundsTree = track("typedTypeBoundsTree") {
- val lo1 = typed(tree.lo)
- val hi1 = typed(tree.hi)
+ val TypeBoundsTree(lo, hi) = desugar.typeBoundsTree(tree)
+ val lo1 = typed(lo)
+ val hi1 = typed(hi)
if (!(lo1.tpe <:< hi1.tpe))
ctx.error(i"lower bound ${lo1.tpe} does not conform to upper bound ${hi1.tpe}", tree.pos)
cpy.TypeBoundsTree(tree, lo1, hi1) withType TypeBounds(lo1.tpe, hi1.tpe)