#![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;
use std::process::Command;
fn rust_compiles(rust_code: &str) -> bool {
let temp_dir = tempfile::tempdir().expect("temp dir");
let rs_path = temp_dir.path().join("test.rs");
std::fs::write(&rs_path, rust_code).expect("write");
let output = Command::new("rustc")
.args(["--crate-type=lib", "--emit=metadata", "--edition", "2021"])
.arg("-o")
.arg(temp_dir.path().join("verify.rmeta"))
.arg(&rs_path)
.output()
.expect("rustc");
output.status.success()
}
#[test]
fn test_vec_index_triangle_clone() {
let source = r#"
pub struct Triangle { pub a: i32 }
pub fn get_first(triangles: Vec<Triangle>) -> Triangle {
triangles[0]
}
fn main() {}
"#;
let rust = test_utils::compile_single_result(source).expect("compile");
assert!(
rust.contains(".clone()") || rust.contains("triangles[0]"),
"Vec index in return needs clone or Copy: {}",
rust
);
assert!(rust_compiles(&rust), "Generated Rust must compile");
}
#[test]
fn test_vec_index_let_binding_clone() {
let source = r#"
pub struct Triangle { pub a: i32 }
pub fn process(tris: Vec<Triangle>, i: i32) -> i32 {
let t = tris[i as usize]
t.a
}
fn main() {}
"#;
let rust = test_utils::compile_single_result(source).expect("compile");
assert!(
rust.contains(".clone()") || rust.contains("&tris[") || rust.contains("tris["),
"Vec index in let binding: {}",
rust
);
assert!(rust_compiles(&rust), "Generated Rust must compile");
}
#[test]
fn test_shared_ref_deref_clone() {
let source = r#"
pub struct Quest { pub name: string }
pub fn get_quest(q: Quest) -> Quest {
q
}
fn main() {}
"#;
let rust = test_utils::compile_single_result(source).expect("compile");
assert!(rust_compiles(&rust), "Generated Rust must compile");
}
#[test]
fn test_enum_variant_behind_field() {
let source = r#"
pub enum Cost { Gold(i32) }
pub struct Item { pub cost: Cost }
impl Item {
pub fn get_amount(self) -> i32 {
match self.cost {
Cost::Gold(amount) => amount
}
}
}
fn main() {
let item = Item { cost: Cost::Gold(42) }
let _ = item.get_amount()
}
"#;
let rust = test_utils::compile_single_result(source).expect("compile");
let has_bare = rust.contains("match self.cost");
let has_ref = rust.contains("&self.cost") || rust.contains("match &");
let has_clone = rust.contains("self.cost.clone()");
assert!(
has_bare || has_ref || has_clone,
"Enum variant behind borrowed field needs valid scrutinee strategy: {}",
rust
);
assert!(
!rust.contains("*self.cost"),
"Copy field should not be dereferenced: {}",
rust
);
assert!(
rust_compiles(&rust),
"Generated Rust must compile: {}",
rust
);
}
#[test]
fn test_for_loop_nested_field() {
let source = r#"
pub struct PixelColor { pub r: u8 }
pub struct Screenshot { pub pixels: Vec<PixelColor> }
impl Screenshot {
pub fn count_pixels(self) -> i32 {
let mut count = 0
for p in self.pixels {
count = count + 1
}
count
}
}
fn main() {}
"#;
let rust = test_utils::compile_single_result(source).expect("compile");
assert!(
rust.contains("&self.pixels") || rust.contains("for p in &"),
"For loop over borrowed field needs &: {}",
rust
);
assert!(rust_compiles(&rust), "Generated Rust must compile");
}
#[test]
fn test_for_loop_deeply_nested_field() {
let source = r#"
pub struct PixelColor { pub r: u8 }
pub struct Screenshot { pub pixels: Vec<PixelColor> }
pub struct App { pub screenshot: Screenshot }
impl App {
pub fn process(self) -> i32 {
let mut count = 0
for p in self.screenshot.pixels {
count = count + 1
}
count
}
}
fn main() {}
"#;
let rust = test_utils::compile_single_result(source).expect("compile");
assert!(
rust.contains("&self.screenshot.pixels") || rust.contains("for p in &"),
"For loop over nested borrowed field: {}",
rust
);
assert!(rust_compiles(&rust), "Generated Rust must compile");
}