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.