use fieldwork_borrow::with_;
struct SigStore {
struct_defs: Vec<StructDef>,
}
struct DiagnosticStore {
errors: Vec<String>,
}
struct ItemStore;
struct Stores<'a, 'b, 'c> {
pub items: &'c mut ItemStore,
pub sigs: &'a mut SigStore,
pub diags: &'b mut DiagnosticStore,
}
struct StructDef {
fields: Vec<StructDefField>,
}
struct StructDefField {
kind: NameResolvedType,
}
enum NameResolvedType {
SimpleCustom { id: usize },
Array(Box<NameResolvedType>, usize),
Other,
}
fn some_f(sigs: &SigStore, idx: usize) -> &StructDef {
&sigs.struct_defs[idx]
}
fn some_f4(field: &StructDefField) -> &NameResolvedType {
&field.kind
}
fn some_code2(_items: &ItemStore, id: usize, diags: &mut DiagnosticStore) {
diags.errors.push(format!("checked id: {}", id));
}
fn problem_non_recursive(stores: &mut Stores) {
with_!(stores, {
methods {
check_field(items, mut diags, field_kind: &NameResolvedType) {
match field_kind {
NameResolvedType::SimpleCustom { id, .. } => {
some_code2(items, *id, diags);
}
_ => {}
}
}
}
fields { sigs }
body {
let struct_def = some_f(sigs, 0);
for field in &struct_def.fields {
stores.check_field(some_f4(field));
}
}
});
}
fn check_recursive(items: &ItemStore, diags: &mut DiagnosticStore, field_kind: &NameResolvedType) {
match field_kind {
NameResolvedType::SimpleCustom { id, .. } => {
some_code2(items, *id, diags);
}
NameResolvedType::Array(inner, _) => {
let mut current = inner;
while let NameResolvedType::Array(next, _) = &**current {
current = next;
}
check_recursive(items, diags, current);
}
_ => {}
}
}
fn problem_recursive(stores: &mut Stores) {
with_!(stores, {
fields {
sigs
items
mut diags
}
body {
let struct_def = some_f(sigs, 0);
for field in &struct_def.fields {
check_recursive(items, diags, some_f4(field));
}
}
});
}
#[test]
fn test_e4_non_recursive() {
let mut sigs = SigStore {
struct_defs: vec![StructDef {
fields: vec![
StructDefField { kind: NameResolvedType::SimpleCustom { id: 1 } },
StructDefField { kind: NameResolvedType::SimpleCustom { id: 2 } },
],
}],
};
let mut diags = DiagnosticStore { errors: vec![] };
let mut items = ItemStore;
let mut stores = Stores {
items: &mut items,
sigs: &mut sigs,
diags: &mut diags,
};
problem_non_recursive(&mut stores);
assert_eq!(stores.diags.errors, vec!["checked id: 1", "checked id: 2"]);
}
#[test]
fn test_e4_recursive() {
let mut sigs = SigStore {
struct_defs: vec![StructDef {
fields: vec![
StructDefField { kind: NameResolvedType::SimpleCustom { id: 1 } },
StructDefField {
kind: NameResolvedType::Array(
Box::new(NameResolvedType::Array(
Box::new(NameResolvedType::SimpleCustom { id: 99 }),
10,
)),
5,
),
},
],
}],
};
let mut diags = DiagnosticStore { errors: vec![] };
let mut items = ItemStore;
let mut stores = Stores {
items: &mut items,
sigs: &mut sigs,
diags: &mut diags,
};
problem_recursive(&mut stores);
assert_eq!(stores.diags.errors, vec!["checked id: 1", "checked id: 99"]);
}