Skip to content

Regression around match type reduction in 3.3.2 nightly versions #18202

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mrdziuban opened this issue Jul 13, 2023 · 2 comments
Closed

Regression around match type reduction in 3.3.2 nightly versions #18202

mrdziuban opened this issue Jul 13, 2023 · 2 comments

Comments

@mrdziuban
Copy link

mrdziuban commented Jul 13, 2023

Compiler version

Nightly versions 3.3.2-RC1-bin-20230605-5d2812a-NIGHTLY through the latest 3.3.2-RC1-bin-20230710-ed319e8-NIGHTLY

By testing every nightly version I've narrowed it down to something in the commit range 348729e...5d2812a, and if git bisect is telling me the truth, then I believe the specific commit is 09f5e4c

Minimized code

type TupleIndex[T <: Tuple, A] = TupleIndex0[T, A, 0]

type TupleIndex0[T <: Tuple, A, I <: Int] <: (Any, Int) =
  T match {
    case A *: _ => (A, I)
    case _ *: t => TupleIndex0[t, A, compiletime.ops.int.S[I]]
  }

def tupleIndex[T <: Tuple, A](using i: ValueOf[Tuple.Elem[TupleIndex[T, A], 1]]): Int = i.value

Output

A type mismatch error is given at the RHS of def tupleIndex

-- [E007] Type Mismatch Error: /path/to/TupleIndex.scala:9:90
9 |def tupleIndex[T <: Tuple, A](using i: ValueOf[Tuple.Elem[TupleIndex[T, A], 1]]): Int = i.value
  |                                                                                        ^^^^^^^
  |Found:    Tuple.Elem[TupleIndex[T, A], (1 : Int)]
  |Required: Int
  |
  |where:    T is a type in method tupleIndex with bounds <: Tuple
  |
  |
  |Note: a match type could not be fully reduced:
  |
  |  trying to reduce  Tuple.Elem[TupleIndex[T, A], (1 : Int)]
  |  trying to reduce  TupleIndex[T, A]
  |  trying to reduce  TupleIndex0[T, A, (0 : Int)]
  |  failed since selector T
  |  does not match  case A *: _ => (A, (0 : Int))
  |  and cannot be shown to be disjoint from it either.
  |  Therefore, reduction cannot advance to the remaining case
  |
  |    case _ *: t => TupleIndex0[t, A, scala.compiletime.ops.int.S[(0 : Int)]]
  |  trying to reduce  TupleIndex[T, A]
  |  trying to reduce  TupleIndex0[T, A, (0 : Int)]
  |  failed since selector T
  |  does not match  case A *: _ => (A, (0 : Int))
  |  and cannot be shown to be disjoint from it either.
  |  Therefore, reduction cannot advance to the remaining case
  |
  |    case _ *: t => TupleIndex0[t, A, scala.compiletime.ops.int.S[(0 : Int)]]
  |  trying to reduce  TupleIndex0[T, A, (0 : Int)]
  |  failed since selector T
  |  does not match  case A *: _ => (A, (0 : Int))
  |  and cannot be shown to be disjoint from it either.
  |  Therefore, reduction cannot advance to the remaining case
  |
  |    case _ *: t => TupleIndex0[t, A, scala.compiletime.ops.int.S[(0 : Int)]]

Expectation

The compiler should recognize that Tuple.Elem[TupleIndex[T, A], 1] is an Int since TupleIndex0 specifies a bound of (Any, Int)

Things work properly if TupleIndex0 has a bound of <: Int and I don't use Tuple.Elem, so does this maybe have something to do with nested match types? i.e. this compiles

type TupleIndex[T <: Tuple, A] = TupleIndex0[T, A, 0]

type TupleIndex0[T <: Tuple, A, I <: Int] <: Int =
  T match {
    case A *: _ => I
    case _ *: t => TupleIndex0[t, A, compiletime.ops.int.S[I]]
  }

def tupleIndex[T <: Tuple, A](using i: ValueOf[TupleIndex[T, A]]): Int = i.value
@mrdziuban mrdziuban added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Jul 13, 2023
@dwijnand dwijnand self-assigned this Jul 13, 2023
@nicolasstucki nicolasstucki removed the stat:needs triage Every issue needs to have an "area" and "itype" label label Jul 14, 2023
@Kordyjan Kordyjan added regression This worked in a previous version but doesn't anymore and removed regression This worked in a previous version but doesn't anymore labels Jul 14, 2023
@dwijnand dwijnand linked a pull request Jul 18, 2023 that will close this issue
@sjrd
Copy link
Member

sjrd commented Aug 16, 2023

As I mention in the PR attempting to fix this, at #18243 (comment), I believe the new error is actually correct. In other words, not emitting an error would be unsound. (And fixing unsoundness issues is allowed in patch releases.)

Your "workaround" is the proper fix, IMO. By removing the indirection through Tuple.Elem, you do not force Tuple.Elem to widen the abstract type _ <: (Any, Int) which is what TupleIndex[T, A] resolves to (given that it cannot reduce because T is too abstract). Widening abstract types then capturing arguments to covariant type params is known to cause unsoundness. See existing test cases in https://github.com/lampepfl/dotty/blob/ca6a80e3c7aef6b16304df20544c41a96556c834/tests/neg/wildcard-match.scala

@dwijnand
Copy link
Member

@sjrd happy to close this as invalid?

@sjrd sjrd closed this as not planned Won't fix, can't repro, duplicate, stale Feb 23, 2024
@sjrd sjrd added itype:invalid and removed regression This worked in a previous version but doesn't anymore labels Feb 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants