#![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]
fn test_infer_mut_from_method_call() {
let source = r#"
struct Grid {
data: Vec<i32>,
}
impl Grid {
fn set(self, value: i32) {
self.data.push(value)
}
}
fn fill_grid(grid: Grid) {
grid.set(42)
}
"#;
let rust_code = match test_utils::compile_single_result(source) {
Ok(code) => code,
Err(e) => panic!("Compilation failed: {}", e),
};
assert!(
rust_code.contains("fn fill_grid(grid: &mut Grid)"),
"Should automatically infer &mut for mutated parameter.\n\nGenerated:\n{}",
rust_code
);
}
#[test]
fn test_infer_mut_self_from_field_method_call() {
let source = r#"
struct Camera {
x: f32,
}
impl Camera {
fn move_to(self, x: f32) {
self.x = x
}
}
struct Game {
camera: Camera,
}
impl Game {
fn update_camera(self) {
self.camera.move_to(10.0)
}
}
"#;
let rust_code = match test_utils::compile_single_result(source) {
Ok(code) => code,
Err(e) => panic!("Compilation failed: {}", e),
};
assert!(
rust_code.contains("fn update_camera(&mut self)"),
"Should infer &mut self when calling mutating method on field.\n\nGenerated:\n{}",
rust_code
);
}
#[test]
fn test_infer_mut_self_from_field_extern_method() {
let source = r#"
extern fn camera_smooth_follow(mut camera: Camera, x: f32, y: f32, z: f32, speed: f32)
struct Camera {
x: f32,
}
impl Camera {
fn smooth_follow(self, x: f32, y: f32, z: f32, speed: f32) {
camera_smooth_follow(self, x, y, z, speed)
}
}
struct Game {
camera: Camera,
}
impl Game {
fn update(self) {
self.camera.smooth_follow(10.0, 5.0, -10.0, 0.1)
}
}
"#;
let rust_code = match test_utils::compile_single_result(source) {
Ok(code) => code,
Err(e) => panic!("Compilation failed: {}", e),
};
assert!(
rust_code.contains("fn update(&mut self)")
|| rust_code.contains("fn update(&self)")
|| rust_code.contains("fn update(self)"),
"Should infer appropriate self ownership.\n\nGenerated:\n{}",
rust_code
);
}
#[test]
fn test_usize_index_not_inferred_as_mut() {
let source = r#"
struct Skill {
unlocked: bool,
points_required: u32,
}
impl Skill {
fn can_unlock(self, points: u32) -> bool {
!self.unlocked && points >= self.points_required
}
fn unlock(self) {
self.unlocked = true
}
}
struct SkillTree {
skills: Vec<Skill>,
total_points: u32,
}
impl SkillTree {
fn unlock_skill(self, index: usize, points: u32) -> bool {
if index >= self.skills.len() {
return false
}
if !self.skills[index].can_unlock(points) {
return false
}
self.skills[index].unlock()
self.total_points = self.total_points + self.skills[index].points_required
true
}
}
"#;
let rust_code = match test_utils::compile_single_result(source) {
Ok(code) => code,
Err(e) => panic!("Compilation failed: {}", e),
};
assert!(
rust_code.contains("index: usize"),
"Should NOT infer &mut for usize parameters used as indices.\n\nGenerated:\n{}",
rust_code
);
assert!(
!rust_code.contains("index: &mut usize"),
"Should NOT generate &mut usize for index parameter.\n\nGenerated:\n{}",
rust_code
);
}
#[test]
fn test_infer_mut_nested_field_method_call() {
let source = r#"
struct Inner {
value: i32,
}
impl Inner {
fn set(self, v: i32) {
self.value = v
}
}
struct Outer {
inner: Inner,
}
fn modify_nested(outer: Outer) {
outer.inner.set(42)
}
"#;
let rust_code = match test_utils::compile_single_result(source) {
Ok(code) => code,
Err(e) => panic!("Compilation failed: {}", e),
};
assert!(
rust_code.contains("fn modify_nested") && rust_code.contains("outer: &mut Outer"),
"Should infer &mut when mutating nested field via method call.\n\nGenerated:\n{}",
rust_code
);
}