mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-18 01:29:47 +00:00
make chasing an ext return a custom type
This commit is contained in:
parent
acb71d6007
commit
d93d42da8c
2 changed files with 57 additions and 28 deletions
|
@ -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),
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue