pub fn lower_service_handler_signature_ir(
h: &Handler,
program: &CheckedProgram,
) -> HandlerSignatureIrExpand description
#1187’s slice 5 (the Service emitter cutover): emit_service’s own
standalone entry point for a handler’s resolved signature only —
params/ret/effectful, never the body. Deliberately does not build
a real IrHandler/bynk_ir::IrItem::Service: both
lower_handler_ir/lower_service_handler_ir unconditionally lower
the handler’s own body into a real IrExpr (IrHandler::body is not
Option), and an ordinary from http handler’s body routinely uses ?
propagation (ExprKind::Question) or an is-expression (ExprKind::Is).
Correction (P6.25, 2026-08-19): both landed — Question as P6.15
(ADR 0337, lower_question_ir, decomposing to IrExprKind::Match per
#1225’s own Ok/Err/Some/None identity precedent) and Is as P6.16
(ADR 0338, lower_is_ir, a forced-temp Let discharging R5.10). Neither
is reached from this call site or any other shipped emitter path yet —
emitter/lower.rs’s own P6.2 Call/Lambda cutover hasn’t landed — so
the reasoning below (a real IrHandler here would still panic on other,
still-unconverted constructs reachable from an ordinary from http body)
stands, just not on Question/Is specifically anymore. Building a real
IrHandler at emit_service’s own call
site would panic on exactly the ordinary Http services this slice needs
to keep working. Mirrors
body_writes_state’s own precedent (#1196): a narrow, standalone
reader of already-resolved data, not the full IrItem/IrHandler
assembly — the same posture, applied to signature data instead of a
single boolean.
Deliberately not lower_handler_signature_ir(h, &cx) (review of
#1198) — that helper’s own ADR 0334 .unwrap_or_else(|| panic!(..)) on a
resolution miss is correct for an agent handler (the checker
guarantees resolution there) but not for a service one:
resolver.rs skips CommonsItem::Service in every type-ref-resolution
pass, check_handler_body silently skips a param whose type doesn’t
resolve and silently returns on an unresolvable return type (no
diagnostic either way), and check_http_handler only constrains a
param’s name (path segment or body), never validates a body:
param’s own declared type. A service handler naming an undeclared type
certifies today (and previously just emitted that bad name verbatim, a
tsc-only failure) — reusing the strict helper here would turn that
pre-existing, real-but-harmless-to-the-compiler gap into an ICE on the
production emit path for every service in every project (confirmed live:
on POST("/x") (body: Nope) -> Effect[HttpResult[String]] by v: Visitor { ... } panics bynkc before this fix). Mirrors lower_protocol_ir’s
own Ty::Unit-on-miss posture, for the identical underlying reason (that
function’s own doc comment already documents the checker’s Service-wide
resolution gap).
effectful is computed from h.return_type’s own AST shape
(TypeRef::Effect(..), matching is_effectful_return exactly), not
from the resolved ret’s Ty::Effect(_) shape — a
resolution miss on ret (falling back to Ty::Unit below) must not
silently flip an Effect[Nope]-returning handler to non-effectful; the
top-level Effect[...] wrapper is always syntactically determinable
regardless of whether its own inner type resolves.