Issue #624: A catch over a method that calls stored code matches the boxed error by its types without opening the box: rustc refuses (C.1)

Open and answer this issue on GitHub.

ready · opened 2026-10-14 · updated 2026-10-14 · 0 comments

What happens

Nikaia accepts this program, and the Rust it lowers to is refused by rustc (Part III C.1). Checked on develop 0.0.964.

enum Bad { Oops }
enum Worse { Boom }
impl Error for Bad { fn message(ref self) -> String { return "oops".clone() } }
impl Error for Worse { fn message(ref self) -> String { return "boom".clone() } }

struct Task { run: fn() throws }
struct Registry { tasks: Vec[Task] }

impl Registry {
    fn register(ref mut self, t: Task) { self.tasks.push(t) }
    fn fire(ref self) throws { for t in self.tasks { t.run() } }
}

fn fail() throws { throw Bad::Oops }
fn worse() throws { throw Worse::Boom }

fn main() {
    let mut r = Registry { tasks: [] }
    r.register(Task { run: fail })
    r.register(Task { run: worse })
    r.fire() catch {
        match error {
            Bad::Oops => println("oops"),
            Worse::Boom => println("boom"),
            else => println("other"),
        }
    }
}

rustc reports Mismatched types at match error twice: expected Box<dyn std::error::Error>, found Bad, and the same for Worse.

Why

fire lowers to async fn fire(&self) -> Result<(), Box<dyn std::error::Error>>, because the stored code’s channel is the box. The catch at the caller is lowered as if the error were the sum: match error { Bad::Oops => …, Worse::Boom => …, _ => … }. It does not open the box by the type each arm names. The opening that exists for a call through a field or a name of code (0.0.956, check_boxes.nika) does not reach a call to a method whose body calls stored code.

To build

  1. In the emitter, a catch over a call whose callee’s channel is the box opens it by the type each arm names (downcast), whatever path made the callee boxed. A method, a free function and a call through a value should all go through the same path.
  2. Test: the program above runs and prints oops.

Related: #620 (ADR-351; this is the registry case discussed there, and #620 may lower it without the box). Independent of how #620’s open question is decided, Nikaia must not accept a program that rustc refuses.

Back to Open Issues