Skip to content

Regression: "a match type could not be fully reduced" when flattening a list of tuples #22022

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
hegetim opened this issue Nov 25, 2024 · 6 comments
Assignees
Labels
area:match-types itype:bug regression This worked in a previous version but doesn't anymore

Comments

@hegetim
Copy link

hegetim commented Nov 25, 2024

Compiler version

Affected: 3.5.0 and newer (tested on Scastie up to 3.6.1)
Latest working version: 3.4.3

Minimized code

case class MyNum(i: Int)

val l = List((MyNum(1), MyNum(1)))

l.flatMap(_.toList)

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

Output

Does not compile on 3.5.0 and newer:

    Found:    List[Tuple.Union[(_$1 : (Playground.MyNum, Playground.MyNum))]]
    Required: IterableOnce[Playground.MyNum]

    Note: a match type could not be fully reduced:

      trying to reduce  Tuple.Union[(_$1 : (Playground.MyNum, Playground.MyNum))]
      trying to reduce  Tuple.Fold[(_$1 : (Playground.MyNum, Playground.MyNum)), Nothing,
      [x, y] =>> x | y]
      failed since selector (_$1 : (Playground.MyNum, Playground.MyNum))
      does not uniquely determine parameters h, t in
        case h *: t => h | Tuple.Fold[t, Nothing, [x, y] =>> x | y]
      The computed bounds for the parameters are:
        h <: Playground.MyNum
        t <: Playground.MyNum *: EmptyTuple.type

Expectation

Should compile (as it does on 3.4.3) and give a flat list of MyNums.

@hegetim hegetim added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Nov 25, 2024
@Gedochao Gedochao added area:match-types regression This worked in a previous version but doesn't anymore stat:needs bisection Need to use nightly builds and git bisect to find out the commit where this issue was introduced and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Nov 26, 2024
@Gedochao
Copy link
Contributor

Last good release: 3.5.0-RC1-bin-20240403-ece87c3-NIGHTLY
First bad release: 3.5.0-RC1-bin-20240404-a7f00e2-NIGHTLY
Bisect points at 0bf43b2

cc @sjrd

@Gedochao Gedochao removed the stat:needs bisection Need to use nightly builds and git bisect to find out the commit where this issue was introduced label Nov 26, 2024
@sjrd
Copy link
Member

sjrd commented Nov 26, 2024

Given the bisect commit, I suspect that the new error is legitimate. It fixed an unsoundness issue (#19746), so it may very well prevent compilation of code that worked more-or-less by chance before.

@hegetim
Copy link
Author

hegetim commented Nov 26, 2024

Not sure if I get this right.

Is my usage of Tuple's toList function unsound? Or does the current implementation of toList just incorrectly rely on unsound behavior that has been fixed in 3.5.0?

The signature of toList is

inline def toList: List[Union[this.type]]

In its current state toList is quite limited. Any chance to get that improved?

@Gedochao
Copy link
Contributor

Gedochao commented Nov 26, 2024

@hegetim I think @sjrd meant that #19746 was an unsoundness issue (check the soundness label), and the fix for that caused this regression (that's where the bisect script points). We need to fix it separately.

@hegetim
Copy link
Author

hegetim commented Dec 4, 2024

@Gedochao thanks for the explanation. So I guess this is not exactly a regression. The error is valid because in the declared return type, this.type is too narrow to be used in Tuple.Union. In order to improve the usability of Tuple's toList function, we probably have to make the widening of the tuple type explicit?

For example, changing toList into an extension method like this

extension [T <: Tuple](t: T)
  inline def toList: List[Tuple.Union[T]] = t.productIterator.toList.asInstanceOf[List[Tuple.Union[T]]]

would solve the issue (see https://scastie.scala-lang.org/42ADHhqzSEaaAmirzwxqyg)

I'm not sure if this can be done in a binary compatible way.

@Gedochao
Copy link
Contributor

In order to improve the usability of Tuple's toList function, we probably have to make the widening of the tuple type explicit?

For example, changing toList into an extension method like this

extension [T <: Tuple](t: T)
inline def toList: List[Tuple.Union[T]] = t.productIterator.toList.asInstanceOf[List[Tuple.Union[T]]]
would solve the issue (see https://scastie.scala-lang.org/42ADHhqzSEaaAmirzwxqyg)

I'm not sure if this can be done in a binary compatible way.

@hegetim This seems out of scope here, potentially separate issue material.

Given the bisect commit, I suspect that the new error is legitimate. It fixed an unsoundness issue (#19746), so it may very well prevent compilation of code that worked more-or-less by chance before.

Alright, so it seems this behaviour is as expected.
Nothing to do here, closing this.

@Gedochao Gedochao closed this as not planned Won't fix, can't repro, duplicate, stale Jan 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:match-types itype:bug regression This worked in a previous version but doesn't anymore
Projects
None yet
Development

No branches or pull requests

3 participants