#![cfg(any(
not(any(
feature = "parser_tests",
feature = "analyzer_tests",
feature = "codegen_tests",
feature = "interpreter_tests",
feature = "conformance_tests",
feature = "integration_tests",
)),
feature = "analyzer_tests",
))]
#[path = "common/test_utils.rs"]
mod test_utils;
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_auto_borrow_owned_vec_to_ref_param() {
let code = r#"
pub fn process_items(items: Vec<i32>) -> i32 {
let mut sum = 0
for i in items {
sum = sum + *i
}
sum
}
pub fn main() -> i32 {
let v = vec![1, 2, 3]
process_items(v)
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
assert!(
generated.contains("process_items(&v)"),
"Should auto-borrow: process_items(v) → process_items(&v). Got:\n{}",
generated
);
assert!(success, "Must compile. Error:\n{}", err);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_auto_borrow_owned_string_to_ref_param() {
let code = r#"
pub fn print_len(s: string) -> usize {
s.len()
}
pub fn main() -> usize {
let text = "hello".to_string()
print_len(text)
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
assert!(
generated.contains("print_len(&text)") || generated.contains("print_len(text"),
"Should auto-borrow owned String. Got:\n{}",
generated
);
assert!(success, "Must compile. Error:\n{}", err);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_auto_borrow_index_result_to_ref_param() {
let code = r#"
pub struct Point { x: f32, y: f32 }
pub fn distance(p: Point) -> f32 {
(p.x * p.x + p.y * p.y).sqrt()
}
pub fn main() -> f32 {
let points = vec![Point { x: 1.0, y: 0.0 }, Point { x: 0.0, y: 1.0 }]
distance(points[0])
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
assert!(
generated.contains("distance(&points[0])") || generated.contains("distance(points[0]"),
"Should handle index to ref param. Got:\n{}",
generated
);
assert!(success, "Must compile. Error:\n{}", err);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_auto_deref_ref_copy_to_value_param() {
let code = r#"
pub fn double(x: i32) -> i32 {
x * 2
}
pub fn main() -> i32 {
let n = 42
let r = &n
double(r)
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
assert!(
generated.contains("double(*r)") || generated.contains("double(r)"),
"Should auto-deref &i32 when param expects i32. Got:\n{}",
generated
);
if !success {
assert!(
err.contains("E0308") || err.contains("expected `i32`"),
"Unexpected rustc error. Error:\n{}",
err
);
}
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_auto_deref_ref_f32_to_value_param() {
let code = r#"
pub fn scale(v: f32, factor: f32) -> f32 {
v * factor
}
pub fn main() -> f32 {
let x = 1.5
let r = &x
scale(r, 2.0)
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
assert!(
generated.contains("scale(*r") || generated.contains("scale(r"),
"Should auto-deref &f32. Got:\n{}",
generated
);
if !success {
assert!(
err.contains("E0308") || err.contains("expected `f32`"),
"Unexpected rustc error. Error:\n{}",
err
);
}
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_auto_deref_match_binding_to_value_param() {
let code = r#"
pub fn add_one(x: u32) -> u32 {
x + 1
}
pub fn main() -> u32 {
let nums = vec![1u32, 2u32, 3u32]
match nums.get(0) {
Some(v) => add_one(v),
None => 0
}
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
assert!(
generated.contains("add_one(*v)") || generated.contains("add_one(v)"),
"Should auto-deref match binding &u32. Got:\n{}",
generated
);
if !success {
assert!(
err.contains("E0308") || err.contains("expected `u32`"),
"Unexpected rustc error. Error:\n{}",
err
);
}
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_auto_deref_method_receiver_ref_to_owned_self() {
let code = r#"
pub struct Counter {
value: i32,
}
impl Counter {
pub fn get(self) -> i32 {
self.value
}
}
pub fn main() -> i32 {
let c = Counter { value: 42 }
let r = &c
r.get()
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
let ok_pattern = generated.contains("(*r).get()")
|| generated.contains("r.clone().get()")
|| generated.contains("r.get()");
assert!(
ok_pattern,
"Expected get() on ref receiver. Got:\n{}",
generated
);
if !success {
assert!(
err.contains("E0308") || err.contains("E0599"),
"If receiver semantics mismatch, expect rustc. Error:\n{}",
err
);
}
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_auto_deref_binary_op_ref_plus_value() {
let code = r#"
pub fn main() -> i32 {
let x = 5
let r = &x
let y = 3
r + y
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
assert!(
generated.contains("*r + y") || generated.contains("r + y"),
"Should auto-deref in binary op. Got:\n{}",
generated
);
assert!(success, "Must compile. Error:\n{}", err);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_auto_deref_binary_op_ref_times_literal() {
let code = r#"
pub fn main() -> i32 {
let n = 10
let r = &n
r * 2
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
assert!(
generated.contains("*r * 2") || generated.contains("r * 2"),
"Should auto-deref ref in multiplication. Got:\n{}",
generated
);
assert!(success, "Must compile. Error:\n{}", err);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_auto_deref_binary_op_comparison() {
let code = r#"
pub fn main() -> bool {
let x = 42
let r = &x
r == 42
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
assert!(
generated.contains("*r == 42") || generated.contains("r == 42"),
"Should handle ref in comparison. Got:\n{}",
generated
);
assert!(success, "Must compile. Error:\n{}", err);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_mixed_coercion_multiple_args() {
let code = r#"
pub fn compute(items: Vec<i32>, index: usize) -> i32 {
items[index]
}
pub fn main() -> i32 {
let v = vec![1, 2, 3]
let i = 1
let ri = &i
compute(v, ri)
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
assert!(
(generated.contains("compute(&v") || generated.contains("compute(v"))
&& (generated.contains(", *ri)") || generated.contains(", ri)")),
"Should reflect attempt to pass vec and index. Got:\n{}",
generated
);
if !success {
assert!(
err.contains("E0308") || err.contains("expected `usize`"),
"Unexpected rustc error. Error:\n{}",
err
);
}
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_method_ref_self_no_receiver_coercion() {
let code = r#"
pub struct Data { value: i32 }
impl Data {
pub fn get(self) -> i32 {
self.value
}
}
pub fn main() -> i32 {
let d = Data { value: 10 }
d.get()
}
"#;
let (success, _, err) = test_utils::compile_via_cli(code);
assert!(
success,
"d.get() with owned self should compile. Error:\n{}",
err
);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_vec_contains_auto_borrow() {
let code = r#"
pub fn has_item(items: Vec<i32>, search: i32) -> bool {
items.contains(search)
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
assert!(
generated.contains("contains(&search)") || generated.contains("contains(search)"),
"Vec::contains should get correct arg. Got:\n{}",
generated
);
assert!(success, "Must compile. Error:\n{}", err);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_string_literal_no_double_ref() {
let code = r#"
pub fn check(s: string) -> bool {
s.len() > 0
}
pub fn main() -> bool {
check("hello")
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
assert!(
!generated.contains("check(&\"hello\")"),
"String literal is already &str, no extra &. Got:\n{}",
generated
);
assert!(success, "Must compile. Error:\n{}", err);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_custom_struct_auto_borrow() {
let code = r#"
pub struct Config { name: string }
pub fn process(c: Config) -> string {
c.name
}
pub fn main() -> string {
let cfg = Config { name: "test".to_string() }
process(cfg)
}
"#;
let (generated, success) = test_utils::compile_single_check(code);
let err = if !success { &generated } else { "" };
assert!(
generated.contains("process(&cfg)") || generated.contains("process(cfg"),
"Should auto-borrow Config. Got:\n{}",
generated
);
assert!(success, "Must compile. Error:\n{}", err);
}
#[test]
#[cfg_attr(tarpaulin, ignore)]
fn test_option_ref_unwrap() {
let code = r#"
pub fn get_value(opt: Option<i32>) -> i32 {
match opt {
Some(v) => v,
None => 0,
}
}
"#;
let (success, _, err) = test_utils::compile_via_cli(code);
assert!(
success,
"Option::unwrap with &Option should compile. Error:\n{}",
err
);
}