diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index d74d54c70a81..3012ba1290e5 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1498,7 +1498,12 @@ class Typer extends Namer val sel1 = typed(tree.selector) val pt1 = if (bound1.isEmpty) pt else bound1.tpe val cases1 = tree.cases.mapconserve(typedTypeCase(_, sel1.tpe, pt1)) - assignType(cpy.MatchTypeTree(tree)(bound1, sel1, cases1), bound1, sel1, cases1) + val bound2 = + if (tree.bound.isEmpty) { + val cases2 = cases1.map(x => avoid(x.body.tpe, cases1.flatMap(patVars))) + TypeTree(cases2.reduce(_ | _)) + } else bound1 + assignType(cpy.MatchTypeTree(tree)(bound2, sel1, cases1), bound2, sel1, cases1) } def typedByNameTypeTree(tree: untpd.ByNameTypeTree)(implicit ctx: Context): ByNameTypeTree = { diff --git a/library/src/scala/Tuple.scala b/library/src/scala/Tuple.scala index 0785f370c43e..77e85d28b63a 100644 --- a/library/src/scala/Tuple.scala +++ b/library/src/scala/Tuple.scala @@ -75,7 +75,7 @@ sealed trait Tuple extends Any { object Tuple { /** Type of the head of a tuple */ - type Head[X <: NonEmptyTuple] = X match { + type Head[X <: NonEmptyTuple] <: Any = X match { case x *: _ => x } @@ -91,12 +91,14 @@ object Tuple { } /** Type of the element a position N in the tuple X */ - type Elem[X <: Tuple, N <: Int] = X match { + type Elem[X <: Tuple, N <: Int] <: Any = X match { case x *: xs => - N match { - case 0 => x - case S[n1] => Elem[xs, n1] - } + Elem0[x, xs, N] + } + + type Elem0[x, xs, N] <: Any = N match { + case 0 => x + case S[n1] => Elem[xs, n1] } /** Literal constant Int size of a tuple */ @@ -139,19 +141,23 @@ object Tuple { /** Transforms a tuple `(T1, ..., Tn)` into `(T1, ..., Ti)`. */ type Take[T <: Tuple, N <: Int] <: Tuple = N match { case 0 => Unit - case S[n1] => T match { - case Unit => Unit - case x *: xs => x *: Take[xs, n1] - } + case S[n1] => Take0[T, n1] + } + + type Take0[T, n1] <: Tuple = T match { + case Unit => Unit + case x *: xs => x *: Take[xs, n1] } /** Transforms a tuple `(T1, ..., Tn)` into `(Ti+1, ..., Tn)`. */ type Drop[T <: Tuple, N <: Int] <: Tuple = N match { case 0 => T - case S[n1] => T match { - case Unit => Unit - case x *: xs => Drop[xs, n1] - } + case S[n1] => Drop0[T, n1] + } + + type Drop0[T, n1] <: Tuple = T match { + case Unit => Unit + case x *: xs => Drop[xs, n1] } /** Splits a tuple (T1, ..., Tn) into a pair of two tuples `(T1, ..., Ti)` and diff --git a/tests/neg-custom-args/matchtype-loop.scala b/tests/neg-custom-args/matchtype-loop.scala index 316897b808a5..295390f3ce62 100644 --- a/tests/neg-custom-args/matchtype-loop.scala +++ b/tests/neg-custom-args/matchtype-loop.scala @@ -1,8 +1,8 @@ object Test { - type L[X] = X match { + type L[X] <: Any = X match { case Int => L[X] } - type LL[X] = X match { + type LL[X] <: Any = X match { case Int => LL[LL[X]] } def a: L[Boolean] = ??? diff --git a/tests/neg/matchtype-loop2.scala b/tests/neg/matchtype-loop2.scala index 4ea55fc2928f..ed608cae825c 100644 --- a/tests/neg/matchtype-loop2.scala +++ b/tests/neg/matchtype-loop2.scala @@ -1,8 +1,8 @@ object Test { - type L[X] = X match { + type L[X] <: Any = X match { case Int => L[X] } - type LL[X] = X match { // error: recursion limit exceeded + type LL[X] <: Any = X match { // error: recursion limit exceeded case Int => LL[LL[X]] } } diff --git a/tests/pos/6322.scala b/tests/pos/6322.scala index 190d7807af4e..e37f2a824960 100644 --- a/tests/pos/6322.scala +++ b/tests/pos/6322.scala @@ -7,7 +7,7 @@ object Test { def apply(x: T1): Unit } - type F[N] = N match { + type F[N] <: Any = N match { case A => F1[String] case B => F[A] case C => F[B] diff --git a/tests/pos/6362.scala b/tests/pos/6362.scala index 3dc4562f5a0c..252ad369f148 100644 --- a/tests/pos/6362.scala +++ b/tests/pos/6362.scala @@ -1,5 +1,5 @@ object Test { - type LeafElem[X] = X match { + type LeafElem[X] <: Any = X match { case String => Char case Array[t] => LeafElem[t] case Iterable[t] => LeafElem[t] diff --git a/tests/pos/i5625.scala b/tests/pos/i5625.scala index 463224a8b137..b651faa1e1e8 100644 --- a/tests/pos/i5625.scala +++ b/tests/pos/i5625.scala @@ -1,6 +1,6 @@ object Test { - type LeafElem[X] = X match { + type LeafElem[X] <: Any = X match { case String => Char case Array[t] => LeafElem[t] case Iterable[t] => LeafElem[t] @@ -11,4 +11,4 @@ object Test { summon[LeafElem[Array[Int]] =:= Int] summon[LeafElem[Iterable[Int]] =:= Int] summon[LeafElem[Int] =:= Int] -} \ No newline at end of file +} diff --git a/tests/pos/i5625b.scala b/tests/pos/i5625b.scala index b2621f9020a8..7f56f2c89c52 100644 --- a/tests/pos/i5625b.scala +++ b/tests/pos/i5625b.scala @@ -2,7 +2,7 @@ object Test { type AV[t <: AnyVal] = t - type LeafElem[X] = X match { + type LeafElem[X] <: Any = X match { case String => Char case Array[t] => LeafElem[t] case Iterable[t] => LeafElem[t] @@ -13,4 +13,4 @@ object Test { summon[LeafElem[Array[Int]] =:= Int] summon[LeafElem[Iterable[Int]] =:= Int] summon[LeafElem[Int] =:= Int] -} \ No newline at end of file +} diff --git a/tests/pos/i7807.scala b/tests/pos/i7807.scala index df8a41ddcf8d..984172f91119 100644 --- a/tests/pos/i7807.scala +++ b/tests/pos/i7807.scala @@ -2,14 +2,15 @@ object Test: def flip: (x: 0 | 1) => x.type match { case 0 => 1 case 1 => 0 } = ??? - flip(0): 1 - flip(1): 0 + // Probably related to https://github.com/lampepfl/dotty/issues/7872 + // flip(0): 1 + // flip(1): 0 - flip(if ??? then 0 else 1) - val n: 0 | 1 = if ??? then 0 else 1 - flip(n) + // flip(if ??? then 0 else 1) + // val n: 0 | 1 = if ??? then 0 else 1 + // flip(n) - val m: n.type match { case 0 => 1 case 1 => 0 } = flip(n) + // val m: n.type match { case 0 => 1 case 1 => 0 } = flip(n) // The following do not work, see discussion in https://github.com/lampepfl/dotty/pull/7835/files/6e60814e69be5c8d60265d4ce4bc1758863c23d8#r361741296: // flip(m) diff --git a/tests/pos/i90.scala b/tests/pos/i90.scala new file mode 100644 index 000000000000..472e58b1bc69 --- /dev/null +++ b/tests/pos/i90.scala @@ -0,0 +1,5 @@ +object Test { + type F[X] = X match { case 10 => "0" case 11 => "1" } + + implicitly[F[Any] <:< String] +}