Dotty has added a really fabulous way of declaring Algebraic Data Types (ADTs) in the form of the new `enum`

syntax

e.g.

```
enum MyEnum {
case A
case B(i: Int, j: Int)
}
```

However these ADT are limited in that they can only be completely flat, while in general it is actually quite useful oftentimes to nest ADTs, and the new enum syntax seems like a great opportunity to provide support for those! I would propose the following syntax

```
enum MyEnum {
case A
case B(i: Int)
case enum C {
case D(s: String)
case E
case enum F {
case G
}
case enum H {
case I, J, K
}
}
}
```

But then the question arises: What type should be inferred for nested enum values, such as `MyEnum.A`

, `MyEnum.B.apply`

, and `MyEnum.C.D.apply(s: String)`

?

I think a simple approach would be: Always infer the most specific enclosing enum. So each of the following expressions should have these types inferred

```
MyEnum.A // MyEnum
MyEnum.B(1) // MyEnum
MyEnum.C.D("") // MyEnum.C
MyEnum.C.E // MyEnum.C
MyEnum.C.F.G // MyEnum.C.F
MyEnum.C.H.I // MyEnum.C.H
MyEnum.C.H.J // MyEnum.C.H
MyEnum.C.H.K // MyEnum.C.H
```

Below I will include a collection of nice usecases of this feature, to demonstrate that it is not just for giggles:

- Paul Philipsâ€™
`SizeInfo`

talked about here

```
enum SizeInfo {
case Bounded(bound: Int)
case enum Atomic {
case Infinite
case Precise(n: Int)
}
}
```

- A Hierarchy of Reals/Rationals/Integers/Naturals

```
enum Real(computeDigits: Int => BigDecimal) {
case enum Rational(numerator: Int, denominator: Int)
extends Real(_ => BigDecimal(numerator) / denominator) {
case enum Integer(n: Int) extends Rational(n, 1) {
case Natural(n: Int) extends Integer(n)
case Negative(n: Int) extends Integer(n)
}
case Fraction(numerator: Int, denominator: Int) extends Rational(numerator, denominator)
}
case Irrational(computeDigits: Int => BigDecimal) extends Real(computeDigits)
}
```

- An generalization of
`Either`

to include â€śInclusive ORâ€ť

```
enum AndOr[+A, +B] {
case Both[+A, +B](left: A, right: B) extends AndOr[A, B]
case enum Either[+A, +B] extends AndOr[A, B] {
case Left[+A, +B](value: A) extends Either[A, B]
case Right[+A, +B](value: B) extends Either[A, B]
}
}
```

- Grouping JSON values into primitives and non primitives

```
enum JsValue {
case Obj(fields: Map[String, JsValue])
case Arr(elems: ArraySeq[JsValue])
case enum Primitive {
case Str(str: String)
case Num(bigDecimal: BigDecimal)
case JsNull
case enum Bool(boolean: Boolean) {
case True extends Bool(true),
case False extends Bool(false) }
}
}
```