Skip to main content
v0.14.0

RFC-0167's error-code reclassification and main-entry Legality Rule are not implemented

Limitation​

RFC-0167 (2-accepted, moved to 3-integrated 2026-09-28) reclassifies six unsoundness-only runtime codes (R0003, R0006, R0008, R0009, R0010, R0011) as internal errors (I0003-I0008), retires R0001/R0002 in favor of a new compile-time Legality Rule (T0031, spec.functions.program-entry-point.legality-1) for the program's main function, and splits R0002's two non-main raise sites into I0007 (merging with the R0010 reclassification) and a wholly new I0009. None of this is implemented: metel-frontend/src/data/error/mod.rs's RuntimeErrorCode/InternalErrorCode/TypeErrorCode enums are unchanged, and evaluator/mod.rs's env.get("main") check still runs lazily at evaluator startup, not during typechecking. Every one of R0001/R0002/R0003/R0006/R0008/R0009/R0010/R0011 continues to fire exactly as documented in their own (now-retired) error-codes.md entries.

Impact​

A program triggering any of the six reclassified codes, or either main-entry case, still sees the pre-RFC-0167 code and message today — the reclassification is a documentation-and-numbering decision made now (per RFC-0167's own Migration section: "new number assignment happens at integration time"), not yet backed by matching interpreter behavior. The nine new/retired-target entries in error-codes.md (T0031, I0003-I0009) and the new spec.functions.program-entry-point.legality-1 rule in reference/spec/functions.md are exempted from fixture coverage for this reason; the eight retired entries (R0001/R0002/R0003/R0006/R0008/R0009/ R0010/R0011) keep their own existing fixtures/exemptions unchanged, since they still accurately describe today's actual behavior.

Affects​

Resolution​

Implemented 2026-09-28, tracked by metel-core#991 (RFC-0167, milestone v0.14.0). metel-frontend/src/data/error/mod.rs's RuntimeErrorCode no longer has R0001-R0003/ R0006/R0008-R0011; InternalErrorCode gained I0003-I0009; TypeErrorCode gained T0031. evaluator/mod.rs::evaluate_graph_with_options now runs a new check_program_entry_point static check against the root module's already-typed declarations before any module's passes run (not lazily inside run_main as env.get("main") used to), raising T0031 for a missing/non-function/generic/ non-zero-arity main; run_main itself no longer raises R0001/R0002 at all -- every remaining arm there is a "should be unreachable after T0031" internal-error defensive fallback. All eight retired R-codes' raise sites in call.rs/lvalue.rs/ builtins.rs/evaluator/mod.rs now raise their I00NN/T0031 replacements instead. Fixtures neg_07_no_main/neg_08_main_not_a_function were updated to expect T0031/typecheck_error; two new fixtures (neg_09_main_is_generic, neg_10_main_has_params) were added since no fixture previously exercised those cases. error-codes.md's and spec.functions.program-entry-point.legality-1's blocked-on-#991 exemptions are removed now that real fixtures cover them; the per-code blocked-on-#986/#989 reachability exemptions on I0003-I0008 carry over unchanged from their retired R-code predecessors (the underlying reachability question, not the RFC-0167 timing question, which is now moot).