make chasing an ext return a custom type

This commit is contained in:
Folkert 2022-08-30 00:51:24 +02:00
parent acb71d6007
commit d93d42da8c
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
2 changed files with 57 additions and 28 deletions

View file

@ -2712,6 +2712,9 @@ pub fn union_sorted_tags<'a>(
subs: &Subs, subs: &Subs,
target_info: TargetInfo, target_info: TargetInfo,
) -> Result<UnionVariant<'a>, LayoutProblem> { ) -> Result<UnionVariant<'a>, LayoutProblem> {
use roc_types::pretty_print::ChasedExt;
use Content::*;
let var = let var =
if let Content::RecursionVar { structure, .. } = subs.get_content_without_compacting(var) { if let Content::RecursionVar { structure, .. } = subs.get_content_without_compacting(var) {
*structure *structure
@ -2721,20 +2724,32 @@ pub fn union_sorted_tags<'a>(
let mut tags_vec = std::vec::Vec::new(); let mut tags_vec = std::vec::Vec::new();
let result = match roc_types::pretty_print::chase_ext_tag_union(subs, var, &mut tags_vec) { let result = match roc_types::pretty_print::chase_ext_tag_union(subs, var, &mut tags_vec) {
Ok(()) ChasedExt::Empty => {
// Admit type variables in the extension for now. This may come from things that never got
// monomorphized, like in
// x : [A]*
// x = A
// x
// In such cases it's fine to drop the variable. We may be proven wrong in the future...
| Err((_, Content::FlexVar(_) | Content::FlexAbleVar(..) | Content::RigidVar(_) | Content::RigidAbleVar(..)))
| Err((_, Content::RecursionVar { .. })) => {
let opt_rec_var = get_recursion_var(subs, var); let opt_rec_var = get_recursion_var(subs, var);
union_sorted_tags_help(arena, tags_vec, opt_rec_var, subs, target_info) union_sorted_tags_help(arena, tags_vec, opt_rec_var, subs, target_info)
} }
Err((_, Content::Error)) => return Err(LayoutProblem::Erroneous), ChasedExt::NonEmpty { content, .. } => {
Err(other) => panic!("invalid content in tag union variable: {:?}", other), match content {
FlexVar(_) | FlexAbleVar(..) | RigidVar(_) | RigidAbleVar(..) => {
// Admit type variables in the extension for now. This may come from things that never got
// monomorphized, like in
// x : [A]*
// x = A
// x
// In such cases it's fine to drop the variable. We may be proven wrong in the future...
let opt_rec_var = get_recursion_var(subs, var);
union_sorted_tags_help(arena, tags_vec, opt_rec_var, subs, target_info)
}
RecursionVar { .. } => {
let opt_rec_var = get_recursion_var(subs, var);
union_sorted_tags_help(arena, tags_vec, opt_rec_var, subs, target_info)
}
Error => return Err(LayoutProblem::Erroneous),
other => panic!("invalid content in tag union variable: {:?}", other),
}
}
}; };
Ok(result) Ok(result)
@ -3366,21 +3381,24 @@ pub fn ext_var_is_empty_record(_subs: &Subs, _ext_var: Variable) -> bool {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
pub fn ext_var_is_empty_tag_union(subs: &Subs, ext_var: Variable) -> bool { pub fn ext_var_is_empty_tag_union(subs: &Subs, ext_var: Variable) -> bool {
use roc_types::pretty_print::ChasedExt;
use Content::*;
// the ext_var is empty // the ext_var is empty
let mut ext_fields = std::vec::Vec::new(); let mut ext_fields = std::vec::Vec::new();
match roc_types::pretty_print::chase_ext_tag_union(subs, ext_var, &mut ext_fields) { match roc_types::pretty_print::chase_ext_tag_union(subs, ext_var, &mut ext_fields) {
Ok(()) ChasedExt::Empty => ext_fields.is_empty(),
| Err(( ChasedExt::NonEmpty { content, .. } => {
_, match content {
// Allow flex/rigid to decay away into nothing // Allow flex/rigid to decay away into nothing
Content::FlexVar(_) FlexVar(_) | FlexAbleVar(..) | RigidVar(_) | RigidAbleVar(..) => {
| Content::FlexAbleVar(..) ext_fields.is_empty()
| Content::RigidVar(_) }
| Content::RigidAbleVar(..) // So that we can continue compiling in the presence of errors
// So that we can continue compiling in the presence of errors Error => ext_fields.is_empty(),
| Content::Error, _ => panic!("invalid content in ext_var: {:?}", content),
)) => ext_fields.is_empty(), }
Err(content) => panic!("invalid content in ext_var: {:?}", content), }
} }
} }

View file

@ -1216,14 +1216,22 @@ pub fn push_union<'a, L: Label>(
} }
} }
pub fn chase_ext_tag_union<'a>( pub enum ChasedExt {
subs: &'a Subs, Empty,
NonEmpty {
variable: Variable,
content: Content,
},
}
pub fn chase_ext_tag_union(
subs: &'_ Subs,
var: Variable, var: Variable,
fields: &mut Vec<(TagName, Vec<Variable>)>, fields: &mut Vec<(TagName, Vec<Variable>)>,
) -> Result<(), (Variable, &'a Content)> { ) -> ChasedExt {
use FlatType::*; use FlatType::*;
match subs.get_content_without_compacting(var) { match subs.get_content_without_compacting(var) {
Content::Structure(EmptyTagUnion) => Ok(()), Content::Structure(EmptyTagUnion) => ChasedExt::Empty,
Content::Structure(TagUnion(tags, ext_var)) => { Content::Structure(TagUnion(tags, ext_var)) => {
push_union(subs, tags, fields); push_union(subs, tags, fields);
chase_ext_tag_union(subs, *ext_var, fields) chase_ext_tag_union(subs, *ext_var, fields)
@ -1241,7 +1249,10 @@ pub fn chase_ext_tag_union<'a>(
Content::Alias(_, _, var, _) => chase_ext_tag_union(subs, *var, fields), Content::Alias(_, _, var, _) => chase_ext_tag_union(subs, *var, fields),
content => Err((var, content)), content => ChasedExt::NonEmpty {
variable: var,
content: *content,
},
} }
} }