diff options
author | Martin Odersky <odersky@gmail.com> | 2017-02-28 18:59:08 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2017-04-04 13:29:38 +0200 |
commit | 44d9ab81886a9ff0b7256fccb584c049f1c18027 (patch) | |
tree | eff314cd55d1917ed9f1cb1d6caba551a3f04a51 /compiler/src | |
parent | 91a26b3f42d1218015acb9b7e1bfc180e3ed779b (diff) | |
download | dotty-44d9ab81886a9ff0b7256fccb584c049f1c18027.tar.gz dotty-44d9ab81886a9ff0b7256fccb584c049f1c18027.tar.bz2 dotty-44d9ab81886a9ff0b7256fccb584c049f1c18027.zip |
Support cases with type parameters that extend a non-parameterized base
Support cases with type parameters that implicitly extend a non-parameterized base
without needing their own extends clause. The proposal has been updated to make clear
that this is supported.
Also address other reviewers comments.
Diffstat (limited to 'compiler/src')
-rw-r--r-- | compiler/src/dotty/tools/dotc/ast/Desugar.scala | 20 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala | 20 |
2 files changed, 24 insertions, 16 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 04834b04b..80da75678 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -296,11 +296,16 @@ object desugar { val isValueClass = parents.nonEmpty && isAnyVal(parents.head) // This is not watertight, but `extends AnyVal` will be replaced by `inline` later. + lazy val reconstitutedTypeParams = reconstitutedEnumTypeParams(cdef.pos.startPos) + val originalTparams = if (isEnumCase && parents.isEmpty) { - if (constr1.tparams.nonEmpty) - ctx.error(em"case with type parameters needs extends clause", constr1.tparams.head.pos) - reconstitutedEnumTypeParams(cdef.pos.startPos) + if (constr1.tparams.nonEmpty) { + if (reconstitutedTypeParams.nonEmpty) + ctx.error(em"case with type parameters needs extends clause", constr1.tparams.head.pos) + constr1.tparams + } + else reconstitutedTypeParams } else constr1.tparams val originalVparamss = constr1.vparamss @@ -339,7 +344,9 @@ object desugar { // a reference to the class type bound by `cdef`, with type parameters coming from the constructor val classTypeRef = appliedRef(classTycon) // a reference to `enumClass`, with type parameters coming from the constructor - lazy val enumClassTypeRef = appliedRef(enumClassRef) + lazy val enumClassTypeRef = + if (reconstitutedTypeParams.isEmpty) enumClassRef + else appliedRef(enumClassRef) // new C[Ts](paramss) lazy val creatorExpr = New(classTypeRef, constrVparamss nestedMap refOfDef) @@ -516,10 +523,7 @@ object desugar { case _ => } - val result = flatTree(cdef1 :: companions ::: implicitWrappers) - //if (isEnum) println(i"enum $cdef\n --->\n$result") - //if (isEnumCase) println(i"enum case $cdef\n --->\n$result") - result + flatTree(cdef1 :: companions ::: implicitWrappers) } val AccessOrSynthetic = AccessFlags | Synthetic diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index 7fdff0e2d..c5c95d647 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -14,14 +14,17 @@ object DesugarEnums { import untpd._ import desugar.DerivedFromParamTree - val EnumCaseCount = new Property.Key[Int] + /** Attachment containing: The number of enum cases seen so far, and whether a + * simple enum case was already seen. + */ + val EnumCaseCount = new Property.Key[(Int, Boolean)] def enumClass(implicit ctx: Context) = ctx.owner.linkedClass - def nextEnumTag(implicit ctx: Context): Int = { - val result = ctx.tree.removeAttachment(EnumCaseCount).getOrElse(0) - ctx.tree.pushAttachment(EnumCaseCount, result + 1) - result + def nextEnumTag(isSimpleCase: Boolean)(implicit ctx: Context): (Int, Boolean) = { + val (count, simpleSeen) = ctx.tree.removeAttachment(EnumCaseCount).getOrElse((0, false)) + ctx.tree.pushAttachment(EnumCaseCount, (count + 1, simpleSeen | isSimpleCase)) + (count, simpleSeen) } def isLegalEnumCase(tree: MemberDef)(implicit ctx: Context): Boolean = @@ -54,7 +57,8 @@ object DesugarEnums { } def enumTagMeth(implicit ctx: Context) = - DefDef(nme.enumTag, Nil, Nil, TypeTree(), Literal(Constant(nextEnumTag))) + DefDef(nme.enumTag, Nil, Nil, TypeTree(), + Literal(Constant(nextEnumTag(isSimpleCase = false)._1))) def enumClassRef(implicit ctx: Context) = TypeTree(enumClass.typeRef) @@ -120,8 +124,8 @@ object DesugarEnums { def expandSimpleEnumCase(name: TermName, mods: Modifiers, pos: Position)(implicit ctx: Context): Tree = { if (reconstitutedEnumTypeParams(pos).nonEmpty) ctx.error(i"illegal enum value of generic $enumClass: an explicit `extends' clause is needed", pos) - val tag = nextEnumTag - val prefix = if (tag == 0) enumScaffolding else Nil + val (tag, simpleSeen) = nextEnumTag(isSimpleCase = true) + val prefix = if (simpleSeen) Nil else enumScaffolding val creator = Apply(Ident(nme.DOLLAR_NEW), List(Literal(Constant(tag)), Literal(Constant(name.toString)))) val vdef = ValDef(name, enumClassRef, creator).withMods(mods | Final).withPos(pos) flatTree(prefix ::: vdef :: Nil).withPos(pos.startPos) |