You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[soundness] hy-check(channel_liveness): function parameter capabilities (hy.send_cap[T] / hy.recv_cap[T]) untracked, bypassing linearity, affine transfer, and terminal lifecycle checks (#4200 regression) #4416
\\hy
// repro4_undrained_recv.hy — receive capability parameter leaked without draining
fn receiver(rx hy.recv_cap[int]) {
v := rx.recv()
_ = v
// rx is never drained or moved before function returns; messages abandoned!
}
**
epro1_unclosed_sender.hy**: Reject (\exit 1) with *\HYB-E4004* (\linear send capability 'tx' was not closed before scope exit).
**
epro2_double_move.hy**: Reject (\exit 1) with *\HYB-E3001* (\�ffine capability 'tx' moved more than once).
**
epro3_use_after_move.hy**: Reject (\exit 1) with *\HYB-E3001* (\use of moved linear capability 'tx').
**
epro4_undrained_recv.hy**: Reject (\exit 1) with *\HYB-E4005* (\linear receive capability 'rx' was not drained before scope exit).
**
epro5_unmoved_task_capture.hy**: Reject (\exit 1) with *\HYB-E3002* (\unmoved capture 'tx' across task boundary is forbidden; must be explicitly transferred with 'move').
During function body analysis in compiler/crates/hy-check/src/channel_liveness.rs, ChannelLivenessChecker::check_fn_decl initializes the local dataflow liveness context solely from inside-body variable declarations (such as destructuring hy.pipe[T]() calls). It fails to inspect and seed the function parameter list (fn_decl.params) into the linear tracking map (CapabilityTracker).
Because hy.send_cap[T] and hy.recv_cap[T] function parameters are omitted from the initial AST variable binding map for the scope:
Asynchronous task captures of parameters bypass move-mode validations, disabling HYB-E3002 (unmoved capture across task boundaries).
Terminal liveness verification at function scope exit skips parameter symbols, permitting leaking unclosed send capabilities (bypassing HYB-E4004) and undrained receive capabilities (bypassing HYB-E4005).
Patch Solution
In compiler/crates/hy-check/src/channel_liveness.rs, seed all function parameter capabilities into the AST scope's active linear environment prior to visiting the function block.
--- a/compiler/crates/hy-check/src/channel_liveness.rs+++ b/compiler/crates/hy-check/src/channel_liveness.rs@@ -112,6 +112,23 @@ impl<'a> Visitor<'a> for ChannelLivenessChecker {
fn visit_fn_decl(&mut self, func: &'a FnDecl) {
self.scopes.enter_scope(ScopeKind::Function);
+ // Seed parameter capability bindings into the current scope's linear tracker+ for param in &func.params {+ if let Some(cap_ty) = self.type_cx.resolve_capability_type(¶m.ty) {+ let state = CapabilityState::new(+ param.id,+ param.name.clone(),+ cap_ty,+ param.span,+ );+ if let Err(err) = self.tracker.register_capability(param.id, state) {+ self.diagnostics.emit(err);+ }+ }+ }+
self.visit_block(&func.body);
// Validate linearity and terminal lifecycle states for all scoped capabilities
+ self.tracker.check_scope_terminal_states(&mut self.diagnostics);
self.scopes.exit_scope();
}
Regression Test Coverage
Add integration tests in compiler/crates/hy-check/tests/channel_liveness_test.rs ensuring all five parameter escape vectors trigger diagnostics:
Activity
dukenordj-rgb commentedon Nov 12, 2026
Root Cause
During function body analysis in
compiler/crates/hy-check/src/channel_liveness.rs,ChannelLivenessChecker::check_fn_declinitializes the local dataflow liveness context solely from inside-body variable declarations (such as destructuringhy.pipe[T]()calls). It fails to inspect and seed the function parameter list (fn_decl.params) into the linear tracking map (CapabilityTracker).Because
hy.send_cap[T]andhy.recv_cap[T]function parameters are omitted from the initial AST variable binding map for the scope:move tx) on parameter bindings bypass single-ownership tracking, disablingHYB-E3001(double move / use-after-move).HYB-E3002(unmoved capture across task boundaries).HYB-E4004) and undrained receive capabilities (bypassingHYB-E4005).Patch Solution
In
compiler/crates/hy-check/src/channel_liveness.rs, seed all function parameter capabilities into the AST scope's active linear environment prior to visiting the function block.Regression Test Coverage
Add integration tests in
compiler/crates/hy-check/tests/channel_liveness_test.rsensuring all five parameter escape vectors trigger diagnostics: