mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
early return in common tag case
This commit is contained in:
parent
05b43c6799
commit
564efd528a
1 changed files with 45 additions and 26 deletions
|
@ -449,18 +449,22 @@ fn unify_tag_union(
|
|||
let tags1 = rec1.tags;
|
||||
let tags2 = rec2.tags;
|
||||
|
||||
let Separate {
|
||||
only_in_1: unique_tags1,
|
||||
only_in_2: unique_tags2,
|
||||
in_both: shared_tags,
|
||||
} = separate(tags1, tags2);
|
||||
|
||||
let recursion_var = match recursion {
|
||||
(None, None) => None,
|
||||
(Some(v), None) | (None, Some(v)) => Some(v),
|
||||
(Some(v1), Some(_v2)) => Some(v1),
|
||||
};
|
||||
|
||||
if tags1.len() == 1 && tags2.len() == 1 && tags1 == tags2 {
|
||||
return unify_shared_tags_merge(subs, ctx, tags1, rec1.ext, recursion_var);
|
||||
}
|
||||
|
||||
let Separate {
|
||||
only_in_1: unique_tags1,
|
||||
only_in_2: unique_tags2,
|
||||
in_both: shared_tags,
|
||||
} = separate(tags1, tags2);
|
||||
|
||||
if unique_tags1.is_empty() {
|
||||
if unique_tags2.is_empty() {
|
||||
let ext_problems = unify_pool(subs, pool, rec1.ext, rec2.ext);
|
||||
|
@ -724,8 +728,8 @@ fn unify_tag_union_not_recursive_recursive(
|
|||
/// into it.
|
||||
#[allow(dead_code)]
|
||||
fn is_structure(var: Variable, subs: &mut Subs) -> bool {
|
||||
match subs.get(var).content {
|
||||
Content::Alias(_, _, actual) => is_structure(actual, subs),
|
||||
match subs.get_content_without_compacting(var) {
|
||||
Content::Alias(_, _, actual) => is_structure(*actual, subs),
|
||||
Content::Structure(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
|
@ -875,6 +879,8 @@ fn unify_shared_tags(
|
|||
}
|
||||
|
||||
if num_shared_tags == matching_tags.len() {
|
||||
let mut new_tags = matching_tags;
|
||||
|
||||
// merge fields from the ext_var into this tag union
|
||||
let mut fields = Vec::new();
|
||||
let new_ext_var = match roc_types::pretty_print::chase_ext_tag_union(subs, ext, &mut fields)
|
||||
|
@ -882,8 +888,7 @@ fn unify_shared_tags(
|
|||
Ok(()) => Variable::EMPTY_TAG_UNION,
|
||||
Err((new, _)) => new,
|
||||
};
|
||||
|
||||
let mut new_tags = matching_tags;
|
||||
new_tags.extend(fields.into_iter());
|
||||
|
||||
match other_tags {
|
||||
OtherTags::Empty => {}
|
||||
|
@ -893,16 +898,7 @@ fn unify_shared_tags(
|
|||
}
|
||||
}
|
||||
|
||||
new_tags.extend(fields.into_iter());
|
||||
|
||||
let flat_type = if let Some(rec) = recursion_var {
|
||||
debug_assert!(is_recursion_var(subs, rec));
|
||||
FlatType::RecursiveTagUnion(rec, new_tags, new_ext_var)
|
||||
} else {
|
||||
FlatType::TagUnion(new_tags, new_ext_var)
|
||||
};
|
||||
|
||||
merge(subs, ctx, Structure(flat_type))
|
||||
unify_shared_tags_merge(subs, ctx, new_tags, new_ext_var, recursion_var)
|
||||
} else {
|
||||
mismatch!(
|
||||
"Problem with Tag Union\nThere should be {:?} matching tags, but I only got \n{:?}",
|
||||
|
@ -912,6 +908,23 @@ fn unify_shared_tags(
|
|||
}
|
||||
}
|
||||
|
||||
fn unify_shared_tags_merge(
|
||||
subs: &mut Subs,
|
||||
ctx: &Context,
|
||||
new_tags: MutMap<TagName, Vec<Variable>>,
|
||||
new_ext_var: Variable,
|
||||
recursion_var: Option<Variable>,
|
||||
) -> Outcome {
|
||||
let flat_type = if let Some(rec) = recursion_var {
|
||||
debug_assert!(is_recursion_var(subs, rec));
|
||||
FlatType::RecursiveTagUnion(rec, new_tags, new_ext_var)
|
||||
} else {
|
||||
FlatType::TagUnion(new_tags, new_ext_var)
|
||||
};
|
||||
|
||||
merge(subs, ctx, Structure(flat_type))
|
||||
}
|
||||
|
||||
fn has_only_optional_fields<'a, I, T>(fields: &mut I) -> bool
|
||||
where
|
||||
I: Iterator<Item = &'a RecordField<T>>,
|
||||
|
@ -1069,8 +1082,8 @@ fn unify_flat_type(
|
|||
if tag_name_1 == tag_name_2 {
|
||||
let problems = unify_pool(subs, pool, *ext_1, *ext_2);
|
||||
if problems.is_empty() {
|
||||
let desc = subs.get(ctx.second);
|
||||
merge(subs, ctx, desc.content)
|
||||
let content = subs.get_content_without_compacting(ctx.second).clone();
|
||||
merge(subs, ctx, content)
|
||||
} else {
|
||||
problems
|
||||
}
|
||||
|
@ -1292,19 +1305,25 @@ fn fresh(subs: &mut Subs, pool: &mut Pool, ctx: &Context, content: Content) -> V
|
|||
|
||||
fn gather_tags(
|
||||
subs: &mut Subs,
|
||||
tags: MutMap<TagName, Vec<Variable>>,
|
||||
mut tags: MutMap<TagName, Vec<Variable>>,
|
||||
var: Variable,
|
||||
) -> TagUnionStructure {
|
||||
use roc_types::subs::Content::*;
|
||||
use roc_types::subs::FlatType::*;
|
||||
|
||||
match subs.get(var).content {
|
||||
match subs.get_content_without_compacting(var) {
|
||||
Structure(TagUnion(sub_tags, sub_ext)) => {
|
||||
gather_tags(subs, union(tags, &sub_tags), sub_ext)
|
||||
for (k, v) in sub_tags {
|
||||
tags.insert(k.clone(), v.clone());
|
||||
}
|
||||
|
||||
let sub_ext = *sub_ext;
|
||||
gather_tags(subs, tags, sub_ext)
|
||||
}
|
||||
|
||||
Alias(_, _, var) => {
|
||||
// TODO according to elm/compiler: "TODO may be dropping useful alias info here"
|
||||
let var = *var;
|
||||
gather_tags(subs, tags, var)
|
||||
}
|
||||
|
||||
|
@ -1314,7 +1333,7 @@ fn gather_tags(
|
|||
|
||||
fn is_recursion_var(subs: &Subs, var: Variable) -> bool {
|
||||
matches!(
|
||||
subs.get_without_compacting(var).content,
|
||||
subs.get_content_without_compacting(var),
|
||||
Content::RecursionVar { .. }
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue