inko-lang / inko

A language for building concurrent software with confidence

Home Page:http://inko-lang.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

OR sub patterns aren't available when bindings are introduced

yorickpeterse opened this issue · comments

Please describe the bug

Consider code such as this:

try iter.try_each fn (entry) {
  match entry {
    case Ok({ @path = p, @type = File or SymbolicLink }) -> paths.push(p)
    case Ok({ @path = p, @type = Directory }) -> queue.push(p)
    case Ok(_) -> {}
    case Error(e) -> throw ListError.new(path.clone, e)
  }
                                                                          
  Result.Ok(nil)
}

This should work as it does in every other language with pattern matching, but instead it produces a compile error stating that p isn't defined in both the File and SymbolicLink branches.

Please list the exact steps necessary to reproduce the bug

Run this code:

class enum Letter {
  case A
  case B
}

class async Main {
  fn async main {
    let x = (42, Letter.A)

    match x {
      case (x, A or B) -> {}
      case _ -> {}
    }
  }
}

This should compile without any errors, but instead produces:

test.inko:11:16 error(invalid-pattern): this pattern must define the variable 'x'
test.inko:11:21 error(invalid-pattern): this pattern must define the variable 'x'

Operating system

Arch Linux

Inko version

main

Rust version

1.74.1

Related issues

Here's another case where OR patterns mess things up:

class async Main {
  fn async main {
    let x = (42, 50)

    match x {
      case (_a, _b or _b) -> {}
    }
  }
}

This triggers an unreachable!() panic because we don't push the _b bindings out of the OR.

The variables error is fixed, but the case #679 (comment) requires some more thought:

Patterns such as 10 or binding and binding or 10 are nonsensical because they always match. This then begs the question: should we fix the pattern matching compiler not supporting bindings in or patterns (as it reaches an unreachable!()), or should we detect these patterns before then and produce an error. Detecting and erroring is probably easier, but it's a bit odd to produce an error when it's really a case of unreachable code, which normally is a warning.