mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +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 tags1 = rec1.tags;
|
||||||
let tags2 = rec2.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 {
|
let recursion_var = match recursion {
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
(Some(v), None) | (None, Some(v)) => Some(v),
|
(Some(v), None) | (None, Some(v)) => Some(v),
|
||||||
(Some(v1), Some(_v2)) => Some(v1),
|
(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_tags1.is_empty() {
|
||||||
if unique_tags2.is_empty() {
|
if unique_tags2.is_empty() {
|
||||||
let ext_problems = unify_pool(subs, pool, rec1.ext, rec2.ext);
|
let ext_problems = unify_pool(subs, pool, rec1.ext, rec2.ext);
|
||||||
|
@ -724,8 +728,8 @@ fn unify_tag_union_not_recursive_recursive(
|
||||||
/// into it.
|
/// into it.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn is_structure(var: Variable, subs: &mut Subs) -> bool {
|
fn is_structure(var: Variable, subs: &mut Subs) -> bool {
|
||||||
match subs.get(var).content {
|
match subs.get_content_without_compacting(var) {
|
||||||
Content::Alias(_, _, actual) => is_structure(actual, subs),
|
Content::Alias(_, _, actual) => is_structure(*actual, subs),
|
||||||
Content::Structure(_) => true,
|
Content::Structure(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -875,6 +879,8 @@ fn unify_shared_tags(
|
||||||
}
|
}
|
||||||
|
|
||||||
if num_shared_tags == matching_tags.len() {
|
if num_shared_tags == matching_tags.len() {
|
||||||
|
let mut new_tags = matching_tags;
|
||||||
|
|
||||||
// merge fields from the ext_var into this tag union
|
// merge fields from the ext_var into this tag union
|
||||||
let mut fields = Vec::new();
|
let mut fields = Vec::new();
|
||||||
let new_ext_var = match roc_types::pretty_print::chase_ext_tag_union(subs, ext, &mut fields)
|
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,
|
Ok(()) => Variable::EMPTY_TAG_UNION,
|
||||||
Err((new, _)) => new,
|
Err((new, _)) => new,
|
||||||
};
|
};
|
||||||
|
new_tags.extend(fields.into_iter());
|
||||||
let mut new_tags = matching_tags;
|
|
||||||
|
|
||||||
match other_tags {
|
match other_tags {
|
||||||
OtherTags::Empty => {}
|
OtherTags::Empty => {}
|
||||||
|
@ -893,16 +898,7 @@ fn unify_shared_tags(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new_tags.extend(fields.into_iter());
|
unify_shared_tags_merge(subs, ctx, new_tags, new_ext_var, recursion_var)
|
||||||
|
|
||||||
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))
|
|
||||||
} else {
|
} else {
|
||||||
mismatch!(
|
mismatch!(
|
||||||
"Problem with Tag Union\nThere should be {:?} matching tags, but I only got \n{:?}",
|
"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
|
fn has_only_optional_fields<'a, I, T>(fields: &mut I) -> bool
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'a RecordField<T>>,
|
I: Iterator<Item = &'a RecordField<T>>,
|
||||||
|
@ -1069,8 +1082,8 @@ fn unify_flat_type(
|
||||||
if tag_name_1 == tag_name_2 {
|
if tag_name_1 == tag_name_2 {
|
||||||
let problems = unify_pool(subs, pool, *ext_1, *ext_2);
|
let problems = unify_pool(subs, pool, *ext_1, *ext_2);
|
||||||
if problems.is_empty() {
|
if problems.is_empty() {
|
||||||
let desc = subs.get(ctx.second);
|
let content = subs.get_content_without_compacting(ctx.second).clone();
|
||||||
merge(subs, ctx, desc.content)
|
merge(subs, ctx, content)
|
||||||
} else {
|
} else {
|
||||||
problems
|
problems
|
||||||
}
|
}
|
||||||
|
@ -1292,19 +1305,25 @@ fn fresh(subs: &mut Subs, pool: &mut Pool, ctx: &Context, content: Content) -> V
|
||||||
|
|
||||||
fn gather_tags(
|
fn gather_tags(
|
||||||
subs: &mut Subs,
|
subs: &mut Subs,
|
||||||
tags: MutMap<TagName, Vec<Variable>>,
|
mut tags: MutMap<TagName, Vec<Variable>>,
|
||||||
var: Variable,
|
var: Variable,
|
||||||
) -> TagUnionStructure {
|
) -> TagUnionStructure {
|
||||||
use roc_types::subs::Content::*;
|
use roc_types::subs::Content::*;
|
||||||
use roc_types::subs::FlatType::*;
|
use roc_types::subs::FlatType::*;
|
||||||
|
|
||||||
match subs.get(var).content {
|
match subs.get_content_without_compacting(var) {
|
||||||
Structure(TagUnion(sub_tags, sub_ext)) => {
|
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) => {
|
Alias(_, _, var) => {
|
||||||
// TODO according to elm/compiler: "TODO may be dropping useful alias info here"
|
// TODO according to elm/compiler: "TODO may be dropping useful alias info here"
|
||||||
|
let var = *var;
|
||||||
gather_tags(subs, tags, var)
|
gather_tags(subs, tags, var)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1314,7 +1333,7 @@ fn gather_tags(
|
||||||
|
|
||||||
fn is_recursion_var(subs: &Subs, var: Variable) -> bool {
|
fn is_recursion_var(subs: &Subs, var: Variable) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
subs.get_without_compacting(var).content,
|
subs.get_content_without_compacting(var),
|
||||||
Content::RecursionVar { .. }
|
Content::RecursionVar { .. }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue