Skip to content

inline match on Tuple fails #12770

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
antognini opened this issue Jun 9, 2021 · 2 comments
Open

inline match on Tuple fails #12770

antognini opened this issue Jun 9, 2021 · 2 comments

Comments

@antognini
Copy link

antognini commented Jun 9, 2021

Compiler version

3.0.0

Minimized code

consider following signature:
def toListOfString(tuple: Tuple): List[String]

to be invoked with
toListOfString(1,2,3)

def toListOfString(tuple: Tuple): List[String] =
  tuple match
    case EmptyTuple   => List()
    case head *: tail => List(head.toString) ++ toListOfString(tail)

// works   => List(1, 2, 3)
// inline def
inline def toListOfString(tuple: Tuple): List[String] =
  tuple match
    case EmptyTuple   => List()
    case head *: tail => List(head.toString) ++ toListOfString(tail)

// Maximal number of successive inlines (32) exceeded,
// Maybe this is caused by a recursive inline method?

// I understand this, the compiler is trying to endlessly nest the same piece of code and fails
// inline match
inline def toListOfString(tuple: Tuple): List[String] =
  inline tuple match
    case EmptyTuple   => List()
    case head *: tail => List(head.toString) ++ toListOfString(tail)

// cannot reduce inline match with
// scrutinee:  tuple$proxy1 : (tuple$proxy1 : (Int, Int, Int))
//   patterns :  case EmptyTuple
//   case *:.unapply[Any, Tuple](head @ _, tail @ _):Any *: Tuple
//   inline tuple match

Expectation

This as a request for clarification (tag it as a question), promote it as a bug in case something needs to be fixed.
Is my expectation justified, that the variant with inline match should compile, like the non-inline toListOfString does?

@bishabosha
Copy link
Member

bishabosha commented Nov 16, 2021

perhaps in this case when the inline recursive call is evaluated there can be some sort of hashing to detect if the arguments changed, if no I would assume it would cause an infinite loop

^ however the above can't catch everything - if the arguments do change, perhaps they change in a way that actually grows the problem away from a base case - e.g. prepending to a tuple rather than removing its head

@Adam-Vandervorst
Copy link

Adam-Vandervorst commented Nov 16, 2021

Could this be a similar problem to the match types? Maybe allow it when the types work out @bishabosha?

Of course, as you alluded to, this leaves behind a large class of problems where only the value changes.
This general problem (determine the termination of let's say def f(n) = if n != 1 then f(if n % 2 == 1 then 3*n+1 else n/2)) can only be circumvented.

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

4 participants