Skip to content

Any type shadows type error in match expressions #742

@In-Veritas

Description

@In-Veritas

Reproducing the behavior

Issue Description

When defining functions that operate on Maybe(A) types, the type checker seems to behave inconsistently, particularly when the unreachable() function is used in a pattern match. Here's an example to illustrate the problem:

Problematic Code

type Maybe(T):
  Some{val: T}
  None 

def Maybe/bug(maybe: Maybe(A)) -> Maybe(A):
    match maybe:
        case Maybe/Some:
            return Maybe/Some(Maybe/Some(maybe.val))
        case Maybe/None:
            return unreachable()

def main():
    return Maybe/bug(Maybe/Some(12))

Result:

The above code executes without type errors, producing the following result:

λa (a Maybe/Some/tag λb (b Maybe/Some/tag 12))

This is unexpected, as the function violates the intended type constraints of Maybe(A).


Correct Behavior

When the function avoids using unreachable() and handles the Maybe/None case with a valid return, the type checker properly enforces the constraints, as seen in the code below:

type Maybe(T):
  Some{val: T}
  None 

def Maybe/bug2(maybe: Maybe(A), x: A) -> Maybe(A):
    match maybe:
        case Maybe/Some:
            return Maybe/Some(Maybe/Some(maybe.val))
        case Maybe/None:
            return Maybe/Some(x)

def main():
    return Maybe/bug2(Maybe/Some(12), 24)

Result:

Running the above code correctly triggers a type error:

Type Error: Expected function type '((Maybe A) -> A -> (Maybe A))' 
but found '((Maybe h) -> (Maybe h) -> (Maybe (Maybe h)))'. 
Variable 'a' occurs in '(Maybe a)'

Analysis

  • Function with unreachable() (Maybe/bug): The type checker does not enforce type correctness, allowing invalid types to pass through and the function to execute.
  • Function without unreachable() (Maybe/bug2): The type checker properly identifies type mismatches and raises an error, preventing invalid behavior.

This inconsistency demonstrates that using unreachable() somehow bypasses type-checking mechanisms.


Expected Behavior

The type checker should raise an error for Maybe/bug, similar to the behavior observed in Maybe/bug2, since the return type violates the Maybe(A) constraint.


Steps to Reproduce

  1. Define the functions Maybe/bug and Maybe/bug2 as described above.
  2. Run the main() function for each case.
  3. Observe the behavior:
    • Maybe/bug: No type error, invalid output.
    • Maybe/bug2: Type error, expected behavior.

System Settings

Environment:

  • HVM: [hvm 2.0.22]
  • Bend: [bend-lang 0.2.37]
  • OS: [Ubuntu 22.04.3 LTS]
  • CPU: [Intel i7-10700KF]
  • GPU: [RTX 2070]

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcompilationCompilation of terms and functions to HVM

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions