1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#![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",
))]
//! Rust Semantics Verification: str vs String vs &str
//!
//! These tests verify Rust's ACTUAL behavior to ensure Windjammer's str/String
//! codegen matches Rust semantics. Each test compiles and runs valid Rust.
//!
//! Rust's Rules (verified below):
//! 1. fn foo(s: &str) - borrowed param ✅
//! 2. struct { name: String } - owned field ✅
//! 3. "hello" - type is &str ✅
//! 4. Option<String> not Option<&str> in containers (no lifetimes) ✅
//! 5. fn -> str INVALID (str unsized) ✅
//! 6. fn -> &str valid for literals/borrowed ✅
//! 7. fn -> String valid for owned ✅
//! 8. HashMap<String, String> - owned in containers ✅
//! 9. &str reference - don't double-ref to &&str ✅
//! 10. Box<str> - valid (Box can hold unsized) ✅
#[test]
fn rust_param_borrowed_str_works() {
// Rule 1: fn foo(s: &str) - borrowed param
fn greet(s: &str) -> String {
format!("Hello, {}!", s)
}
assert_eq!(greet("world"), "Hello, world!");
assert_eq!(greet(&String::from("Rust")), "Hello, Rust!");
}
#[test]
fn rust_struct_field_owned_string_works() {
// Rule 2: struct { name: String } - owned field
struct Person {
name: String,
}
let p = Person {
name: String::from("Alice"),
};
assert_eq!(p.name, "Alice");
}
#[test]
fn rust_string_literal_is_str() {
// Rule 3: "hello" - type is &str
let s: &str = "hello";
assert_eq!(s, "hello");
fn take_str(s: &str) -> &str {
s
}
assert_eq!(take_str("literal"), "literal");
}
#[test]
fn rust_option_string_not_option_str() {
// Rule 4: Option<String> - not Option<&str> (lifetimes in containers are complex)
let opt: Option<String> = Some(String::from("value"));
assert_eq!(opt.as_deref(), Some("value"));
// Option<&str> requires lifetime - can't store in struct without lifetime param
#[allow(dead_code)]
struct WithOptionalRef<'a> {
name: Option<&'a str>,
}
let _ = WithOptionalRef { name: Some("ok") };
}
#[test]
fn rust_cannot_return_str_directly() {
// Rule 5: fn -> str INVALID - str is unsized
// This test documents the compile error we'd get:
// fn bad() -> str { "hello" } // ERROR: the size for values of type `str` cannot be known at compilation time
// We verify the valid alternatives work:
}
#[test]
fn rust_return_str_valid_for_literal() {
// Rule 6: fn -> &str valid when returning literal
fn get_static() -> &'static str {
"static"
}
assert_eq!(get_static(), "static");
}
#[test]
fn rust_return_str_valid_for_borrowed_input() {
// Rule 6b: fn -> &str valid when returning slice of input
fn first_word(s: &str) -> &str {
s.split_whitespace().next().unwrap_or("")
}
assert_eq!(first_word("hello world"), "hello");
}
#[test]
fn rust_return_string_for_owned() {
// Rule 7: fn -> String for owned/new strings
fn create_greeting(name: &str) -> String {
format!("Hello, {}!", name)
}
let s = create_greeting("world");
assert_eq!(s, "Hello, world!");
}
#[test]
fn rust_hashmap_string_string_owned() {
// Rule 8: HashMap<String, String> - owned in containers
use std::collections::HashMap;
let mut map: HashMap<String, String> = HashMap::new();
map.insert(String::from("key"), String::from("value"));
assert_eq!(map.get("key").map(String::as_str), Some("value"));
}
#[test]
fn rust_ref_str_no_double_ref() {
// Rule 9: &str stays &str, not &&str
fn take_ref(s: &str) -> &str {
s
}
let s = "hello";
let r: &str = s;
assert_eq!(take_ref(r), "hello");
// &(&str) would be &&str - different type, not what we want for params
}
#[test]
fn rust_box_str_valid() {
// Rule 10: Box<str> - valid (Box can hold unsized types)
let boxed: Box<str> = "hello".into();
assert_eq!(&*boxed, "hello");
}
#[test]
fn rust_result_string_works() {
// Result<T, String> - owned error type
fn parse_int(s: &str) -> Result<i32, String> {
s.parse().map_err(|e| format!("{}", e))
}
assert_eq!(parse_int("42"), Ok(42));
assert!(parse_int("x").is_err());
}
#[test]
fn rust_vec_string_works() {
// Vec<String> - owned
let v: Vec<String> = vec!["a".into(), "b".into()];
assert_eq!(v, vec!["a", "b"]);
}