Skip to content

Unable to pattern match an exported enum #15347

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
noti0na1 opened this issue May 31, 2022 · 1 comment · Fixed by #15367
Closed

Unable to pattern match an exported enum #15347

noti0na1 opened this issue May 31, 2022 · 1 comment · Fixed by #15367
Assignees
Milestone

Comments

@noti0na1
Copy link
Member

Compiler version

3.1.3-RC2 and main branch

Minimized code

enum E[T]:
  case A(i: Int)

export E.*

def f(x: E[Int]) = x match
  case A(i) => i

Output

case A(i) => i
|       ^
|       Not found: A
  • If we change export to import, there is no error
  • If we remove the type parameter of E, there is no error
  • If we change case A(i: Int) to case A(i: T), the error is same; change export to import here, there is no error as well
  • If we change case A(i: Int) to case A(i: Int) extends E[Int], there is no error

Expectation

I expect the code can be compiled with both import and export.

@noti0na1 noti0na1 added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label area:export and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels May 31, 2022
@bishabosha
Copy link
Member

bishabosha commented Jun 1, 2022

seems that the reason is that all values are exported as def and never as val, and that affects what can be used as en extractor, for example we can "forward it again" manually:

enum E[T]:
  case A(i: Int)

export E.*
val A_Extractor = A // `A` is the exported `E.A`

def f(x: E[Int]) = x match
  case A_Extractor(i) => I

there may be some good reasons not to export as a val, so I wonder if we can tweak the typing of extractor patterns to 'see through' pure methods like export forwarders.

odersky added a commit to dotty-staging/dotty that referenced this issue Jun 3, 2022
There's a strange and almost forgotten rule that disqualifies method symbols
from direct lookup when the identifier is the constructor of a pattern. This
is done to make code like this work:
```
class List[T]:
  def :: (that: T): List[T]
  def f(...) = this match
    case x :: xs => ...
object `::`:
  def unapply...
```
Without the rule, the `::` in the pattern would resolve to the `::` method
in `List` which does not have an `unapply`. We need to skip that method to get
to the outer `::` object.

The rule plays badly with export forwarders, which are methods, and therefore
were ineligible for pattern constructurs. We now change the rule so that methods
are also accepted as unqualified `unapply` prefixes as long as they are parameterless.

Fixes scala#15347
bishabosha pushed a commit to dotty-staging/dotty that referenced this issue Oct 18, 2022
There's a strange and almost forgotten rule that disqualifies method symbols
from direct lookup when the identifier is the constructor of a pattern. This
is done to make code like this work:
```
class List[T]:
  def :: (that: T): List[T]
  def f(...) = this match
    case x :: xs => ...
object `::`:
  def unapply...
```
Without the rule, the `::` in the pattern would resolve to the `::` method
in `List` which does not have an `unapply`. We need to skip that method to get
to the outer `::` object.

The rule plays badly with export forwarders, which are methods, and therefore
were ineligible for pattern constructurs. We now change the rule so that methods
are also accepted as unqualified `unapply` prefixes as long as they are parameterless.

Fixes scala#15347
@Kordyjan Kordyjan added this to the 3.2.0 milestone Aug 1, 2023
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.

4 participants