mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 21:39:07 +00:00
Unwrap layouts containing void layouts as newtypes
Addresses the attempt to do so in https://github.com/roc-lang/roc/pull/3465 Co-authored-by: Folkert <folkert@folkertdev.nl>
This commit is contained in:
parent
639c1e5fa3
commit
f41936d5e5
9 changed files with 228 additions and 14 deletions
|
@ -1,4 +1,5 @@
|
|||
use crate::ir::Parens;
|
||||
use bitvec::vec::BitVec;
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||
|
@ -3279,6 +3280,11 @@ pub enum UnionVariant<'a> {
|
|||
tag_name: TagOrClosure,
|
||||
arguments: Vec<'a, Layout<'a>>,
|
||||
},
|
||||
NewtypeByVoid {
|
||||
data_tag_name: TagOrClosure,
|
||||
data_tag_id: TagIdIntType,
|
||||
data_tag_arguments: Vec<'a, Layout<'a>>,
|
||||
},
|
||||
Wrapped(WrappedVariant<'a>),
|
||||
}
|
||||
|
||||
|
@ -3525,6 +3531,8 @@ where
|
|||
Vec::with_capacity_in(tags_list.len(), env.arena);
|
||||
let mut has_any_arguments = false;
|
||||
|
||||
let mut inhabited_tag_ids = BitVec::<usize>::repeat(true, num_tags);
|
||||
|
||||
for &(tag_name, arguments) in tags_list.into_iter() {
|
||||
let mut arg_layouts = Vec::with_capacity_in(arguments.len() + 1, env.arena);
|
||||
|
||||
|
@ -3536,6 +3544,10 @@ where
|
|||
has_any_arguments = true;
|
||||
|
||||
arg_layouts.push(layout);
|
||||
|
||||
if layout == Layout::VOID {
|
||||
inhabited_tag_ids.set(answer.len(), false);
|
||||
}
|
||||
}
|
||||
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
|
||||
// If we encounter an unbound type var (e.g. `Ok *`)
|
||||
|
@ -3560,6 +3572,18 @@ where
|
|||
answer.push((tag_name.clone().into(), arg_layouts.into_bump_slice()));
|
||||
}
|
||||
|
||||
if inhabited_tag_ids.count_ones() == 1 {
|
||||
let kept_tag_id = inhabited_tag_ids.first_one().unwrap();
|
||||
let kept = answer.get(kept_tag_id).unwrap();
|
||||
|
||||
let variant = UnionVariant::NewtypeByVoid {
|
||||
data_tag_name: kept.0.clone(),
|
||||
data_tag_id: kept_tag_id as _,
|
||||
data_tag_arguments: Vec::from_iter_in(kept.1.iter().copied(), env.arena),
|
||||
};
|
||||
return Cacheable(variant, cache_criteria);
|
||||
}
|
||||
|
||||
match num_tags {
|
||||
2 if !has_any_arguments => {
|
||||
// type can be stored in a boolean
|
||||
|
@ -3680,6 +3704,7 @@ where
|
|||
let mut has_any_arguments = false;
|
||||
|
||||
let mut nullable = None;
|
||||
let mut inhabited_tag_ids = BitVec::<usize>::repeat(true, num_tags);
|
||||
|
||||
// only recursive tag unions can be nullable
|
||||
let is_recursive = opt_rec_var.is_some();
|
||||
|
@ -3721,6 +3746,10 @@ where
|
|||
} else {
|
||||
arg_layouts.push(layout);
|
||||
}
|
||||
|
||||
if layout == Layout::VOID {
|
||||
inhabited_tag_ids.set(answer.len(), false);
|
||||
}
|
||||
}
|
||||
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
|
||||
// If we encounter an unbound type var (e.g. `Ok *`)
|
||||
|
@ -3746,6 +3775,18 @@ where
|
|||
answer.push((tag_name.into(), arg_layouts.into_bump_slice()));
|
||||
}
|
||||
|
||||
if inhabited_tag_ids.count_ones() == 1 && !is_recursive {
|
||||
let kept_tag_id = inhabited_tag_ids.first_one().unwrap();
|
||||
let kept = answer.get(kept_tag_id).unwrap();
|
||||
|
||||
let variant = UnionVariant::NewtypeByVoid {
|
||||
data_tag_name: kept.0.clone(),
|
||||
data_tag_id: kept_tag_id as _,
|
||||
data_tag_arguments: Vec::from_iter_in(kept.1.iter().copied(), env.arena),
|
||||
};
|
||||
return Cacheable(variant, cache_criteria);
|
||||
}
|
||||
|
||||
match num_tags {
|
||||
2 if !has_any_arguments => {
|
||||
// type can be stored in a boolean
|
||||
|
@ -3870,6 +3911,15 @@ where
|
|||
|
||||
answer1
|
||||
}
|
||||
NewtypeByVoid {
|
||||
data_tag_arguments, ..
|
||||
} => {
|
||||
if data_tag_arguments.len() == 1 {
|
||||
data_tag_arguments[0]
|
||||
} else {
|
||||
Layout::struct_no_name_order(data_tag_arguments.into_bump_slice())
|
||||
}
|
||||
}
|
||||
Wrapped(variant) => {
|
||||
use WrappedVariant::*;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue