Skip to content

Match type fails to reduce in a simple case #23159

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

Open
keynmol opened this issue May 14, 2025 · 3 comments
Open

Match type fails to reduce in a simple case #23159

keynmol opened this issue May 14, 2025 · 3 comments

Comments

@keynmol
Copy link
Contributor

keynmol commented May 14, 2025

I don't have a better title because I don't currently see the difference between failing and suceeding case.

Compiler version

3.3.6, 3.7.0

Minimized code

type TupleContains[X <: Tuple, Y] <: Boolean = X match
  case Y *: _     => true
  case _ *: xs    => TupleContains[xs, Y]
  case EmptyTuple => false

trait TC1[A]
trait TC2[A]

// this works
summon[
  (TupleContains[(Int, String, Boolean), String]) =:= true
]

// this also works
summon[
  (TupleContains[(Array[Int], Set[Int], List[Boolean]), Set[Int]]) =:= true
]

// how is this different from above?
summon[
  (TupleContains[(TC1[Int], TC2[Int], Set[Boolean]), TC2[Int]]) =:= true
]

Output

https://scastie.scala-lang.org/BO4FKhFwRMSjhGaIQBKIlg

  Cannot prove that Playground.TupleContains[
    (Playground.TC1[Int], Playground.TC2[Int], Set[Boolean]), Playground.TC2[Int]] =:= (true : Boolean).

  Note: a match type could not be fully reduced:

    trying to reduce  Playground.TupleContains[
    (Playground.TC1[Int], Playground.TC2[Int], Set[Boolean]), Playground.TC2[Int]]
    failed since selector (Playground.TC1[Int], Playground.TC2[Int], Set[Boolean])
    does not match  case Playground.TC2[Int] *: _ => (true : Boolean)
    and cannot be shown to be disjoint from it either.
    Therefore, reduction cannot advance to the remaining cases

      case _ *: xs => Playground.TupleContains[xs, Playground.TC2[Int]]
      case EmptyTuple => (false : Boolean)

Expectation

I'm not sure why the failing reduction is different from the one above it that succeeds?

@keynmol keynmol added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels May 14, 2025
@sjrd
Copy link
Member

sjrd commented May 14, 2025

TC1 and TC2 are traits, so not probably disjoint. The others are classes.

@Gedochao Gedochao added area:typeclass-derivation area:match-types and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels May 15, 2025
@keynmol
Copy link
Contributor Author

keynmol commented May 15, 2025

Gotcha, Aly on Discord educated me:

Yeah it's bcs you could have val x: TC2[Int] = new TC1 with TC2

Do you know if there's a way to implement this Contains check? As it only returns true or false (shortcircuiting), those conflicting cases are not a concern.

@sjrd
Copy link
Member

sjrd commented May 15, 2025

I don't think so. Perhaps wrapping both sides in an invariant container, but I don't remember what we settled on for invariant type constructors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants