Skip to content

Commit ad3f72c

Browse files
committed
Fix captured callable runtime classification
1 parent baed84f commit ad3f72c

2 files changed

Lines changed: 51 additions & 1 deletion

File tree

src/compiler/codegen.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,11 @@ impl Compiler {
254254
self.function_prototype_ids
255255
.insert(function_index, prototype_id);
256256
self.callable_prototypes.push(CallablePrototype {
257-
kind: CallableKind::FunctionItem,
257+
kind: if function_impl.capture_copies.is_empty() {
258+
CallableKind::FunctionItem
259+
} else {
260+
CallableKind::Closure
261+
},
258262
target: CallableTarget::ScriptFunction(script_function_id),
259263
arity: function_impl.param_slots.len() as u8,
260264
frame_local_count: self.frame_local_count,

tests/compiler/compiler_rustscript_tests.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2247,6 +2247,52 @@ fn escaping_closure_retains_its_environment() {
22472247
run_runtime_case(&case);
22482248
}
22492249

2250+
#[test]
2251+
fn closure_aliases_share_state_and_factory_evaluations_are_independent() {
2252+
let case = rustscript_runtime_case(
2253+
"closure aliases share one environment while factory calls allocate distinct environments",
2254+
r#"
2255+
fn make_counter() {
2256+
let mut count = 0;
2257+
fn next() {
2258+
count = count + 1;
2259+
count
2260+
}
2261+
next
2262+
}
2263+
let first = make_counter();
2264+
let alias = first;
2265+
let second = make_counter();
2266+
first();
2267+
alias();
2268+
second();
2269+
"#,
2270+
vec![Value::Int(1), Value::Int(2), Value::Int(1)],
2271+
);
2272+
2273+
run_runtime_case(&case);
2274+
}
2275+
2276+
#[test]
2277+
fn capturing_named_functions_use_closure_runtime_kind() {
2278+
let compiled = vm::compile_source_for_repl(
2279+
r#"
2280+
let captured = 42;
2281+
fn read_captured() { captured }
2282+
read_captured;
2283+
"#,
2284+
)
2285+
.expect("capturing named function should compile");
2286+
let prototype = compiled
2287+
.program
2288+
.callable_prototypes
2289+
.iter()
2290+
.find(|prototype| !prototype.capture_slots.is_empty())
2291+
.expect("capturing named function should have an environment layout");
2292+
2293+
assert_eq!(prototype.kind, vm::CallableKind::Closure);
2294+
}
2295+
22502296
#[test]
22512297
fn callable_equality_distinguishes_items_aliases_and_closure_instances() {
22522298
let case = RuntimeCase {

0 commit comments

Comments
 (0)