mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 22:34:45 +00:00
use UnionTags for recursive tag unions
This commit is contained in:
parent
e86cc22024
commit
3bbf1a5506
7 changed files with 183 additions and 90 deletions
|
@ -1299,8 +1299,22 @@ fn layout_from_flat_type<'a>(
|
||||||
let rec_var = subs.get_root_key_without_compacting(rec_var);
|
let rec_var = subs.get_root_key_without_compacting(rec_var);
|
||||||
let mut tag_layouts = Vec::with_capacity_in(tags.len(), arena);
|
let mut tag_layouts = Vec::with_capacity_in(tags.len(), arena);
|
||||||
|
|
||||||
|
let mut new_tags = MutMap::default();
|
||||||
|
|
||||||
|
for (tag_index, index) in tags.iter_all() {
|
||||||
|
let tag = subs[tag_index].clone();
|
||||||
|
let slice = subs[index];
|
||||||
|
let mut new_vars = std::vec::Vec::new();
|
||||||
|
for var_index in slice {
|
||||||
|
let var = subs[var_index];
|
||||||
|
new_vars.push(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_tags.insert(tag, new_vars);
|
||||||
|
}
|
||||||
|
|
||||||
// VERY IMPORTANT: sort the tags
|
// VERY IMPORTANT: sort the tags
|
||||||
let mut tags_vec: std::vec::Vec<_> = tags.into_iter().collect();
|
let mut tags_vec: std::vec::Vec<_> = new_tags.into_iter().collect();
|
||||||
tags_vec.sort();
|
tags_vec.sort();
|
||||||
|
|
||||||
let mut nullable = None;
|
let mut nullable = None;
|
||||||
|
|
|
@ -780,8 +780,12 @@ fn type_to_variable(
|
||||||
};
|
};
|
||||||
tag_vars.extend(ext_tag_vec.into_iter());
|
tag_vars.extend(ext_tag_vec.into_iter());
|
||||||
|
|
||||||
let content =
|
let content = Content::Structure(roc_unify::unify::from_mutmap_rec(
|
||||||
Content::Structure(FlatType::RecursiveTagUnion(*rec_var, tag_vars, new_ext_var));
|
subs,
|
||||||
|
*rec_var,
|
||||||
|
tag_vars,
|
||||||
|
new_ext_var,
|
||||||
|
));
|
||||||
|
|
||||||
let tag_union_var = register(subs, rank, pools, content);
|
let tag_union_var = register(subs, rank, pools, content);
|
||||||
|
|
||||||
|
@ -896,7 +900,8 @@ fn check_for_infinite_type(
|
||||||
|
|
||||||
let new_ext_var = subs.explicit_substitute(recursive, rec_var, ext_var);
|
let new_ext_var = subs.explicit_substitute(recursive, rec_var, ext_var);
|
||||||
|
|
||||||
let flat_type = FlatType::RecursiveTagUnion(rec_var, new_tags, new_ext_var);
|
let flat_type =
|
||||||
|
roc_unify::unify::from_mutmap_rec(subs, rec_var, new_tags, new_ext_var);
|
||||||
|
|
||||||
subs.set_content(recursive, Content::Structure(flat_type));
|
subs.set_content(recursive, Content::Structure(flat_type));
|
||||||
}
|
}
|
||||||
|
@ -1124,9 +1129,13 @@ fn adjust_rank_content(
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *ext_var);
|
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *ext_var);
|
||||||
|
|
||||||
for var in tags.values().flatten() {
|
for (_, index) in tags.iter_all() {
|
||||||
rank =
|
let slice = subs[index];
|
||||||
rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var));
|
for var_index in slice {
|
||||||
|
let var = subs[var_index];
|
||||||
|
rank = rank
|
||||||
|
.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// THEORY: the recursion var has the same rank as the tag union itself
|
// THEORY: the recursion var has the same rank as the tag union itself
|
||||||
|
@ -1275,8 +1284,10 @@ fn instantiate_rigids_help(
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
instantiate_rigids_help(subs, max_rank, pools, rec_var);
|
instantiate_rigids_help(subs, max_rank, pools, rec_var);
|
||||||
|
|
||||||
for (_, vars) in tags {
|
for (_, index) in tags.iter_all() {
|
||||||
for var in vars.into_iter() {
|
let slice = subs[index];
|
||||||
|
for var_index in slice {
|
||||||
|
let var = subs[var_index];
|
||||||
instantiate_rigids_help(subs, max_rank, pools, var);
|
instantiate_rigids_help(subs, max_rank, pools, var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1466,19 +1477,21 @@ fn deep_copy_var_help(
|
||||||
|
|
||||||
let new_rec_var = deep_copy_var_help(subs, max_rank, pools, rec_var);
|
let new_rec_var = deep_copy_var_help(subs, max_rank, pools, rec_var);
|
||||||
|
|
||||||
for (tag, vars) in tags {
|
for (tag_index, index) in tags.iter_all() {
|
||||||
let new_vars: Vec<Variable> = vars
|
let tag = subs[tag_index].clone();
|
||||||
.into_iter()
|
let slice = subs[index];
|
||||||
.map(|var| deep_copy_var_help(subs, max_rank, pools, var))
|
let mut new_vars = Vec::new();
|
||||||
.collect();
|
for var_index in slice {
|
||||||
|
let var = subs[var_index];
|
||||||
|
let new_var = deep_copy_var_help(subs, max_rank, pools, var);
|
||||||
|
new_vars.push(new_var);
|
||||||
|
}
|
||||||
|
|
||||||
new_tags.insert(tag, new_vars);
|
new_tags.insert(tag, new_vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecursiveTagUnion(
|
let new_ext = deep_copy_var_help(subs, max_rank, pools, ext_var);
|
||||||
new_rec_var,
|
roc_unify::unify::from_mutmap_rec(subs, new_rec_var, new_tags, new_ext)
|
||||||
new_tags,
|
|
||||||
deep_copy_var_help(subs, max_rank, pools, ext_var),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,8 @@ fn find_names_needed(
|
||||||
|
|
||||||
match content {
|
match content {
|
||||||
Content::Structure(FlatType::TagUnion(tags, ext_var)) => {
|
Content::Structure(FlatType::TagUnion(tags, ext_var)) => {
|
||||||
|
let ext_var = *ext_var;
|
||||||
|
|
||||||
let mut new_tags = MutMap::default();
|
let mut new_tags = MutMap::default();
|
||||||
|
|
||||||
for (name_index, slice_index) in tags.iter_all() {
|
for (name_index, slice_index) in tags.iter_all() {
|
||||||
|
@ -96,7 +98,12 @@ fn find_names_needed(
|
||||||
new_tags.insert(subs[name_index].clone(), new_vars);
|
new_tags.insert(subs[name_index].clone(), new_vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
let flat_type = FlatType::RecursiveTagUnion(rec_var, new_tags, *ext_var);
|
let mut x: Vec<_> = new_tags.into_iter().collect();
|
||||||
|
x.sort();
|
||||||
|
|
||||||
|
let union_tags = UnionTags::insert_into_subs(subs, x);
|
||||||
|
|
||||||
|
let flat_type = FlatType::RecursiveTagUnion(rec_var, union_tags, ext_var);
|
||||||
subs.set_content(recursive, Content::Structure(flat_type));
|
subs.set_content(recursive, Content::Structure(flat_type));
|
||||||
}
|
}
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
|
@ -178,11 +185,12 @@ fn find_names_needed(
|
||||||
find_names_needed(*ext_var, subs, roots, root_appearances, names_taken);
|
find_names_needed(*ext_var, subs, roots, root_appearances, names_taken);
|
||||||
}
|
}
|
||||||
Structure(RecursiveTagUnion(rec_var, tags, ext_var)) => {
|
Structure(RecursiveTagUnion(rec_var, tags, ext_var)) => {
|
||||||
let mut sorted_tags: Vec<_> = tags.iter().collect();
|
for slice_index in tags.variables {
|
||||||
sorted_tags.sort();
|
let slice = subs[slice_index];
|
||||||
|
for var_index in slice {
|
||||||
for var in sorted_tags.into_iter().map(|(_, v)| v).flatten() {
|
let var = subs[var_index];
|
||||||
find_names_needed(*var, subs, roots, root_appearances, names_taken);
|
find_names_needed(var, subs, roots, root_appearances, names_taken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
find_names_needed(*ext_var, subs, roots, root_appearances, names_taken);
|
find_names_needed(*ext_var, subs, roots, root_appearances, names_taken);
|
||||||
|
@ -587,7 +595,7 @@ fn write_flat_type(env: &Env, flat_type: &FlatType, subs: &Subs, buf: &mut Strin
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
buf.push_str("[ ");
|
buf.push_str("[ ");
|
||||||
|
|
||||||
let ext_content = write_sorted_tags(env, subs, buf, tags, *ext_var);
|
let ext_content = write_sorted_tags2(env, subs, buf, tags, *ext_var);
|
||||||
|
|
||||||
buf.push_str(" ]");
|
buf.push_str(" ]");
|
||||||
|
|
||||||
|
@ -629,8 +637,12 @@ pub fn chase_ext_tag_union<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
Content::Structure(RecursiveTagUnion(_, tags, ext_var)) => {
|
Content::Structure(RecursiveTagUnion(_, tags, ext_var)) => {
|
||||||
for (label, vars) in tags {
|
for (name_index, slice_index) in tags.iter_all() {
|
||||||
fields.push((label.clone(), vars.to_vec()));
|
let subs_slice = subs[slice_index];
|
||||||
|
let slice = subs.get_subs_slice(*subs_slice.as_subs_slice());
|
||||||
|
let tag_name = subs[name_index].clone();
|
||||||
|
|
||||||
|
fields.push((tag_name, slice.to_vec()));
|
||||||
}
|
}
|
||||||
|
|
||||||
chase_ext_tag_union(subs, *ext_var, fields)
|
chase_ext_tag_union(subs, *ext_var, fields)
|
||||||
|
|
|
@ -447,13 +447,16 @@ impl SolvedType {
|
||||||
|
|
||||||
let mut new_tags = Vec::with_capacity(tags.len());
|
let mut new_tags = Vec::with_capacity(tags.len());
|
||||||
|
|
||||||
for (tag_name, args) in tags {
|
for (name_index, slice_index) in tags.iter_all() {
|
||||||
let mut new_args = Vec::with_capacity(args.len());
|
let slice = subs[slice_index];
|
||||||
|
|
||||||
for var in args {
|
let mut new_args = Vec::with_capacity(slice.len());
|
||||||
new_args.push(Self::from_var_help(subs, recursion_vars, *var));
|
|
||||||
|
for var_index in slice {
|
||||||
|
let var = subs[var_index];
|
||||||
|
new_args.push(Self::from_var_help(subs, recursion_vars, var));
|
||||||
}
|
}
|
||||||
|
let tag_name = subs[name_index].clone();
|
||||||
new_tags.push((tag_name.clone(), new_args));
|
new_tags.push((tag_name.clone(), new_args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::types::{name_type_var, ErrorType, Problem, RecordField, TypeExt};
|
use crate::types::{name_type_var, ErrorType, Problem, RecordField, TypeExt};
|
||||||
use roc_collections::all::{ImMap, ImSet, MutMap, MutSet, SendMap};
|
use roc_collections::all::{ImMap, ImSet, MutSet, SendMap};
|
||||||
use roc_module::ident::{Lowercase, TagName};
|
use roc_module::ident::{Lowercase, TagName};
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -9,9 +9,9 @@ use ven_ena::unify::{InPlace, Snapshot, UnificationTable, UnifyKey};
|
||||||
// if your changes cause this number to go down, great!
|
// if your changes cause this number to go down, great!
|
||||||
// please change it to the lower number.
|
// please change it to the lower number.
|
||||||
// if it went up, maybe check that the change is really required
|
// if it went up, maybe check that the change is really required
|
||||||
static_assertions::assert_eq_size!([u8; 72], Descriptor);
|
static_assertions::assert_eq_size!([u8; 64], Descriptor);
|
||||||
static_assertions::assert_eq_size!([u8; 56], Content);
|
static_assertions::assert_eq_size!([u8; 48], Content);
|
||||||
static_assertions::assert_eq_size!([u8; 48], FlatType);
|
static_assertions::assert_eq_size!([u8; 40], FlatType);
|
||||||
static_assertions::assert_eq_size!([u8; 48], Problem);
|
static_assertions::assert_eq_size!([u8; 48], Problem);
|
||||||
|
|
||||||
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
|
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
|
@ -884,7 +884,7 @@ pub enum FlatType {
|
||||||
Record(RecordFields, Variable),
|
Record(RecordFields, Variable),
|
||||||
TagUnion(UnionTags, Variable),
|
TagUnion(UnionTags, Variable),
|
||||||
FunctionOrTagUnion(SubsIndex<TagName>, Symbol, Variable),
|
FunctionOrTagUnion(SubsIndex<TagName>, Symbol, Variable),
|
||||||
RecursiveTagUnion(Variable, MutMap<TagName, Vec<Variable>>, Variable),
|
RecursiveTagUnion(Variable, UnionTags, Variable),
|
||||||
Erroneous(Box<Problem>),
|
Erroneous(Box<Problem>),
|
||||||
EmptyRecord,
|
EmptyRecord,
|
||||||
EmptyTagUnion,
|
EmptyTagUnion,
|
||||||
|
@ -1376,8 +1376,15 @@ fn occurs(
|
||||||
}
|
}
|
||||||
RecursiveTagUnion(_rec_var, tags, ext_var) => {
|
RecursiveTagUnion(_rec_var, tags, ext_var) => {
|
||||||
// TODO rec_var is excluded here, verify that this is correct
|
// TODO rec_var is excluded here, verify that this is correct
|
||||||
let it = once(ext_var).chain(tags.values().flatten());
|
for slice_index in tags.variables {
|
||||||
short_circuit(subs, root_var, &new_seen, it)
|
let slice = subs[slice_index];
|
||||||
|
for var_index in slice {
|
||||||
|
let var = subs[var_index];
|
||||||
|
short_circuit_help(subs, root_var, &new_seen, var)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
short_circuit_help(subs, root_var, &new_seen, *ext_var)
|
||||||
}
|
}
|
||||||
EmptyRecord | EmptyTagUnion | Erroneous(_) => Ok(()),
|
EmptyRecord | EmptyTagUnion | Erroneous(_) => Ok(()),
|
||||||
}
|
}
|
||||||
|
@ -1481,7 +1488,6 @@ fn explicit_substitute(
|
||||||
let var = subs[var_index];
|
let var = subs[var_index];
|
||||||
let new_var = explicit_substitute(subs, from, to, var, seen);
|
let new_var = explicit_substitute(subs, from, to, var, seen);
|
||||||
new_variables.push(new_var);
|
new_variables.push(new_var);
|
||||||
// subs[var_index] = new_var;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = subs.variables.len() as u32;
|
let start = subs.variables.len() as u32;
|
||||||
|
@ -1509,17 +1515,40 @@ fn explicit_substitute(
|
||||||
Structure(FunctionOrTagUnion(tag_name, symbol, new_ext_var)),
|
Structure(FunctionOrTagUnion(tag_name, symbol, new_ext_var)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
RecursiveTagUnion(rec_var, mut tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
// NOTE rec_var is not substituted, verify that this is correct!
|
// NOTE rec_var is not substituted, verify that this is correct!
|
||||||
let new_ext_var = explicit_substitute(subs, from, to, ext_var, seen);
|
let new_ext_var = explicit_substitute(subs, from, to, ext_var, seen);
|
||||||
for (_, variables) in tags.iter_mut() {
|
|
||||||
for var in variables.iter_mut() {
|
let mut new_slices = Vec::new();
|
||||||
*var = explicit_substitute(subs, from, to, *var, seen);
|
for slice_index in tags.variables {
|
||||||
|
let slice = subs[slice_index];
|
||||||
|
|
||||||
|
let mut new_variables = Vec::new();
|
||||||
|
for var_index in slice {
|
||||||
|
let var = subs[var_index];
|
||||||
|
let new_var = explicit_substitute(subs, from, to, var, seen);
|
||||||
|
new_variables.push(new_var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let start = subs.variables.len() as u32;
|
||||||
|
let length = new_variables.len() as u16;
|
||||||
|
|
||||||
|
subs.variables.extend(new_variables);
|
||||||
|
|
||||||
|
new_slices.push(VariableSubsSlice::new(start, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let start = subs.variable_slices.len() as u32;
|
||||||
|
let length = new_slices.len() as u16;
|
||||||
|
|
||||||
|
subs.variable_slices.extend(new_slices);
|
||||||
|
|
||||||
|
let mut union_tags = tags;
|
||||||
|
union_tags.variables = SubsSlice::new(start, length);
|
||||||
|
|
||||||
subs.set_content(
|
subs.set_content(
|
||||||
in_var,
|
in_var,
|
||||||
Structure(RecursiveTagUnion(rec_var, tags, new_ext_var)),
|
Structure(RecursiveTagUnion(rec_var, union_tags, new_ext_var)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Record(vars_by_field, ext_var) => {
|
Record(vars_by_field, ext_var) => {
|
||||||
|
@ -1657,9 +1686,11 @@ fn get_var_names(
|
||||||
let taken_names = get_var_names(subs, ext_var, taken_names);
|
let taken_names = get_var_names(subs, ext_var, taken_names);
|
||||||
let mut taken_names = get_var_names(subs, rec_var, taken_names);
|
let mut taken_names = get_var_names(subs, rec_var, taken_names);
|
||||||
|
|
||||||
for vars in tags.values() {
|
for slice_index in tags.variables {
|
||||||
for arg_var in vars {
|
let slice = subs[slice_index];
|
||||||
taken_names = get_var_names(subs, *arg_var, taken_names)
|
for var_index in slice {
|
||||||
|
let arg_var = subs[var_index];
|
||||||
|
taken_names = get_var_names(subs, arg_var, taken_names)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1947,13 +1978,16 @@ fn flat_type_to_err_type(
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
let mut err_tags = SendMap::default();
|
let mut err_tags = SendMap::default();
|
||||||
|
|
||||||
for (tag, vars) in tags.into_iter() {
|
for (name_index, slice_index) in tags.iter_all() {
|
||||||
let mut err_vars = Vec::with_capacity(vars.len());
|
let mut err_vars = Vec::with_capacity(tags.len());
|
||||||
|
|
||||||
for var in vars {
|
let slice = subs[slice_index];
|
||||||
|
for var_index in slice {
|
||||||
|
let var = subs[var_index];
|
||||||
err_vars.push(var_to_err_type(subs, state, var));
|
err_vars.push(var_to_err_type(subs, state, var));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let tag = subs[name_index].clone();
|
||||||
err_tags.insert(tag, err_vars);
|
err_tags.insert(tag, err_vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2049,8 +2083,12 @@ fn restore_content(subs: &mut Subs, content: &Content) {
|
||||||
}
|
}
|
||||||
|
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
for var in tags.values().flatten() {
|
for slice_index in tags.variables {
|
||||||
subs.restore(*var);
|
let slice = subs[slice_index];
|
||||||
|
for var_index in slice {
|
||||||
|
let var = subs[var_index];
|
||||||
|
subs.restore(var);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subs.restore(*ext_var);
|
subs.restore(*ext_var);
|
||||||
|
|
|
@ -902,18 +902,7 @@ fn unify_shared_tags_merge_new(
|
||||||
) -> Outcome {
|
) -> Outcome {
|
||||||
let flat_type = if let Some(rec) = recursion_var {
|
let flat_type = if let Some(rec) = recursion_var {
|
||||||
debug_assert!(is_recursion_var(subs, rec));
|
debug_assert!(is_recursion_var(subs, rec));
|
||||||
|
FlatType::RecursiveTagUnion(rec, new_tags, new_ext_var)
|
||||||
let mut tags = MutMap::default();
|
|
||||||
|
|
||||||
for (name_index, slice_index) in new_tags.iter_all() {
|
|
||||||
let subs_slice = subs[slice_index];
|
|
||||||
let slice = subs.get_subs_slice(*subs_slice.as_subs_slice());
|
|
||||||
let tag = subs[name_index].clone();
|
|
||||||
|
|
||||||
tags.insert(tag, slice.to_vec());
|
|
||||||
}
|
|
||||||
|
|
||||||
FlatType::RecursiveTagUnion(rec, tags, new_ext_var)
|
|
||||||
} else {
|
} else {
|
||||||
FlatType::TagUnion(new_tags, new_ext_var)
|
FlatType::TagUnion(new_tags, new_ext_var)
|
||||||
};
|
};
|
||||||
|
@ -1296,7 +1285,7 @@ fn unify_shared_tags_recursive_not_recursive(
|
||||||
let mut new_tags = union(matching_tags, &other_tags);
|
let mut new_tags = union(matching_tags, &other_tags);
|
||||||
new_tags.extend(fields.into_iter());
|
new_tags.extend(fields.into_iter());
|
||||||
|
|
||||||
let flat_type = FlatType::RecursiveTagUnion(recursion_var, new_tags, new_ext_var);
|
let flat_type = from_mutmap_rec(subs, recursion_var, new_tags, new_ext_var);
|
||||||
|
|
||||||
merge(subs, ctx, Structure(flat_type))
|
merge(subs, ctx, Structure(flat_type))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1408,7 +1397,7 @@ fn unify_shared_tags_merge(
|
||||||
) -> Outcome {
|
) -> Outcome {
|
||||||
let flat_type = if let Some(rec) = recursion_var {
|
let flat_type = if let Some(rec) = recursion_var {
|
||||||
debug_assert!(is_recursion_var(subs, rec));
|
debug_assert!(is_recursion_var(subs, rec));
|
||||||
FlatType::RecursiveTagUnion(rec, new_tags, new_ext_var)
|
from_mutmap_rec(subs, rec, new_tags, new_ext_var)
|
||||||
} else {
|
} else {
|
||||||
from_mutmap(subs, new_tags, new_ext_var)
|
from_mutmap(subs, new_tags, new_ext_var)
|
||||||
};
|
};
|
||||||
|
@ -1458,7 +1447,7 @@ fn unify_flat_type(
|
||||||
(RecursiveTagUnion(recursion_var, tags1, ext1), TagUnion(tags2, ext2)) => {
|
(RecursiveTagUnion(recursion_var, tags1, ext1), TagUnion(tags2, ext2)) => {
|
||||||
debug_assert!(is_recursion_var(subs, *recursion_var));
|
debug_assert!(is_recursion_var(subs, *recursion_var));
|
||||||
// this never happens in type-correct programs, but may happen if there is a type error
|
// this never happens in type-correct programs, but may happen if there is a type error
|
||||||
let union1 = gather_tags(subs, tags1.clone(), *ext1);
|
let union1 = gather_tags_new(subs, *tags1, *ext1);
|
||||||
let union2 = gather_tags_new(subs, *tags2, *ext2);
|
let union2 = gather_tags_new(subs, *tags2, *ext2);
|
||||||
|
|
||||||
unify_tag_union(
|
unify_tag_union(
|
||||||
|
@ -1474,7 +1463,7 @@ fn unify_flat_type(
|
||||||
(TagUnion(tags1, ext1), RecursiveTagUnion(recursion_var, tags2, ext2)) => {
|
(TagUnion(tags1, ext1), RecursiveTagUnion(recursion_var, tags2, ext2)) => {
|
||||||
debug_assert!(is_recursion_var(subs, *recursion_var));
|
debug_assert!(is_recursion_var(subs, *recursion_var));
|
||||||
let union1 = gather_tags_new(subs, *tags1, *ext1);
|
let union1 = gather_tags_new(subs, *tags1, *ext1);
|
||||||
let union2 = gather_tags(subs, tags2.clone(), *ext2);
|
let union2 = gather_tags_new(subs, *tags2, *ext2);
|
||||||
|
|
||||||
unify_tag_union_not_recursive_recursive(subs, pool, ctx, union1, union2, *recursion_var)
|
unify_tag_union_not_recursive_recursive(subs, pool, ctx, union1, union2, *recursion_var)
|
||||||
}
|
}
|
||||||
|
@ -1482,8 +1471,8 @@ fn unify_flat_type(
|
||||||
(RecursiveTagUnion(rec1, tags1, ext1), RecursiveTagUnion(rec2, tags2, ext2)) => {
|
(RecursiveTagUnion(rec1, tags1, ext1), RecursiveTagUnion(rec2, tags2, ext2)) => {
|
||||||
debug_assert!(is_recursion_var(subs, *rec1));
|
debug_assert!(is_recursion_var(subs, *rec1));
|
||||||
debug_assert!(is_recursion_var(subs, *rec2));
|
debug_assert!(is_recursion_var(subs, *rec2));
|
||||||
let union1 = gather_tags(subs, tags1.clone(), *ext1);
|
let union1 = gather_tags_new(subs, *tags1, *ext1);
|
||||||
let union2 = gather_tags(subs, tags2.clone(), *ext2);
|
let union2 = gather_tags_new(subs, *tags2, *ext2);
|
||||||
|
|
||||||
let mut problems =
|
let mut problems =
|
||||||
unify_tag_union(subs, pool, ctx, union1, union2, (Some(*rec1), Some(*rec2)));
|
unify_tag_union(subs, pool, ctx, union1, union2, (Some(*rec1), Some(*rec2)));
|
||||||
|
@ -1602,7 +1591,7 @@ fn unify_flat_type(
|
||||||
let mut tags2 = MutMap::default();
|
let mut tags2 = MutMap::default();
|
||||||
tags2.insert(tag_name, vec![]);
|
tags2.insert(tag_name, vec![]);
|
||||||
|
|
||||||
let union1 = gather_tags(subs, tags1.clone(), *ext1);
|
let union1 = gather_tags_new(subs, *tags1, *ext1);
|
||||||
let union2 = gather_tags(subs, tags2, *ext2);
|
let union2 = gather_tags(subs, tags2, *ext2);
|
||||||
|
|
||||||
unify_tag_union(
|
unify_tag_union(
|
||||||
|
@ -1624,7 +1613,7 @@ fn unify_flat_type(
|
||||||
tags1.insert(tag_name, vec![]);
|
tags1.insert(tag_name, vec![]);
|
||||||
|
|
||||||
let union1 = gather_tags(subs, tags1, *ext1);
|
let union1 = gather_tags(subs, tags1, *ext1);
|
||||||
let union2 = gather_tags(subs, tags2.clone(), *ext2);
|
let union2 = gather_tags_new(subs, *tags2, *ext2);
|
||||||
|
|
||||||
unify_tag_union_not_recursive_recursive(subs, pool, ctx, union1, union2, *recursion_var)
|
unify_tag_union_not_recursive_recursive(subs, pool, ctx, union1, union2, *recursion_var)
|
||||||
}
|
}
|
||||||
|
@ -1894,6 +1883,21 @@ pub fn from_mutmap(
|
||||||
FlatType::TagUnion(union_tags, ext)
|
FlatType::TagUnion(union_tags, ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_mutmap_rec(
|
||||||
|
subs: &mut Subs,
|
||||||
|
rec: Variable,
|
||||||
|
tags: MutMap<TagName, Vec<Variable>>,
|
||||||
|
ext: Variable,
|
||||||
|
) -> FlatType {
|
||||||
|
let mut vec: Vec<_> = tags.into_iter().collect();
|
||||||
|
|
||||||
|
vec.sort();
|
||||||
|
|
||||||
|
let union_tags = UnionTags::insert_into_subs(subs, vec);
|
||||||
|
|
||||||
|
FlatType::RecursiveTagUnion(rec, union_tags, ext)
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn unify_function_or_tag_union_and_func(
|
fn unify_function_or_tag_union_and_func(
|
||||||
subs: &mut Subs,
|
subs: &mut Subs,
|
||||||
|
|
|
@ -1013,7 +1013,8 @@ fn check_for_infinite_type(
|
||||||
|
|
||||||
let new_ext_var = subs.explicit_substitute(recursive, rec_var, ext_var);
|
let new_ext_var = subs.explicit_substitute(recursive, rec_var, ext_var);
|
||||||
|
|
||||||
let flat_type = FlatType::RecursiveTagUnion(rec_var, new_tags, new_ext_var);
|
let flat_type =
|
||||||
|
roc_unify::unify::from_mutmap_rec(subs, rec_var, new_tags, new_ext_var);
|
||||||
|
|
||||||
subs.set_content(recursive, Content::Structure(flat_type));
|
subs.set_content(recursive, Content::Structure(flat_type));
|
||||||
}
|
}
|
||||||
|
@ -1252,9 +1253,13 @@ fn adjust_rank_content(
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *ext_var);
|
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *ext_var);
|
||||||
|
|
||||||
for var in tags.values().flatten() {
|
for (_, index) in tags.iter_all() {
|
||||||
rank =
|
let slice = subs[index];
|
||||||
rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var));
|
for var_index in slice {
|
||||||
|
let var = subs[var_index];
|
||||||
|
rank = rank
|
||||||
|
.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// THEORY: the recursion var has the same rank as the tag union itself
|
// THEORY: the recursion var has the same rank as the tag union itself
|
||||||
|
@ -1403,8 +1408,10 @@ fn instantiate_rigids_help(
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
instantiate_rigids_help(subs, max_rank, pools, rec_var);
|
instantiate_rigids_help(subs, max_rank, pools, rec_var);
|
||||||
|
|
||||||
for (_, vars) in tags {
|
for (_, index) in tags.iter_all() {
|
||||||
for var in vars.into_iter() {
|
let slice = subs[index];
|
||||||
|
for var_index in slice {
|
||||||
|
let var = subs[var_index];
|
||||||
instantiate_rigids_help(subs, max_rank, pools, var);
|
instantiate_rigids_help(subs, max_rank, pools, var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1594,19 +1601,21 @@ fn deep_copy_var_help(
|
||||||
|
|
||||||
let new_rec_var = deep_copy_var_help(subs, max_rank, pools, rec_var);
|
let new_rec_var = deep_copy_var_help(subs, max_rank, pools, rec_var);
|
||||||
|
|
||||||
for (tag, vars) in tags {
|
for (tag_index, index) in tags.iter_all() {
|
||||||
let new_vars: Vec<Variable> = vars
|
let tag = subs[tag_index].clone();
|
||||||
.into_iter()
|
let slice = subs[index];
|
||||||
.map(|var| deep_copy_var_help(subs, max_rank, pools, var))
|
let mut new_vars = Vec::new();
|
||||||
.collect();
|
for var_index in slice {
|
||||||
|
let var = subs[var_index];
|
||||||
|
let new_var = deep_copy_var_help(subs, max_rank, pools, var);
|
||||||
|
new_vars.push(new_var);
|
||||||
|
}
|
||||||
|
|
||||||
new_tags.insert(tag, new_vars);
|
new_tags.insert(tag, new_vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecursiveTagUnion(
|
let new_ext = deep_copy_var_help(subs, max_rank, pools, ext_var);
|
||||||
new_rec_var,
|
roc_unify::unify::from_mutmap_rec(subs, new_rec_var, new_tags, new_ext)
|
||||||
new_tags,
|
|
||||||
deep_copy_var_help(subs, max_rank, pools, ext_var),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue