mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 00:01:16 +00:00
Cloning references in a variable may end up cloning the variable itself
This commit is contained in:
parent
9bc6bb3664
commit
480b84bec1
1 changed files with 47 additions and 51 deletions
|
@ -51,7 +51,7 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
let mark = desc.mark;
|
let mark = desc.mark;
|
||||||
|
|
||||||
// Unlike `deep_copy_var` in solve, here we are cloning *all* flex and rigid vars.
|
// Unlike `deep_copy_var` in solve, here we are cloning *all* flex and rigid vars.
|
||||||
// So we only want to fast-return if we've already done the cloning work for a particular
|
// So we only want to short-circuit if we've already done the cloning work for a particular
|
||||||
// var.
|
// var.
|
||||||
if let Some(copy) = desc.copy.into_variable() {
|
if let Some(copy) = desc.copy.into_variable() {
|
||||||
return Some(copy);
|
return Some(copy);
|
||||||
|
@ -86,6 +86,23 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! perform_clone {
|
||||||
|
($needs_clone:ident, $do_clone:expr) => {
|
||||||
|
if $needs_clone {
|
||||||
|
// It may the case that while deep-copying nested variables of this type, we
|
||||||
|
// ended up copying the type itself (notably if it was self-referencing, in a
|
||||||
|
// recursive type). In that case, short-circuit with the known copy.
|
||||||
|
if let Some(copy) = subs.get_ref(var).copy.into_variable() {
|
||||||
|
return Some(copy);
|
||||||
|
}
|
||||||
|
// Perform the clone.
|
||||||
|
Some($do_clone)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Now we recursively copy the content of the variable.
|
// Now we recursively copy the content of the variable.
|
||||||
// We have already marked the variable as copied, so we
|
// We have already marked the variable as copied, so we
|
||||||
// will not repeat this work or crawl this variable again.
|
// will not repeat this work or crawl this variable again.
|
||||||
|
@ -103,12 +120,10 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
let mut needs_clone = false;
|
let mut needs_clone = false;
|
||||||
descend_slice!(arguments, needs_clone);
|
descend_slice!(arguments, needs_clone);
|
||||||
|
|
||||||
if needs_clone {
|
perform_clone!(needs_clone, {
|
||||||
let new_arguments = clone_var_slice!(arguments);
|
let new_arguments = clone_var_slice!(arguments);
|
||||||
Some(Structure(Apply(symbol, new_arguments)))
|
Structure(Apply(symbol, new_arguments))
|
||||||
} else {
|
})
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Func(arguments, closure_var, ret_var) => {
|
Func(arguments, closure_var, ret_var) => {
|
||||||
let mut needs_clone = false;
|
let mut needs_clone = false;
|
||||||
|
@ -118,12 +133,10 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
let new_closure_var = descend_var!(closure_var, needs_clone);
|
let new_closure_var = descend_var!(closure_var, needs_clone);
|
||||||
let new_ret_var = descend_var!(ret_var, needs_clone);
|
let new_ret_var = descend_var!(ret_var, needs_clone);
|
||||||
|
|
||||||
if needs_clone {
|
perform_clone!(needs_clone, {
|
||||||
let new_arguments = clone_var_slice!(arguments);
|
let new_arguments = clone_var_slice!(arguments);
|
||||||
Some(Structure(Func(new_arguments, new_closure_var, new_ret_var)))
|
Structure(Func(new_arguments, new_closure_var, new_ret_var))
|
||||||
} else {
|
})
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Record(fields, ext_var) => {
|
Record(fields, ext_var) => {
|
||||||
let mut needs_clone = false;
|
let mut needs_clone = false;
|
||||||
|
@ -132,7 +145,7 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
|
|
||||||
descend_slice!(fields.variables(), needs_clone);
|
descend_slice!(fields.variables(), needs_clone);
|
||||||
|
|
||||||
if needs_clone {
|
perform_clone!(needs_clone, {
|
||||||
let new_variables = clone_var_slice!(fields.variables());
|
let new_variables = clone_var_slice!(fields.variables());
|
||||||
let new_fields = {
|
let new_fields = {
|
||||||
RecordFields {
|
RecordFields {
|
||||||
|
@ -142,10 +155,9 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
field_types_start: fields.field_types_start,
|
field_types_start: fields.field_types_start,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Some(Structure(Record(new_fields, new_ext_var)))
|
|
||||||
} else {
|
Structure(Record(new_fields, new_ext_var))
|
||||||
None
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
TagUnion(tags, ext_var) => {
|
TagUnion(tags, ext_var) => {
|
||||||
let mut needs_clone = false;
|
let mut needs_clone = false;
|
||||||
|
@ -157,7 +169,7 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
descend_slice!(variables_slice, needs_clone);
|
descend_slice!(variables_slice, needs_clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
if needs_clone {
|
perform_clone!(needs_clone, {
|
||||||
let new_variable_slices =
|
let new_variable_slices =
|
||||||
SubsSlice::reserve_variable_slices(subs, tags.len());
|
SubsSlice::reserve_variable_slices(subs, tags.len());
|
||||||
let it = (new_variable_slices.indices()).zip(tags.variables());
|
let it = (new_variable_slices.indices()).zip(tags.variables());
|
||||||
|
@ -170,10 +182,8 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
let new_union_tags =
|
let new_union_tags =
|
||||||
UnionTags::from_slices(tags.tag_names(), new_variable_slices);
|
UnionTags::from_slices(tags.tag_names(), new_variable_slices);
|
||||||
|
|
||||||
Some(Structure(TagUnion(new_union_tags, new_ext_var)))
|
Structure(TagUnion(new_union_tags, new_ext_var))
|
||||||
} else {
|
})
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
let mut needs_clone = false;
|
let mut needs_clone = false;
|
||||||
|
@ -186,7 +196,7 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
descend_slice!(variables_slice, needs_clone);
|
descend_slice!(variables_slice, needs_clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
if needs_clone {
|
perform_clone!(needs_clone, {
|
||||||
let new_variable_slices =
|
let new_variable_slices =
|
||||||
SubsSlice::reserve_variable_slices(subs, tags.len());
|
SubsSlice::reserve_variable_slices(subs, tags.len());
|
||||||
let it = (new_variable_slices.indices()).zip(tags.variables());
|
let it = (new_variable_slices.indices()).zip(tags.variables());
|
||||||
|
@ -199,23 +209,15 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
let new_union_tags =
|
let new_union_tags =
|
||||||
UnionTags::from_slices(tags.tag_names(), new_variable_slices);
|
UnionTags::from_slices(tags.tag_names(), new_variable_slices);
|
||||||
|
|
||||||
Some(Structure(RecursiveTagUnion(
|
Structure(RecursiveTagUnion(new_rec_var, new_union_tags, new_ext_var))
|
||||||
new_rec_var,
|
})
|
||||||
new_union_tags,
|
|
||||||
new_ext_var,
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
FunctionOrTagUnion(tag_name, symbol, ext_var) => {
|
FunctionOrTagUnion(tag_name, symbol, ext_var) => {
|
||||||
let mut needs_clone = false;
|
let mut needs_clone = false;
|
||||||
let new_ext_var = descend_var!(ext_var, needs_clone);
|
let new_ext_var = descend_var!(ext_var, needs_clone);
|
||||||
if needs_clone {
|
perform_clone!(needs_clone, {
|
||||||
Some(Structure(FunctionOrTagUnion(tag_name, symbol, new_ext_var)))
|
Structure(FunctionOrTagUnion(tag_name, symbol, new_ext_var))
|
||||||
} else {
|
})
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -227,14 +229,12 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
|
|
||||||
let new_structure = descend_var!(structure, needs_clone);
|
let new_structure = descend_var!(structure, needs_clone);
|
||||||
|
|
||||||
if needs_clone {
|
perform_clone!(needs_clone, {
|
||||||
Some(RecursionVar {
|
RecursionVar {
|
||||||
opt_name,
|
opt_name,
|
||||||
structure: new_structure,
|
structure: new_structure,
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Alias(symbol, arguments, real_type_var, kind) => {
|
Alias(symbol, arguments, real_type_var, kind) => {
|
||||||
|
@ -243,17 +243,15 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
let new_real_type_var = descend_var!(real_type_var, needs_clone);
|
let new_real_type_var = descend_var!(real_type_var, needs_clone);
|
||||||
descend_slice!(arguments.all_variables(), needs_clone);
|
descend_slice!(arguments.all_variables(), needs_clone);
|
||||||
|
|
||||||
if needs_clone {
|
perform_clone!(needs_clone, {
|
||||||
let new_variables = clone_var_slice!(arguments.all_variables());
|
let new_variables = clone_var_slice!(arguments.all_variables());
|
||||||
let new_arguments = AliasVariables {
|
let new_arguments = AliasVariables {
|
||||||
variables_start: new_variables.start,
|
variables_start: new_variables.start,
|
||||||
..arguments
|
..arguments
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(Alias(symbol, new_arguments, new_real_type_var, kind))
|
Alias(symbol, new_arguments, new_real_type_var, kind)
|
||||||
} else {
|
})
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RangedNumber(typ, range_vars) => {
|
RangedNumber(typ, range_vars) => {
|
||||||
|
@ -262,13 +260,11 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
let new_typ = descend_var!(typ, needs_clone);
|
let new_typ = descend_var!(typ, needs_clone);
|
||||||
descend_slice!(range_vars, needs_clone);
|
descend_slice!(range_vars, needs_clone);
|
||||||
|
|
||||||
if needs_clone {
|
perform_clone!(needs_clone, {
|
||||||
let new_range_vars = clone_var_slice!(range_vars);
|
let new_range_vars = clone_var_slice!(range_vars);
|
||||||
|
|
||||||
Some(RangedNumber(new_typ, new_range_vars))
|
RangedNumber(new_typ, new_range_vars)
|
||||||
} else {
|
})
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Error => None,
|
Error => None,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue