Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion compiler/crates/hy-check/src/emit_guard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1310,7 +1310,9 @@ impl<'a> Checker<'a> {
// TypeRef, so running the builtin-argument check here covers struct
// fields, aliases, local annotations, literals and conversions.
let empty_st = crate::model::FnState::default();
self.check_expr_builtin_args(st.unwrap_or(&empty_st), len);
let st_ref = st.unwrap_or(&empty_st);
self.check_expr_recv_operands(st_ref, len);
self.check_expr_builtin_args(st_ref, len);
let is_wrapped_ident_int_conv = matches!(
unwrap_parens(len),
Expr::Call { callee, args, .. }
Expand Down
2 changes: 1 addition & 1 deletion compiler/crates/hy-check/src/recv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ impl<'a> Checker<'a> {
/// Recurse an expression tree, classifying every `Expr::Receive`
/// operand found at any depth. FnLit bodies are the A5 perimeter —
/// not walked here (the closure pass enters them).
fn check_expr_recv_operands(&mut self, st: &FnState, expr: &Expr) {
pub(crate) fn check_expr_recv_operands(&mut self, st: &FnState, expr: &Expr) {
match expr {
Expr::Receive { chan, span } => {
self.check_recv_operand(st, chan, *span);
Expand Down
43 changes: 43 additions & 0 deletions compiler/crates/hy-check/tests/recv_operand_soundness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,46 @@ fn drain(opt option[chan chan<- int]) {
);
assert_has(&r_select, "HYB-E3008");
}

#[test]
fn decl_type_expr_array_length_non_channel_receive_rejected_3880() {
// Issue #3880: struct field, type alias, enum payload, and fn signature
// array-length TypeExprs must reject receive from non-channel with HYB-E2008.
let r_struct = check(
r#"package main

struct bad_struct {
a [<-5]int
}
"#,
);
assert_has(&r_struct, "HYB-E2008");

let r_alias = check(
r#"package main

type bad_alias = [<-"abc"]int
"#,
);
assert_has(&r_alias, "HYB-E2008");

let r_fn_param = check(
r#"package main

fn run(a [<-5]int) {
_ = a
}
"#,
);
assert_has(&r_fn_param, "HYB-E2008");

let r_fn_ret = check(
r#"package main

fn run() [<-5]int {
return [0]
}
"#,
);
assert_has(&r_fn_ret, "HYB-E2008");
}