manually track visited varibles in deep_copy_var_to

This commit is contained in:
Folkert 2021-11-20 01:39:57 +01:00
parent 2bccc2d28d
commit 594e754e1e
2 changed files with 53 additions and 23 deletions

View file

@ -1373,7 +1373,7 @@ fn instantiate_rigids_help(subs: &mut Subs, max_rank: Rank, initial: Variable) {
} }
// we have tracked all visited variables, and can now traverse them // we have tracked all visited variables, and can now traverse them
// in one go (without looking at the UnificationTable) and clear copy field // in one go (without looking at the UnificationTable) and clear the copy field
for var in visited { for var in visited {
let descriptor = subs.get_ref_mut(var); let descriptor = subs.get_ref_mut(var);

View file

@ -3042,15 +3042,28 @@ pub fn deep_copy_var_to(
// capacity based on the false hello world program // capacity based on the false hello world program
let arena = bumpalo::Bump::with_capacity(4 * 1024); let arena = bumpalo::Bump::with_capacity(4 * 1024);
let copy = deep_copy_var_to_help(&arena, source, target, rank, var); let mut visited = bumpalo::collections::Vec::with_capacity_in(256, &arena);
source.restore(var); let copy = deep_copy_var_to_help(&arena, &mut visited, source, target, rank, var);
// we have tracked all visited variables, and can now traverse them
// in one go (without looking at the UnificationTable) and clear the copy field
for var in visited {
let descriptor = source.get_ref_mut(var);
if descriptor.copy.is_some() {
descriptor.rank = Rank::NONE;
descriptor.mark = Mark::NONE;
descriptor.copy = OptVariable::NONE;
}
}
copy copy
} }
fn deep_copy_var_to_help<'a>( fn deep_copy_var_to_help<'a>(
arena: &'a bumpalo::Bump, arena: &'a bumpalo::Bump,
visited: &mut bumpalo::collections::Vec<'a, Variable>,
source: &mut Subs, source: &mut Subs,
target: &mut Subs, target: &mut Subs,
max_rank: Rank, max_rank: Rank,
@ -3066,7 +3079,7 @@ fn deep_copy_var_to_help<'a>(
debug_assert!(target.contains(copy)); debug_assert!(target.contains(copy));
return copy; return copy;
} else if desc.rank != Rank::NONE { } else if desc.rank != Rank::NONE {
// DO NOTHING // DO NOTHING, Fall through
// //
// The original deep_copy_var can do // The original deep_copy_var can do
// return var; // return var;
@ -3075,6 +3088,8 @@ fn deep_copy_var_to_help<'a>(
// should only return variables in the target // should only return variables in the target
} }
visited.push(var);
let make_descriptor = |content| Descriptor { let make_descriptor = |content| Descriptor {
content, content,
rank: max_rank, rank: max_rank,
@ -3104,7 +3119,9 @@ fn deep_copy_var_to_help<'a>(
for index in args.into_iter() { for index in args.into_iter() {
let var = source[index]; let var = source[index];
new_args.push(deep_copy_var_to_help(arena, source, target, max_rank, var)); new_args.push(deep_copy_var_to_help(
arena, visited, source, target, max_rank, var,
));
} }
let arg_vars = VariableSubsSlice::insert_into_subs(target, new_args); let arg_vars = VariableSubsSlice::insert_into_subs(target, new_args);
@ -3114,16 +3131,23 @@ fn deep_copy_var_to_help<'a>(
Func(arg_vars, closure_var, ret_var) => { Func(arg_vars, closure_var, ret_var) => {
let new_ret_var = let new_ret_var =
deep_copy_var_to_help(arena, source, target, max_rank, ret_var); deep_copy_var_to_help(arena, visited, source, target, max_rank, ret_var);
let new_closure_var = let new_closure_var = deep_copy_var_to_help(
deep_copy_var_to_help(arena, source, target, max_rank, closure_var); arena,
visited,
source,
target,
max_rank,
closure_var,
);
let mut new_arg_vars = Vec::with_capacity_in(arg_vars.len(), arena); let mut new_arg_vars = Vec::with_capacity_in(arg_vars.len(), arena);
for index in arg_vars.into_iter() { for index in arg_vars.into_iter() {
let var = source[index]; let var = source[index];
let copy_var = deep_copy_var_to_help(arena, source, target, max_rank, var); let copy_var =
deep_copy_var_to_help(arena, visited, source, target, max_rank, var);
new_arg_vars.push(copy_var); new_arg_vars.push(copy_var);
} }
@ -3140,8 +3164,9 @@ fn deep_copy_var_to_help<'a>(
for index in fields.iter_variables() { for index in fields.iter_variables() {
let var = source[index]; let var = source[index];
let copy_var = let copy_var = deep_copy_var_to_help(
deep_copy_var_to_help(arena, source, target, max_rank, var); arena, visited, source, target, max_rank, var,
);
new_vars.push(copy_var); new_vars.push(copy_var);
} }
@ -3172,12 +3197,13 @@ fn deep_copy_var_to_help<'a>(
Record( Record(
record_fields, record_fields,
deep_copy_var_to_help(arena, source, target, max_rank, ext_var), deep_copy_var_to_help(arena, visited, source, target, max_rank, ext_var),
) )
} }
TagUnion(tags, ext_var) => { TagUnion(tags, ext_var) => {
let new_ext = deep_copy_var_to_help(arena, source, target, max_rank, ext_var); let new_ext =
deep_copy_var_to_help(arena, visited, source, target, max_rank, ext_var);
let mut new_variable_slices = Vec::with_capacity_in(tags.len(), arena); let mut new_variable_slices = Vec::with_capacity_in(tags.len(), arena);
@ -3186,8 +3212,9 @@ fn deep_copy_var_to_help<'a>(
let slice = source[index]; let slice = source[index];
for var_index in slice { for var_index in slice {
let var = source[var_index]; let var = source[var_index];
let new_var = let new_var = deep_copy_var_to_help(
deep_copy_var_to_help(arena, source, target, max_rank, var); arena, visited, source, target, max_rank, var,
);
new_variables.push(new_var); new_variables.push(new_var);
} }
@ -3231,7 +3258,7 @@ fn deep_copy_var_to_help<'a>(
FunctionOrTagUnion( FunctionOrTagUnion(
new_tag_name, new_tag_name,
symbol, symbol,
deep_copy_var_to_help(arena, source, target, max_rank, ext_var), deep_copy_var_to_help(arena, visited, source, target, max_rank, ext_var),
) )
} }
@ -3243,8 +3270,9 @@ fn deep_copy_var_to_help<'a>(
let slice = source[index]; let slice = source[index];
for var_index in slice { for var_index in slice {
let var = source[var_index]; let var = source[var_index];
let new_var = let new_var = deep_copy_var_to_help(
deep_copy_var_to_help(arena, source, target, max_rank, var); arena, visited, source, target, max_rank, var,
);
new_variables.push(new_var); new_variables.push(new_var);
} }
@ -3277,9 +3305,10 @@ fn deep_copy_var_to_help<'a>(
let union_tags = UnionTags::from_slices(new_tag_names, new_variables); let union_tags = UnionTags::from_slices(new_tag_names, new_variables);
let new_ext = deep_copy_var_to_help(arena, source, target, max_rank, ext_var); let new_ext =
deep_copy_var_to_help(arena, visited, source, target, max_rank, ext_var);
let new_rec_var = let new_rec_var =
deep_copy_var_to_help(arena, source, target, max_rank, rec_var); deep_copy_var_to_help(arena, visited, source, target, max_rank, rec_var);
RecursiveTagUnion(new_rec_var, union_tags, new_ext) RecursiveTagUnion(new_rec_var, union_tags, new_ext)
} }
@ -3296,7 +3325,8 @@ fn deep_copy_var_to_help<'a>(
opt_name, opt_name,
structure, structure,
} => { } => {
let new_structure = deep_copy_var_to_help(arena, source, target, max_rank, structure); let new_structure =
deep_copy_var_to_help(arena, visited, source, target, max_rank, structure);
debug_assert!((new_structure.index() as usize) < target.len()); debug_assert!((new_structure.index() as usize) < target.len());
@ -3322,7 +3352,7 @@ fn deep_copy_var_to_help<'a>(
for var_index in args.variables() { for var_index in args.variables() {
let var = source[var_index]; let var = source[var_index];
let new_var = deep_copy_var_to_help(arena, source, target, max_rank, var); let new_var = deep_copy_var_to_help(arena, visited, source, target, max_rank, var);
new_vars.push(new_var); new_vars.push(new_var);
} }
@ -3336,7 +3366,7 @@ fn deep_copy_var_to_help<'a>(
target.field_names.extend(lowercases.iter().cloned()); target.field_names.extend(lowercases.iter().cloned());
let new_real_type_var = let new_real_type_var =
deep_copy_var_to_help(arena, source, target, max_rank, real_type_var); deep_copy_var_to_help(arena, visited, source, target, max_rank, real_type_var);
let new_content = Alias(symbol, args, new_real_type_var); let new_content = Alias(symbol, args, new_real_type_var);
target.set(copy, make_descriptor(new_content)); target.set(copy, make_descriptor(new_content));