1
//! CONS / `$pair` construction codegen. The Commodity-specific
2
//! type-mismatch tests moved into the inline `list::tests` module
3
//! since they exercise the private `infer_pair_element` directly —
4
//! script-mode lacks a Commodity producer, and the unit tests are
5
//! the right level for that contract.
6

            
7
use super::common::{compile_and_validate, compile_expect_error};
8

            
9
#[test]
10
1
fn nil_car_in_runtime_string_cell_is_compile_error_not_car_trap() {
11
    // A runtime string element forces the cell to `PairElement::StringRef`.
12
    // A `nil` car must stay a COMPILE error — not a typed null that `CAR`'s
13
    // non-null cast would trap on at runtime. (Value cells coerce nil to a real
14
    // zero; ref cells keep the strict match.)
15
1
    let err =
16
1
        compile_expect_error("(let* ((idx (entity-count))) (cons nil (cons (tag-name idx) nil)))");
17
1
    assert!(
18
1
        err.contains("CONS car") || err.contains("string"),
19
        "expected a car type-mismatch compile error, got: {err}",
20
    );
21
1
}
22

            
23
#[test]
24
1
fn integer_cons_chain() {
25
    // P3a 3a.2: all-integer literal cons chain rides $pair with
26
    // `PairElement::I32`. Replaces the pre-migration i32-only `$cons`.
27
1
    compile_and_validate("(cons 1 (cons 2 (cons 3 nil)))");
28
1
}
29

            
30
#[test]
31
1
fn pair_of_ratios() {
32
    // P3a 3a.3: per-element pair codegen handles Ratio cars without
33
    // the legacy `capture_pending_ratio` helper.
34
1
    compile_and_validate("(cons (/ 1 2) (cons (/ 3 4) nil))");
35
1
}
36

            
37
#[test]
38
1
fn pair_of_strings() {
39
1
    compile_and_validate("(cons \"hi\" (cons \"world\" nil))");
40
1
}