Expand description
P6.1 (#1141): the &CheckedProgram → Ir lowering pass — real construction
for the node kinds design/tracks/the-ir.md’s own P6.1 row names (Const,
Local, Global, Record, Field, List, Block, If, And, Or,
Not, Return, Await, Send, Pure); every other IrExprKind/
IrStmt arm is a todo!() naming the slice that completes it
(Decision D).
Correction (Arc D, P7.12): the claim this paragraph made through the
crate carve — “nothing in this module is called from anywhere in
bynk-emit’s existing emission path… it has no consumer yet” — was
false and is corrected here rather than left standing. lower_service_ item_ir unconditionally lowers every handler’s own body, and is
reached for real from bynk_check-typed Events-protocol services via
lower_event_subscriber_shapes_ir (bynk-emit/src/project.rs), reaching
lower_service_handler_ir → lower_service_handler_body_ir →
lower_block_ir → lower_expr_ir/lower_stmt_ir and the rest of this
module’s own recursive expression-lowering machinery — real, live,
production code, verified panic-free across the whole e2e fixture corpus
by a catch_unwind safety probe (see lower_service_item_ir’s own doc
comment). A handful of top-level item constructors genuinely have no
caller outside this crate’s own test suite (lower_agent_item_ir,
lower_provider_item_ir, lower_fn_item_ir, and the handler/store-field/
invariant/transition helpers only those three call) — each of those is
real test-harness infrastructure for the shared lowering machinery above,
not dead code, per this crate carve’s own accepted proposal issue.
Totality discipline (ADR 0334, Q2): every entry point here takes a
&CheckedProgram, not a bare &TypedCommons — a certified program only,
so LowerIrCtx::expr_ty’s .expect() on a miss is the checker and this
pass disagreeing about which expressions a unit contains, a compiler bug,
not a recoverable state. This scoping is the same discipline
bynk-emit/src/emitter/emit.rs’s lower_workers_cross_context_call
already applies to its own bynk.emit.unresolved_cross_context_signature
panic.
Structs§
- Lower
IrCtx - The lowering pass’s own working state: the certified program’s typed
output (for
.ty/.typeslookups), a lexical scope stack this pass tracks itself —TypedCommonshas no persisted “what type does this bound name have” table (that lived only in the checker’s own transientCtx), so the one case that needs it (a record shorthand field,{ x }, which has noExprIdof its own to keyexpr_typesby) re-derives it from the same param/letbinding sites the checker itself walked — and the enclosing fn/method’s own rigid type variables (fn identity[T](x: T), and a generic type’s own params on one of its methods), needed byresolve_type_ref_inthe same wayCtx::type_varsis (bynk-check/src/checker.rs:2816);resolve_type_ref(novarsset) would otherwise resolve a rigidTas an unknown declared type and silently fail.
Functions§
- body_
writes_ state - [DECISION B]/[DECISION C] (#1165): does
bodyreach a mutatingCallee::Storewrite, or an unconditionalStatement::Assign(:=), anywhere — including inside a nestedif/match/lambda? Driveslower_commit_shape_ir’s ownTransactionaldecision, and, as of #1196 (the #1187 emitter-cutover track’s own R6.5 stake),emit_agent‘s (bynk-emit/src/emitter/emit.rs) own real implicit-commit-wrapper decision too — its previous own name-matchingblock_writes_state(emitter.rs) is deleted, this function is its sole, direct replacement. The walk’s own shape is that deleted function’s own already-correct skeleton reused structurally, not re-derived:Block/If/Matchare hand-matched so crossing a nested block re-enters the statement-aware case (anexpr_childrendescent alone flattens a block straight to its statements’ values, losing theStatement::Assigntag), everywhere else recurses overexpr_children’s total child iterator. - capability_
op_ sig_ from_ commons - P6.29 (design/tracks/the-ir.md §6a): the
TypedCommons-only counterpart tolower_capability_item_ir, for call sites (emitter/lower.rs’scap_op_param_names) that have aTypedCommonsin hand but noCheckedProgram—LowerCtx/ModuleCtxnever carry one (seelower_op_sig_ir_from_commons, this function’s own single-op sibling, for the identical reason it exists as a separate entry point rather than a thin wrapper over theCheckedProgram-drivenlower_op_sig_ir). - is_
effectful_ return - P6.50 (design/tracks/the-ir.md §6b): a return type’s own syntactic
Effect[...]wrapper —TypeRef::Effect(_, _), not the resolvedTy::Effect(_)shapelower_handler_signature_irreads above viacx.program.ty_intern. Relocated here fromemitter/emit.rs(its original home,#[allow(dead_code)]-free and with eight call sites acrossemit.rs/workers.rs/workers_entry.rs) becauselower_service_handler_signature_irbelow was already calling up into it (bynk_emit::emitter::is_effectful_return) — theAst → Irboundary running backwards, anIr-side lowering function reaching into theemittermodule it should only ever be called from.emit.rsand friends now callbynk_lower::is_effectful_returninstead (relocated again at the P7.12 crate carve —emitter/ir::lowerare now separate crates,bynk-emit/bynk-lowerrespectively). - lower_
actor_ seam_ ir - #1187’s slice 3: a handler’s resolved actor-verification seam — the same
“narrow, standalone reader of already-resolved data” precedent
body_writes_state/lower_service_handler_signature_irestablished, applied tobynk-check’s own five actor-seam resolvers (bynk-check/src/actors.rs) instead of a fullIrHandlerassembly.ActorSeamIr’s own doc comment has the full grounding for the priority order and for the deliberately-missingSignaturevariant. - lower_
agent_ item_ ir - P6.10 (#1169): assemble an agent declaration into a real
bynk_ir::IrItem::Agent— wires every prior slice’s own standalone constructor (lower_store_field_irsince P6.7,lower_invariant_ir/lower_transition_ir/lower_commit_shape_irsince P6.8,lower_handler_irsince P6.9) rather than re-deriving any of their logic — the firstIrItemvariant assembled from other already-real IR data rather than lowered fresh from the AST by itself. - lower_
attached_ fn_ sig_ ir_ from_ types - P6.x (#1137):
lower_fn_sig_ir_from_typesover an entireMethodTable’s own instance + static entries — the attached-method gathering [bynk-emit’sbuild_emit_unit_ctx] needs for auses-imported type. Filters toFnName::Methodbefore lowering:ResolverMethodTableonly ever collects attached methods in practice (bynk-check/src/resolver.rs’s own doc comment onMethodTable), but the filter stays as a defensive match rather than an assumption, matching the caller’s own pre-existing posture one step earlier — this just moves that posture in front of the lowering call instead of behind it, so theFnNameread (and the filter itself) never has to leave this module. - lower_
block_ ir - Lower a block as a value — no
Returnwrapping (seelower_fn_body_ir’s doc comment for the distinction). A block’s own type is always its tail’s type. - lower_
capability_ item_ ir - P6.12 (#1173): assemble a capability declaration into a real
bynk_ir::IrItem::Capability— structural mirror oflower_service_item_ir/lower_agent_item_ir, but with nothing to compute once and share:CapabilityDeclcarries no state/invariants/ transitions/protocol of its own, onlyops, so each op lowers independently throughlower_op_sig_ir. - lower_
commit_ shape_ ir - P6.8 ([DECISION B]/[DECISION D]/[DECISION F], #1165): decide a handler
body’s own one-of-three
CommitShapefrom resolved data —body_writes_state’s own write-detection walk, plusemits([DECISION D]: the caller’s ownbynk_emit::emitter::block_uses_emit(body)call, not re-derived here — noCalleeclassification exists forEvents.emitto consume instead, see that decision’s own grounding). Does not lowerbodyinto anIrExprtree first ([DECISION B]) — deciding the shape only needs the two booleans, and lowering the whole body just to throw the result away would be pure waste; a realIrHandler.bodylowering is a separate, not-yet-commissioned step (seebynk_ir::IrItem’s own doc comment). - lower_
event_ subscriber_ shapes_ ir - P6.47 (design/tracks/the-ir.md §6b): every
from Events(E)service inprogram’s own unit, captured as anbynk_ir::EventSubscriberShapekeyed by service name — see that struct’s own doc comment for why this is captured now rather than re-derived cross-unit at compose time. Absorbs theServiceProtocol::Eventspre-filter this function’s own single call site used to apply externally:lower_service_item_irunconditionally lowers every handler’s own body (not just its declared shape), so the guard stays first here too — a cheap, structural pre-filter (which services even have a shape to capture), not a resurrected raw-AST read — before paying for a full lowering pass on a matching service. Safe as of #1254: acatch_unwindprobe wrappinglower_service_item_iracross the entire e2e fixture corpus found zero panics, down from ~51 when the P6.23 investigation first ran. - lower_
expr_ ir - lower_
fn_ body_ ir - Lower a function/method body: seeds scope from
f’s params (and its own rigid type variables — its own[T, ...]type parameters, plus a generic receiver’s, for a method), lowers the body as an ordinary value block, then wraps the tail viawrap_body_return. Distinct fromlower_block_ir, which lowers a nested block as a bare value with no such wrapping. - lower_
fn_ item_ ir - P6.6 (#1161): lower a
fndeclaration into a realIrItem::Fn— wrapslower_fn_body_ir(#1141, unchanged) rather than re-deriving its own rigid-variable seeding or body lowering; adds onlydef/receiver/params/ret/effectfularound its existing return value. Covers both free functions and methods alike (FnName::Free/FnName::Method) — whichIrItem::Fns a future printer re-attaches under whichIrItem::Type’s own namespace (R8.1) is phase 7’s own concern, not decided here. - lower_
fn_ sig_ ir_ from_ types - P6.18:
bynk_ir::FnSig’s own constructor — afn’s own resolved signature, for a call site holding only that fn’s declaring unit’s own combined types (bynk_check::symbols::combined_types_for’s return shape), never aCheckedProgram. The one real call site (bynk-emit/src/project.rs’sbuild_emit_unit_ctx) reads auses- imported foreign unit’s own attached methods, whose ownCheckedProgramdoes not survive past that unit’s owncheck_unit_filesiteration — the same “dropped before any later, project-wide pass runs” shapeunit_callees(#1202)/EventSubscriberShape(#1232) both work around, except here no project-wide accumulator is needed at all: unlike aCallee/event-subscriber-shape classification (checker-only facts, never re-derivable from raw declarations alone), a fn signature’s ownparams/return_typeare ordinary type references, resolvable from that unit’s own declared types the same waylower_op_sig_ir_from_commonsalready resolves a capability op’s — so a bare types map is sufficient, the same non-CheckedProgramscope that function already established. - lower_
handler_ given_ ir - #1187’s slice 6 plumbing (sibling of
lower_provider_given_ir): a handler’s owngivenclause, resolved independent of any fullIrHandler/IrItemassembly — the standalone entry point forproject.rs’splan_agent_given_deps,EmitProjectCtx:: agent_method_givens, andemitter/workers.rs’s owngivencollection. Reuseslower_cap_ref_irverbatim; a handler’sgivenis syntactically identical to a provider’s (bynk_syntax::ast::CapRef), so this is the same one-line adapter, not a new design. - lower_
handler_ ir - P6.9’s real
IrHandlerconstructor ([DECISION C]/[DECISION D]/ [DECISION E], #1167) — lowers an agenton callhandlerhinto a realIrHandler.store_cells/state_ty/invariants/transitionsare parameters, not re-derived ([DECISION E], mirroringlower_invariant_ir’s/lower_transition_ir’s own precedent, P6.8): no persisted “this agent’s store cells / state type” table survivescheck_agent_decls’s own transient scope, andinvariants/transitionsare themselves already-loweredIrPredicates a caller must have produced via those same two functions — this function only threads them intolower_commit_shape_ir, never lowers or re-derives them itself. A futureIrItem::Agentbuilder (not commissioned by this slice — seebynk_ir::IrItem’s own doc comment) computes all four once per agent and calls this function once per handler, not re-deriving any of them per call. - lower_
handler_ kind_ ir - P6.24a: pure, unconditional
HandlerKind→IrHandlerKindconversion — every field is already fully resolved at parse time, so unlike almost every other function in this module this one takes no&CheckedProgram/&TypedCommonsat all and can never miss. - lower_
invariant_ ir - P6.8 ([DECISION A]/[DECISION E], #1165): lower an agent invariant into a
real
IrPredicate— seeds the predicate’s own scope fromstore_cellsexactly aschecker::check_invariantsdoes (bynk-check/src/checker.rs: eachstoreCellfield in scope by bare name, reading as its element type), then lowerspredicatethrough the ordinarylower_expr_irmachinery unchanged. Takesstore_cellsas a parameter rather than re-deriving it fromprogram([DECISION E]) — a certifiedCheckedProgramcarries no persisted “this agent’s store cells” table; that scope ischeck_agent_decls’s own transient scratch, never persisted toTypedCommons. Called once per agent’s own invariant list, by whichever future slice buildsIrItem::Agentfor real — not once per handler, mirroringcheck_invariants’s own once-per-agent posture. - lower_
op_ sig_ ir_ from_ commons - #1187’s own closing scoping pass: a
TypedCommons-only sibling oflower_op_sig_ir, for the one real call site that never has a&CheckedProgram—emitter/lower.rs’scap_op_param_names, feedingtrace(Cap.op)/with-predicate observation lowering (bynk.test’s DSL). That call path’s ownTypedCommonsis a synthetic, hand-assembled project-wide view (project/tests_emit.rs’ssynthetic_typed_commons_for_target, merging every consumed unit’s owncapabilitydeclarations into one scratch commons for lookup) — never itself the output ofcertify, so wrapping it as aCheckedProgramhere would misrepresent an uncertified value as certified (CheckedProgram’s own doc comment,bynk-check/src/checker.rs, warns against exactly this). Splitting this out is sound precisely because this function never callsLowerIrCtx::expr_ty— the one method whose.expect()-panic needs a genuinely certified program, the reason this module’s own file-level doc comment gives for taking&CheckedProgrameverywhere else.resolve_type_ref/unit_ty()(below) both degrade via.unwrap_or_elseand read nothingTypedCommonsdoesn’t already expose directly. - lower_
protocol_ ir - P6.11 ([DECISION A], #1171): lower a service’s own
from <protocol>header into a realProtocolIr— standalone, takes the sub-node rather than the owningServiceDecl(mirrorslower_store_field_ir), so afrom websocket/from Eventsfixture can pin the descriptor by itself even wherelower_service_handler_ircannot yet lower every handler on the same service (the WebSocket lifecycle-body deferral — see that function’s own doc comment). - lower_
protocol_ ir_ from_ commons - P6.24a: a
TypedCommons-only sibling oflower_protocol_ir, the same splitlower_op_sig_ir/lower_op_sig_ir_from_commonsalready established — for a call site holding only a unit’s ownTypedCommons, never a&CheckedProgram(emitter.rs’semit_project_imports, a header-import-collection pass that runs well outside the per-declaration emission loop anyCheckedProgramis threaded through). Sound for the identical reason: this function never callsLowerIrCtx::expr_ty, the one method whose.expect()-panic needs a genuinely certified program. - lower_
provider_ given_ ir - A provider’s own
givenclause, resolved independent ofProviderBody’sexternal/Bynkdispatch and independent oflower_provider_item_ir’s own full assembly (#1187’s Providergiven/deps-wiring slice) — the standalone entry pointbynk-emit/src/project.rs’sinstantiate_provider_ts_expractually calls. Building a realIrItem::Providerthere would still need care for aBynkprovider specifically:ProviderBody::Bynk::opsunconditionally lowers every op’s body throughlower_provider_op_ir→lower_expr_ir, which does not yet handle every expression shape a real op body can contain. Correction (P6.25, 2026-08-19):?propagation (ExprKind::Question) and anis-expression (ExprKind::Is) are no longer among those gaps — both landed (P6.15/ADR 0337, P6.16/ADR 0338, following #1225’s ownOk/Err/Some/Noneconstruction fix) — butlower_expr_irstill has two production-reachabletodo!()s (lower_call_ir’s missing-Calleeguard and a bare ident naming a free fn used as a value, P6.2 territory), so a real op body is not yet unconditionally safe to build; the risk has just narrowed. This function never touchesops/bodies, so it carries none of that risk;lower_provider_item_iritself now calls it too, rather than hand-duplicating the one-linemap. - lower_
provider_ item_ ir - P6.14 (#1174): assemble a provider declaration into a real
bynk_ir::IrItem::Provider— readsProviderDecl::externalstraight intoProviderBody’s ownBynk/Externaldispatch (bynk_ir::IrItem’s own doc comment has the full grounding for why this, unlikeActor, was buildable this slice).external: truemeansopsis empty by the field’s own doc comment (bynk-syntax/src/ast.rs:592-595) — nothing to lower.givenlowers unconditionally vialower_provider_given_ir(#1187’s Providergiven/deps-wiring slice, fixing a real gap theExternalvariant’s own bare-unit shape used to leave:provider.givenis populated the same way regardless ofexternal, andProviderBody::Bynk’s own doc comment names why it, unlikemodule, is not deferrable — that reasoning always applied toExternaltoo, just wasn’t wired through). - lower_
route_ cache_ ir - #1228: a GET handler’s own
@cache(maxAge:, scope:)freshness policy —bynk_ir::CacheIr’s own doc comment has the full grounding for why this is a standalone reader rather than aPolicyIrfield. Field-for- field the same extractionemitter/workers_entry.rs’s own (now superseded)cache_policy_fordid: only aGETyields a policy; project validation (bynk.http.cache_*) has already rejected a@cacheanywhere else, and a malformedmaxAgethere, so a missing or ill-formed annotation here simply yieldsNone— no&CheckedProgramneeded, the same posturelower_policy_ir’s own doc comment already argues for:maxAge/scopeare already-resolved syntactic literals (ExprKind::DurationLit/Ident), not a type this pass would ever need to resolve. - lower_
route_ limit_ ir - #1228: a route’s own
@limit(maxBody:)annotation, if present — the override half ofemitter/workers_entry.rs’s own (now superseded)effective_max_body; the service-widelimits { maxBody }fallback stays that function’s own concern (already IR-native viaPolicyIr::max_body_bytes, but read from a service, not a per-routeHandler, so it does not move here). Project validation (bynk.http.limit_*/limits_*) has already rejected a malformed or misplaced@limit, so an absent/ill-formed annotation here simply yieldsNone— the caller’s own service-default fallback still applies. No&CheckedProgramneeded, same reasoning aslower_route_cache_ir:maxBodyis an already-resolvedExprKind::IntLit, not a type. - lower_
service_ handler_ ir - P6.11’s real service-handler
IrHandlerconstructor ([DECISION E], #1171) — the sibling tolower_handler_ir, not a widening of it.lower_fn_body_ir’s own doc comment already states the governing rule (“a free fn/method and an agent handler seed genuinely different scopes … that would otherwise have to coexist behind one signature for no shared benefit”); the same reasoning gives the same answer here, more strongly: - lower_
service_ handler_ signature_ ir - #1187’s slice 5 (the
Serviceemitter 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 realIrHandler/bynk_ir::IrItem::Service: bothlower_handler_ir/lower_service_handler_irunconditionally lower the handler’s own body into a realIrExpr(IrHandler::bodyis notOption), and an ordinaryfrom httphandler’s body routinely uses?propagation (ExprKind::Question) or anis-expression (ExprKind::Is). Correction (P6.25, 2026-08-19): both landed —Questionas P6.15 (ADR 0337,lower_question_ir, decomposing toIrExprKind::Matchper #1225’s ownOk/Err/Some/Noneidentity precedent) andIsas P6.16 (ADR 0338,lower_is_ir, a forced-tempLetdischarging R5.10). Neither is reached from this call site or any other shipped emitter path yet —emitter/lower.rs’s own P6.2Call/Lambdacutover hasn’t landed — so the reasoning below (a realIrHandlerhere would still panic on other, still-unconverted constructs reachable from an ordinaryfrom httpbody) stands, just not onQuestion/Isspecifically anymore. Building a realIrHandleratemit_service’s own call site would panic on exactly the ordinary Http services this slice needs to keep working. Mirrorsbody_writes_state’s own precedent (#1196): a narrow, standalone reader of already-resolved data, not the fullIrItem/IrHandlerassembly — the same posture, applied to signature data instead of a single boolean. Deliberately notlower_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.rsskipsCommonsItem::Servicein every type-ref-resolution pass,check_handler_bodysilently skips a param whose type doesn’t resolve and silently returns on an unresolvable return type (no diagnostic either way), andcheck_http_handleronly constrains a param’s name (path segment orbody), never validates abody:param’s own declared type. A service handler naming an undeclared type certifies today (and previously just emitted that bad name verbatim, atsc-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 { ... }panicsbynkcbefore this fix). Mirrorslower_protocol_ir’s ownTy::Unit-on-miss posture, for the identical underlying reason (that function’s own doc comment already documents the checker’s Service-wide resolution gap). - lower_
service_ item_ ir - P6.11 (#1171): assemble a service declaration into a real
bynk_ir::IrItem::Service— structural mirror oflower_agent_item_ir, wiringlower_protocol_ir,lower_service_handler_irandlower_policy_irrather than re-deriving any of their logic. Unlike the agent case, there is no shared per-declaration context to compute once: a service has nostore_cells/state_ty/invariants/transitions (none of those concepts exist for a service at all), so&service.protocol, already on the declaration, is threaded to each handler call directly — the “compute once, reuse” steplower_agent_item_ir’s own doc comment describes degenerates to a borrow here, not because this function skips a step, but because a service’s own handlers have nothing else to share. - lower_
store_ field_ ir - P6.7 (#1163): lower an agent
storefield declaration into a realStoreFieldIr— dispatches onf.kind.head.nameintoStoreKindIr’s five real variants;Queuecannot reach a certified program (bynk.store.kind_unsupportedgates it beforecertify, R3.10), so this match is total over what one can actually contain, not a gap needing its own extension later. - lower_
store_ field_ shape_ ir - #1187’s Agent state-field slice:
lower_store_field_ir’s shape-only sibling — samekind/indexed(viastore_field_kind_and_indexed),initalwaysNone. This is the entry pointemit_agent’s own state section actually needs: a field’s storage shape (itsCell/Map/Set/Cache/Logkind and@indexedkeys), never itsCellzero/ initial value expression. Deliberately never lowersinit, unlikelower_store_field_ir— aCellfield’s initializer can be anis-expression (= x is SomeVariant), which still hitsExprKind::Is’s owntodo!()a few hundred lines below (1029_agent_static_init_hoist’sstore active: Cell[Bool] = if true { 5 is PositiveInt } else { false }hits exactly this onlower_store_field_ir’s owninitarm). The sibling= Noneshape (223_store_cell_agent’s ownstore paymentRef: Cell[Option[AuthId]] = None) no longer needs this workaround as of #1225’s own ADR —lower_store_field_irlowers it directly now (store_field_cell_option_init_none_lowers_without_panicking). This function’s callers never needinitat all regardless, so neither gap is a risk for them. - lower_
transition_ ir - P6.8 ([DECISION A]/[DECISION E], #1165): lower a step invariant
(
Transition) into a realIrPredicate— seedsold/new, both bound to the agent’s own synthetic state-record type, exactly aschecker::check_transitionsdoes.state_tyis a parameter, not re-derived, for the same reasonlower_invariant_ir’s ownstore_cellsis: no persisted “this agent’s state type” table survives pastcheck_agent_decls’s own transient scope. Called once per agent’s own transition list, by the same future callerlower_invariant_irnames. - lower_
type_ item_ ir - P6.6 (#1161): lower a
typedeclaration into a realIrItem::Type—IrItem’s own doc comment names which of its seven design-sketch variants are real as of this slice (Type/Fnonly, Decision D). Takes a certified&CheckedProgram, matching this module’s own categorical discipline (this file’s own header doc: “every entry point here takes a&CheckedProgram”), even though onlyTypedCommons::types/ty_internare read — no per-expressionexpr_typeslookup is involved (Q2,design/tracks/the-ir.md§3.2), but which fields are read isn’t the discipline; which failures are allowed topanic!is. Every panic below asserts “the checker already accepted this declaration” — true only oncecertifyhas run: a bareTypedCommonsis not certified by construction (checker.rs’s ownCheckedProgramdoc notes the project/batch path holds per-unitTypedCommonsvalues before that unit’s build-wide gate is decided), so accepting one here would makeresolve_type_ref_inreturningNonea reachable, not just a buggy, outcome.
Type Aliases§
- Handler
Signature Ir (params, given, ret, effectful)—lower_handler_signature_ir’s own return shape, andlower_service_handler_signature_ir’s (#1187’s slice 5), reused as a named alias rather than a bare tuple at both call sites once one of them (emit_service,bynk-emit/src/emitter/emit.rs) had to spell it out in a function signature.