Make var_contains_content a loop

This commit is contained in:
ayazhafiz 2022-01-20 18:09:04 -05:00
parent 53be0e2674
commit b281ea8c2c

View file

@ -3483,77 +3483,69 @@ fn var_contains_content_help<P>(
where where
P: Fn(&Content) -> bool + Copy, P: Fn(&Content) -> bool + Copy,
{ {
if seen_recursion_vars.contains(&var) { let mut stack = vec![var];
return false;
}
let content = subs.get_content_without_compacting(var); macro_rules! push_var_slice {
if predicate(content) {
return true;
}
macro_rules! check_var {
($v:expr) => {
var_contains_content_help(subs, $v, predicate, seen_recursion_vars)
};
}
macro_rules! check_var_slice {
($slice:expr) => { ($slice:expr) => {
subs.get_subs_slice($slice) stack.extend(subs.get_subs_slice($slice))
.into_iter()
.any(|v| check_var!(*v))
}; };
} }
use Content::*; while let Some(var) = stack.pop() {
use FlatType::*; if seen_recursion_vars.contains(&var) {
match content { continue;
FlexVar(_) => false,
RigidVar(_) => false,
RecursionVar {
structure,
opt_name: _,
} => {
seen_recursion_vars.insert(var);
var_contains_content_help(subs, *structure, predicate, seen_recursion_vars)
} }
Structure(flat_type) => match flat_type {
Apply(_, vars) => check_var_slice!(*vars), let content = subs.get_content_without_compacting(var);
Func(args, clos, ret) => {
check_var_slice!(*args) || check_var!(*clos) || check_var!(*ret) if predicate(content) {
} return true;
Record(fields, var) => check_var_slice!(fields.variables()) || check_var!(*var), }
TagUnion(tags, ext_var) => {
for i in tags.variables() { use Content::*;
if check_var_slice!(subs[i]) { use FlatType::*;
return true; match content {
} FlexVar(_) | RigidVar(_) => {}
} RecursionVar {
if check_var!(*ext_var) { structure,
return true; opt_name: _,
} } => {
false seen_recursion_vars.insert(var);
} stack.push(*structure);
FunctionOrTagUnion(_, _, var) => check_var!(*var), }
RecursiveTagUnion(rec_var, tags, ext_var) => { Structure(flat_type) => match flat_type {
seen_recursion_vars.insert(*rec_var); Apply(_, vars) => push_var_slice!(*vars),
for i in tags.variables() { Func(args, clos, ret) => {
if check_var_slice!(subs[i]) { push_var_slice!(*args);
return true; stack.push(*clos);
} stack.push(*ret);
} }
if check_var!(*ext_var) { Record(fields, var) => {
return true; push_var_slice!(fields.variables());
} stack.push(*var);
false }
} TagUnion(tags, ext_var) => {
Erroneous(_) | EmptyRecord | EmptyTagUnion => false, for i in tags.variables() {
}, push_var_slice!(subs[i]);
Alias(_, arguments, real_type_var) => { }
check_var_slice!(arguments.variables()) || check_var!(*real_type_var) stack.push(*ext_var);
}
FunctionOrTagUnion(_, _, var) => stack.push(*var),
RecursiveTagUnion(rec_var, tags, ext_var) => {
seen_recursion_vars.insert(*rec_var);
for i in tags.variables() {
push_var_slice!(subs[i]);
}
stack.push(*ext_var);
}
Erroneous(_) | EmptyRecord | EmptyTagUnion => {}
},
Alias(_, arguments, real_type_var) => {
push_var_slice!(arguments.variables());
stack.push(*real_type_var);
}
Error => {}
} }
Error => false,
} }
false
} }