mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
refactor union layout
This commit is contained in:
parent
c85fa58648
commit
de666c575f
6 changed files with 266 additions and 193 deletions
|
@ -9,8 +9,8 @@ use crate::llvm::build_str::{
|
||||||
};
|
};
|
||||||
use crate::llvm::compare::{build_eq, build_neq};
|
use crate::llvm::compare::{build_eq, build_neq};
|
||||||
use crate::llvm::convert::{
|
use crate::llvm::convert::{
|
||||||
basic_type_from_builtin, basic_type_from_layout, block_of_memory, block_of_memory_slice,
|
basic_type_from_builtin, basic_type_from_layout, block_of_memory, collection, get_fn_type,
|
||||||
collection, get_fn_type, get_ptr_type, ptr_int,
|
get_ptr_type, ptr_int,
|
||||||
};
|
};
|
||||||
use crate::llvm::refcounting::{
|
use crate::llvm::refcounting::{
|
||||||
decrement_refcount_layout, increment_refcount_layout, refcount_is_one_comparison,
|
decrement_refcount_layout, increment_refcount_layout, refcount_is_one_comparison,
|
||||||
|
@ -42,7 +42,7 @@ use roc_module::ident::TagName;
|
||||||
use roc_module::low_level::LowLevel;
|
use roc_module::low_level::LowLevel;
|
||||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||||
use roc_mono::ir::{CallType, JoinPointId, Wrapped};
|
use roc_mono::ir::{CallType, JoinPointId, Wrapped};
|
||||||
use roc_mono::layout::{Builtin, ClosureLayout, Layout, LayoutIds, MemoryMode};
|
use roc_mono::layout::{Builtin, ClosureLayout, Layout, LayoutIds, MemoryMode, UnionLayout};
|
||||||
use target_lexicon::CallingConvention;
|
use target_lexicon::CallingConvention;
|
||||||
|
|
||||||
/// This is for Inkwell's FunctionValue::verify - we want to know the verification
|
/// This is for Inkwell's FunctionValue::verify - we want to know the verification
|
||||||
|
@ -859,13 +859,13 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
Tag {
|
Tag {
|
||||||
arguments,
|
arguments,
|
||||||
tag_layout: Layout::Union(fields),
|
tag_layout: Layout::Union(UnionLayout::NonRecursive(fields)),
|
||||||
union_size,
|
union_size,
|
||||||
tag_id,
|
tag_id,
|
||||||
tag_name,
|
tag_name,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let tag_layout = Layout::Union(fields);
|
let tag_layout = Layout::Union(UnionLayout::NonRecursive(fields));
|
||||||
|
|
||||||
debug_assert!(*union_size > 1);
|
debug_assert!(*union_size > 1);
|
||||||
let ptr_size = env.ptr_bytes;
|
let ptr_size = env.ptr_bytes;
|
||||||
|
@ -960,13 +960,13 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
Tag {
|
Tag {
|
||||||
arguments,
|
arguments,
|
||||||
tag_layout: Layout::RecursiveUnion(fields),
|
tag_layout: Layout::Union(UnionLayout::Recursive(fields)),
|
||||||
union_size,
|
union_size,
|
||||||
tag_id,
|
tag_id,
|
||||||
tag_name,
|
tag_name,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let tag_layout = Layout::Union(fields);
|
let tag_layout = Layout::Union(UnionLayout::NonRecursive(fields));
|
||||||
|
|
||||||
debug_assert!(*union_size > 1);
|
debug_assert!(*union_size > 1);
|
||||||
let ptr_size = env.ptr_bytes;
|
let ptr_size = env.ptr_bytes;
|
||||||
|
@ -1042,17 +1042,17 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
Tag {
|
Tag {
|
||||||
arguments,
|
arguments,
|
||||||
tag_layout:
|
tag_layout:
|
||||||
Layout::NullableUnion {
|
Layout::Union(UnionLayout::NullableWrapped {
|
||||||
nullable_id,
|
nullable_id,
|
||||||
nullable_layout: _,
|
nullable_layout: _,
|
||||||
foo: fields,
|
other_tags: fields,
|
||||||
},
|
}),
|
||||||
union_size,
|
union_size,
|
||||||
tag_id,
|
tag_id,
|
||||||
tag_name,
|
tag_name,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let tag_layout = Layout::Union(fields);
|
let tag_layout = Layout::Union(UnionLayout::NonRecursive(fields));
|
||||||
let tag_struct_type =
|
let tag_struct_type =
|
||||||
basic_type_from_layout(env.arena, env.context, &tag_layout, env.ptr_bytes);
|
basic_type_from_layout(env.arena, env.context, &tag_layout, env.ptr_bytes);
|
||||||
if *tag_id == *nullable_id as u8 {
|
if *tag_id == *nullable_id as u8 {
|
||||||
|
@ -1251,11 +1251,11 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
PointerValue(value) => {
|
PointerValue(value) => {
|
||||||
match structure_layout {
|
match structure_layout {
|
||||||
Layout::NullableUnion {
|
Layout::Union(UnionLayout::NullableWrapped {
|
||||||
nullable_id,
|
nullable_id,
|
||||||
foo: fields,
|
other_tags: fields,
|
||||||
..
|
..
|
||||||
} if *index == 0 => {
|
}) if *index == 0 => {
|
||||||
let ptr = value;
|
let ptr = value;
|
||||||
let is_null = env.builder.build_is_null(ptr, "is_null");
|
let is_null = env.builder.build_is_null(ptr, "is_null");
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use inkwell::context::Context;
|
||||||
use inkwell::types::BasicTypeEnum::{self, *};
|
use inkwell::types::BasicTypeEnum::{self, *};
|
||||||
use inkwell::types::{ArrayType, BasicType, FunctionType, IntType, PointerType, StructType};
|
use inkwell::types::{ArrayType, BasicType, FunctionType, IntType, PointerType, StructType};
|
||||||
use inkwell::AddressSpace;
|
use inkwell::AddressSpace;
|
||||||
use roc_mono::layout::{Builtin, Layout};
|
use roc_mono::layout::{Builtin, Layout, UnionLayout};
|
||||||
|
|
||||||
/// TODO could this be added to Inkwell itself as a method on BasicValueEnum?
|
/// TODO could this be added to Inkwell itself as a method on BasicValueEnum?
|
||||||
pub fn get_ptr_type<'ctx>(
|
pub fn get_ptr_type<'ctx>(
|
||||||
|
@ -132,18 +132,17 @@ pub fn basic_type_from_layout<'ctx>(
|
||||||
.into(),
|
.into(),
|
||||||
PhantomEmptyStruct => context.struct_type(&[], false).into(),
|
PhantomEmptyStruct => context.struct_type(&[], false).into(),
|
||||||
Struct(sorted_fields) => basic_type_from_record(arena, context, sorted_fields, ptr_bytes),
|
Struct(sorted_fields) => basic_type_from_record(arena, context, sorted_fields, ptr_bytes),
|
||||||
// Union(tags) if tags.len() == 1 => {
|
Union(variant) => {
|
||||||
// let sorted_fields = tags.iter().next().unwrap();
|
let block = block_of_memory(context, layout, ptr_bytes);
|
||||||
//
|
|
||||||
// basic_type_from_record(arena, context, sorted_fields, ptr_bytes)
|
use UnionLayout::*;
|
||||||
// }
|
match variant {
|
||||||
RecursiveUnion(_) => block_of_memory(context, layout, ptr_bytes)
|
Recursive(_) | NullableWrapped { .. } => {
|
||||||
.ptr_type(AddressSpace::Generic)
|
block.ptr_type(AddressSpace::Generic).into()
|
||||||
.into(),
|
}
|
||||||
NullableUnion { .. } => block_of_memory(context, layout, ptr_bytes)
|
NonRecursive(_) => block,
|
||||||
.ptr_type(AddressSpace::Generic)
|
}
|
||||||
.into(),
|
}
|
||||||
Union(_) => block_of_memory(context, layout, ptr_bytes),
|
|
||||||
RecursivePointer => {
|
RecursivePointer => {
|
||||||
// TODO make this dynamic
|
// TODO make this dynamic
|
||||||
context
|
context
|
||||||
|
@ -183,20 +182,6 @@ pub fn basic_type_from_builtin<'ctx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block_of_memory_slice<'ctx>(
|
|
||||||
context: &'ctx Context,
|
|
||||||
layouts: &[Layout<'_>],
|
|
||||||
ptr_bytes: u32,
|
|
||||||
) -> BasicTypeEnum<'ctx> {
|
|
||||||
let mut union_size = 0;
|
|
||||||
|
|
||||||
for layout in layouts {
|
|
||||||
union_size += layout.stack_size(ptr_bytes as u32);
|
|
||||||
}
|
|
||||||
|
|
||||||
block_of_memory_help(context, union_size)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn block_of_memory<'ctx>(
|
pub fn block_of_memory<'ctx>(
|
||||||
context: &'ctx Context,
|
context: &'ctx Context,
|
||||||
layout: &Layout<'_>,
|
layout: &Layout<'_>,
|
||||||
|
|
|
@ -12,7 +12,7 @@ use inkwell::types::{AnyTypeEnum, BasicTypeEnum};
|
||||||
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
|
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
|
||||||
use inkwell::{AddressSpace, IntPredicate};
|
use inkwell::{AddressSpace, IntPredicate};
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, MemoryMode};
|
use roc_mono::layout::{Builtin, Layout, LayoutIds, MemoryMode, UnionLayout};
|
||||||
|
|
||||||
pub const REFCOUNT_MAX: usize = 0_usize;
|
pub const REFCOUNT_MAX: usize = 0_usize;
|
||||||
|
|
||||||
|
@ -338,20 +338,28 @@ pub fn decrement_refcount_layout<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
RecursivePointer => todo!("TODO implement decrement layout of recursive tag union"),
|
RecursivePointer => todo!("TODO implement decrement layout of recursive tag union"),
|
||||||
|
|
||||||
Union(tags) => {
|
Union(variant) => {
|
||||||
|
use UnionLayout::*;
|
||||||
|
|
||||||
|
match variant {
|
||||||
|
NonRecursive(tags) => {
|
||||||
build_dec_union(env, layout_ids, tags, value);
|
build_dec_union(env, layout_ids, tags, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
NullableUnion { foo: tags, .. } => {
|
NullableWrapped {
|
||||||
|
other_tags: tags, ..
|
||||||
|
} => {
|
||||||
debug_assert!(value.is_pointer_value());
|
debug_assert!(value.is_pointer_value());
|
||||||
|
|
||||||
build_dec_rec_union(env, layout_ids, tags, value.into_pointer_value(), true);
|
build_dec_rec_union(env, layout_ids, tags, value.into_pointer_value(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecursiveUnion(tags) => {
|
Recursive(tags) => {
|
||||||
debug_assert!(value.is_pointer_value());
|
debug_assert!(value.is_pointer_value());
|
||||||
build_dec_rec_union(env, layout_ids, tags, value.into_pointer_value(), false);
|
build_dec_rec_union(env, layout_ids, tags, value.into_pointer_value(), false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FunctionPointer(_, _) | Pointer(_) => {}
|
FunctionPointer(_, _) | Pointer(_) => {}
|
||||||
}
|
}
|
||||||
|
@ -433,16 +441,28 @@ pub fn increment_refcount_layout<'a, 'ctx, 'env>(
|
||||||
increment_refcount_builtin(env, parent, layout_ids, value, layout, builtin)
|
increment_refcount_builtin(env, parent, layout_ids, value, layout, builtin)
|
||||||
}
|
}
|
||||||
|
|
||||||
NullableUnion { foo: tags, .. } => {
|
Union(variant) => {
|
||||||
|
use UnionLayout::*;
|
||||||
|
|
||||||
|
match variant {
|
||||||
|
NullableWrapped {
|
||||||
|
other_tags: tags, ..
|
||||||
|
} => {
|
||||||
debug_assert!(value.is_pointer_value());
|
debug_assert!(value.is_pointer_value());
|
||||||
|
|
||||||
build_inc_rec_union(env, layout_ids, tags, value.into_pointer_value(), true);
|
build_inc_rec_union(env, layout_ids, tags, value.into_pointer_value(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecursiveUnion(tags) => {
|
Recursive(tags) => {
|
||||||
debug_assert!(value.is_pointer_value());
|
debug_assert!(value.is_pointer_value());
|
||||||
build_inc_rec_union(env, layout_ids, tags, value.into_pointer_value(), false);
|
build_inc_rec_union(env, layout_ids, tags, value.into_pointer_value(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NonRecursive(tags) => {
|
||||||
|
build_inc_union(env, layout_ids, tags, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Closure(_, closure_layout, _) => {
|
Closure(_, closure_layout, _) => {
|
||||||
if closure_layout.contains_refcounted() {
|
if closure_layout.contains_refcounted() {
|
||||||
let wrapper_struct = value.into_struct_value();
|
let wrapper_struct = value.into_struct_value();
|
||||||
|
@ -1053,7 +1073,7 @@ pub fn build_dec_rec_union<'a, 'ctx, 'env>(
|
||||||
value: PointerValue<'ctx>,
|
value: PointerValue<'ctx>,
|
||||||
is_nullable: bool,
|
is_nullable: bool,
|
||||||
) {
|
) {
|
||||||
let layout = Layout::RecursiveUnion(fields);
|
let layout = Layout::Union(UnionLayout::Recursive(fields));
|
||||||
|
|
||||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||||
|
@ -1130,7 +1150,7 @@ pub fn build_dec_rec_union_help<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let parent = fn_val;
|
let parent = fn_val;
|
||||||
|
|
||||||
let layout = Layout::RecursiveUnion(tags);
|
let layout = Layout::Union(UnionLayout::Recursive(tags));
|
||||||
|
|
||||||
debug_assert!(arg_val.is_pointer_value());
|
debug_assert!(arg_val.is_pointer_value());
|
||||||
let value_ptr = arg_val.into_pointer_value();
|
let value_ptr = arg_val.into_pointer_value();
|
||||||
|
@ -1270,7 +1290,7 @@ pub fn build_dec_union<'a, 'ctx, 'env>(
|
||||||
fields: &'a [&'a [Layout<'a>]],
|
fields: &'a [&'a [Layout<'a>]],
|
||||||
value: BasicValueEnum<'ctx>,
|
value: BasicValueEnum<'ctx>,
|
||||||
) {
|
) {
|
||||||
let layout = Layout::Union(fields);
|
let layout = Layout::Union(UnionLayout::NonRecursive(fields));
|
||||||
|
|
||||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||||
|
@ -1435,7 +1455,7 @@ pub fn build_inc_rec_union<'a, 'ctx, 'env>(
|
||||||
value: PointerValue<'ctx>,
|
value: PointerValue<'ctx>,
|
||||||
is_nullable: bool,
|
is_nullable: bool,
|
||||||
) {
|
) {
|
||||||
let layout = Layout::RecursiveUnion(fields);
|
let layout = Layout::Union(UnionLayout::Recursive(fields));
|
||||||
|
|
||||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||||
|
@ -1531,7 +1551,7 @@ pub fn build_inc_rec_union_help<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let parent = fn_val;
|
let parent = fn_val;
|
||||||
|
|
||||||
let layout = Layout::RecursiveUnion(tags);
|
let layout = Layout::Union(UnionLayout::Recursive(tags));
|
||||||
|
|
||||||
debug_assert!(arg_val.is_pointer_value());
|
debug_assert!(arg_val.is_pointer_value());
|
||||||
let value_ptr = arg_val.into_pointer_value();
|
let value_ptr = arg_val.into_pointer_value();
|
||||||
|
@ -1663,7 +1683,7 @@ pub fn build_inc_union<'a, 'ctx, 'env>(
|
||||||
fields: &'a [&'a [Layout<'a>]],
|
fields: &'a [&'a [Layout<'a>]],
|
||||||
value: BasicValueEnum<'ctx>,
|
value: BasicValueEnum<'ctx>,
|
||||||
) {
|
) {
|
||||||
let layout = Layout::Union(fields);
|
let layout = Layout::Union(UnionLayout::NonRecursive(fields));
|
||||||
|
|
||||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||||
|
@ -1737,7 +1757,7 @@ pub fn build_inc_union_help<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let parent = fn_val;
|
let parent = fn_val;
|
||||||
|
|
||||||
let layout = Layout::RecursiveUnion(tags);
|
let layout = Layout::Union(UnionLayout::Recursive(tags));
|
||||||
let before_block = env.builder.get_insert_block().expect("to be in a function");
|
let before_block = env.builder.get_insert_block().expect("to be in a function");
|
||||||
|
|
||||||
let wrapper_struct = arg_val.into_struct_value();
|
let wrapper_struct = arg_val.into_struct_value();
|
||||||
|
@ -1880,9 +1900,7 @@ pub fn refcount_offset<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, layout: &Layou
|
||||||
match layout {
|
match layout {
|
||||||
Layout::Builtin(Builtin::List(_, _)) => env.ptr_bytes as u64,
|
Layout::Builtin(Builtin::List(_, _)) => env.ptr_bytes as u64,
|
||||||
Layout::Builtin(Builtin::Str) => env.ptr_bytes as u64,
|
Layout::Builtin(Builtin::Str) => env.ptr_bytes as u64,
|
||||||
Layout::RecursivePointer | Layout::Union(_) | Layout::RecursiveUnion(_) => {
|
Layout::RecursivePointer | Layout::Union(_) => env.ptr_bytes as u64,
|
||||||
env.ptr_bytes as u64
|
|
||||||
}
|
|
||||||
_ => (env.ptr_bytes as u64).max(value_bytes),
|
_ => (env.ptr_bytes as u64).max(value_bytes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::exhaustive::{Ctor, RenderAs, TagId, Union};
|
||||||
use crate::ir::{
|
use crate::ir::{
|
||||||
DestructType, Env, Expr, JoinPointId, Literal, Param, Pattern, Procs, Stmt, Wrapped,
|
DestructType, Env, Expr, JoinPointId, Literal, Param, Pattern, Procs, Stmt, Wrapped,
|
||||||
};
|
};
|
||||||
use crate::layout::{Builtin, Layout, LayoutCache};
|
use crate::layout::{Builtin, Layout, LayoutCache, UnionLayout};
|
||||||
use roc_collections::all::{MutMap, MutSet};
|
use roc_collections::all::{MutMap, MutSet};
|
||||||
use roc_module::ident::TagName;
|
use roc_module::ident::TagName;
|
||||||
use roc_module::low_level::LowLevel;
|
use roc_module::low_level::LowLevel;
|
||||||
|
@ -228,7 +228,9 @@ fn flatten<'a>(
|
||||||
tag_id,
|
tag_id,
|
||||||
tag_name,
|
tag_name,
|
||||||
layout,
|
layout,
|
||||||
} if union.alternatives.len() == 1 && !matches!(layout, Layout::NullableUnion { .. } ) => {
|
} if union.alternatives.len() == 1
|
||||||
|
&& !matches!(layout, Layout::Union(UnionLayout::NullableWrapped { .. })) =>
|
||||||
|
{
|
||||||
// TODO ^ do we need to check that guard.is_none() here?
|
// TODO ^ do we need to check that guard.is_none() here?
|
||||||
|
|
||||||
let path = path_pattern.0;
|
let path = path_pattern.0;
|
||||||
|
@ -1005,25 +1007,29 @@ fn path_to_expr_help<'a>(
|
||||||
}
|
}
|
||||||
Some(wrapped) => {
|
Some(wrapped) => {
|
||||||
let field_layouts = match &layout {
|
let field_layouts = match &layout {
|
||||||
Layout::Union(layouts) | Layout::RecursiveUnion(layouts) => {
|
Layout::Union(variant) => {
|
||||||
layouts[*tag_id as usize]
|
use UnionLayout::*;
|
||||||
}
|
|
||||||
Layout::NullableUnion {
|
match variant {
|
||||||
|
NonRecursive(layouts) | Recursive(layouts) => layouts[*tag_id as usize],
|
||||||
|
NullableWrapped {
|
||||||
nullable_id,
|
nullable_id,
|
||||||
nullable_layout,
|
nullable_layout,
|
||||||
foo: layouts,
|
other_tags: layouts,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
dbg!(nullable_id, tag_id);
|
dbg!(nullable_id, tag_id);
|
||||||
match (*tag_id as usize).cmp(&(*nullable_id as usize)) {
|
match (*tag_id as usize).cmp(&(*nullable_id as usize)) {
|
||||||
Ordering::Equal => {
|
Ordering::Equal => &*env
|
||||||
&*env.arena.alloc([Layout::Builtin(nullable_layout.clone())])
|
.arena
|
||||||
}
|
.alloc([Layout::Builtin(nullable_layout.clone())]),
|
||||||
Ordering::Less => layouts[*tag_id as usize],
|
Ordering::Less => layouts[*tag_id as usize],
|
||||||
Ordering::Greater => layouts[*tag_id as usize - 1],
|
Ordering::Greater => layouts[*tag_id as usize - 1],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Layout::Struct(layouts) => layouts,
|
Layout::Struct(layouts) => layouts,
|
||||||
other => env.arena.alloc([other.clone()]),
|
other => env.arena.alloc([other.clone()]),
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use self::InProgressProc::*;
|
use self::InProgressProc::*;
|
||||||
use crate::exhaustive::{Ctor, Guard, RenderAs, TagId};
|
use crate::exhaustive::{Ctor, Guard, RenderAs, TagId};
|
||||||
use crate::layout::{
|
use crate::layout::{
|
||||||
Builtin, ClosureLayout, Layout, LayoutCache, LayoutProblem, WrappedVariant, TAG_SIZE,
|
Builtin, ClosureLayout, Layout, LayoutCache, LayoutProblem, UnionLayout, WrappedVariant,
|
||||||
|
TAG_SIZE,
|
||||||
};
|
};
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
@ -820,7 +821,11 @@ impl Wrapped {
|
||||||
_ => Some(Wrapped::RecordOrSingleTagUnion),
|
_ => Some(Wrapped::RecordOrSingleTagUnion),
|
||||||
},
|
},
|
||||||
|
|
||||||
Layout::Union(tags) | Layout::RecursiveUnion(tags) => match tags {
|
Layout::Union(variant) => {
|
||||||
|
use UnionLayout::*;
|
||||||
|
|
||||||
|
match variant {
|
||||||
|
Recursive(tags) | NonRecursive(tags) => match tags {
|
||||||
[] => todo!("how to handle empty tag unions?"),
|
[] => todo!("how to handle empty tag unions?"),
|
||||||
[single] => match single.len() {
|
[single] => match single.len() {
|
||||||
0 => Some(Wrapped::EmptyRecord),
|
0 => Some(Wrapped::EmptyRecord),
|
||||||
|
@ -829,7 +834,9 @@ impl Wrapped {
|
||||||
},
|
},
|
||||||
_ => Some(Wrapped::MultiTagUnion),
|
_ => Some(Wrapped::MultiTagUnion),
|
||||||
},
|
},
|
||||||
Layout::NullableUnion { .. } => Some(Wrapped::MultiTagUnion),
|
NullableWrapped { .. } => Some(Wrapped::MultiTagUnion),
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2742,7 +2749,8 @@ pub fn with_hole<'a>(
|
||||||
layouts.push(arg_layouts);
|
layouts.push(arg_layouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
let layout = Layout::RecursiveUnion(layouts.into_bump_slice());
|
let layout =
|
||||||
|
Layout::Union(UnionLayout::Recursive(layouts.into_bump_slice()));
|
||||||
|
|
||||||
let tag = Expr::Tag {
|
let tag = Expr::Tag {
|
||||||
tag_layout: layout.clone(),
|
tag_layout: layout.clone(),
|
||||||
|
@ -2775,7 +2783,8 @@ pub fn with_hole<'a>(
|
||||||
layouts.push(arg_layouts);
|
layouts.push(arg_layouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
let layout = Layout::Union(layouts.into_bump_slice());
|
let layout =
|
||||||
|
Layout::Union(UnionLayout::NonRecursive(layouts.into_bump_slice()));
|
||||||
|
|
||||||
let tag = Expr::Tag {
|
let tag = Expr::Tag {
|
||||||
tag_layout: layout.clone(),
|
tag_layout: layout.clone(),
|
||||||
|
@ -2812,11 +2821,11 @@ pub fn with_hole<'a>(
|
||||||
layouts.push(arg_layouts);
|
layouts.push(arg_layouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
let layout = Layout::NullableUnion {
|
let layout = Layout::Union(UnionLayout::NullableWrapped {
|
||||||
nullable_id,
|
nullable_id,
|
||||||
nullable_layout: TAG_SIZE,
|
nullable_layout: TAG_SIZE,
|
||||||
foo: layouts.into_bump_slice(),
|
other_tags: layouts.into_bump_slice(),
|
||||||
};
|
});
|
||||||
|
|
||||||
let tag = Expr::Tag {
|
let tag = Expr::Tag {
|
||||||
tag_layout: layout.clone(),
|
tag_layout: layout.clone(),
|
||||||
|
@ -5945,6 +5954,8 @@ fn from_can_pattern_help<'a>(
|
||||||
}
|
}
|
||||||
Wrapped(variant) => {
|
Wrapped(variant) => {
|
||||||
let (tag_id, argument_layouts) = variant.tag_name_to_id(tag_name);
|
let (tag_id, argument_layouts) = variant.tag_name_to_id(tag_name);
|
||||||
|
let number_of_tags = variant.number_of_tags();
|
||||||
|
let mut ctors = std::vec::Vec::with_capacity(number_of_tags);
|
||||||
|
|
||||||
let arguments = {
|
let arguments = {
|
||||||
let mut temp = arguments.clone();
|
let mut temp = arguments.clone();
|
||||||
|
@ -5971,7 +5982,6 @@ fn from_can_pattern_help<'a>(
|
||||||
} => {
|
} => {
|
||||||
debug_assert!(tags.len() > 1);
|
debug_assert!(tags.len() > 1);
|
||||||
|
|
||||||
let mut ctors = std::vec::Vec::with_capacity(tags.len());
|
|
||||||
for (i, (tag_name, args)) in tags.iter().enumerate() {
|
for (i, (tag_name, args)) in tags.iter().enumerate() {
|
||||||
ctors.push(Ctor {
|
ctors.push(Ctor {
|
||||||
tag_id: TagId(i as u8),
|
tag_id: TagId(i as u8),
|
||||||
|
@ -6013,7 +6023,8 @@ fn from_can_pattern_help<'a>(
|
||||||
temp
|
temp
|
||||||
};
|
};
|
||||||
|
|
||||||
let layout = Layout::Union(layouts.into_bump_slice());
|
let layout =
|
||||||
|
Layout::Union(UnionLayout::NonRecursive(layouts.into_bump_slice()));
|
||||||
|
|
||||||
Pattern::AppliedTag {
|
Pattern::AppliedTag {
|
||||||
tag_name: tag_name.clone(),
|
tag_name: tag_name.clone(),
|
||||||
|
@ -6029,7 +6040,6 @@ fn from_can_pattern_help<'a>(
|
||||||
} => {
|
} => {
|
||||||
debug_assert!(tags.len() > 1);
|
debug_assert!(tags.len() > 1);
|
||||||
|
|
||||||
let mut ctors = std::vec::Vec::with_capacity(tags.len());
|
|
||||||
for (i, (tag_name, args)) in tags.iter().enumerate() {
|
for (i, (tag_name, args)) in tags.iter().enumerate() {
|
||||||
ctors.push(Ctor {
|
ctors.push(Ctor {
|
||||||
tag_id: TagId(i as u8),
|
tag_id: TagId(i as u8),
|
||||||
|
@ -6071,7 +6081,8 @@ fn from_can_pattern_help<'a>(
|
||||||
temp
|
temp
|
||||||
};
|
};
|
||||||
|
|
||||||
let layout = Layout::RecursiveUnion(layouts.into_bump_slice());
|
let layout =
|
||||||
|
Layout::Union(UnionLayout::Recursive(layouts.into_bump_slice()));
|
||||||
|
|
||||||
Pattern::AppliedTag {
|
Pattern::AppliedTag {
|
||||||
tag_name: tag_name.clone(),
|
tag_name: tag_name.clone(),
|
||||||
|
@ -6089,8 +6100,6 @@ fn from_can_pattern_help<'a>(
|
||||||
} => {
|
} => {
|
||||||
debug_assert!(!tags.is_empty());
|
debug_assert!(!tags.is_empty());
|
||||||
|
|
||||||
let mut ctors = std::vec::Vec::with_capacity(tags.len());
|
|
||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for (tag_name, args) in tags.iter() {
|
for (tag_name, args) in tags.iter() {
|
||||||
if i == nullable_id as usize {
|
if i == nullable_id as usize {
|
||||||
|
@ -6158,11 +6167,11 @@ fn from_can_pattern_help<'a>(
|
||||||
temp
|
temp
|
||||||
};
|
};
|
||||||
|
|
||||||
let layout = Layout::NullableUnion {
|
let layout = Layout::Union(UnionLayout::NullableWrapped {
|
||||||
nullable_id,
|
nullable_id,
|
||||||
nullable_layout: TAG_SIZE,
|
nullable_layout: TAG_SIZE,
|
||||||
foo: layouts.into_bump_slice(),
|
other_tags: layouts.into_bump_slice(),
|
||||||
};
|
});
|
||||||
|
|
||||||
Pattern::AppliedTag {
|
Pattern::AppliedTag {
|
||||||
tag_name: tag_name.clone(),
|
tag_name: tag_name.clone(),
|
||||||
|
|
|
@ -29,13 +29,7 @@ pub enum Layout<'a> {
|
||||||
/// this is important for closures that capture zero-sized values
|
/// this is important for closures that capture zero-sized values
|
||||||
PhantomEmptyStruct,
|
PhantomEmptyStruct,
|
||||||
Struct(&'a [Layout<'a>]),
|
Struct(&'a [Layout<'a>]),
|
||||||
Union(&'a [&'a [Layout<'a>]]),
|
Union(UnionLayout<'a>),
|
||||||
RecursiveUnion(&'a [&'a [Layout<'a>]]),
|
|
||||||
NullableUnion {
|
|
||||||
nullable_id: i64,
|
|
||||||
nullable_layout: Builtin<'a>,
|
|
||||||
foo: &'a [&'a [Layout<'a>]],
|
|
||||||
},
|
|
||||||
RecursivePointer,
|
RecursivePointer,
|
||||||
/// A function. The types of its arguments, then the type of its return value.
|
/// A function. The types of its arguments, then the type of its return value.
|
||||||
FunctionPointer(&'a [Layout<'a>], &'a Layout<'a>),
|
FunctionPointer(&'a [Layout<'a>], &'a Layout<'a>),
|
||||||
|
@ -43,6 +37,18 @@ pub enum Layout<'a> {
|
||||||
Pointer(&'a Layout<'a>),
|
Pointer(&'a Layout<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum UnionLayout<'a> {
|
||||||
|
NonRecursive(&'a [&'a [Layout<'a>]]),
|
||||||
|
Recursive(&'a [&'a [Layout<'a>]]),
|
||||||
|
NullableWrapped {
|
||||||
|
nullable_id: i64,
|
||||||
|
nullable_layout: Builtin<'a>,
|
||||||
|
other_tags: &'a [&'a [Layout<'a>]],
|
||||||
|
},
|
||||||
|
// NullableUnwrapped,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct ClosureLayout<'a> {
|
pub struct ClosureLayout<'a> {
|
||||||
/// the layout that this specific closure captures
|
/// the layout that this specific closure captures
|
||||||
|
@ -104,7 +110,9 @@ impl<'a> ClosureLayout<'a> {
|
||||||
|
|
||||||
ClosureLayout {
|
ClosureLayout {
|
||||||
captured: tags,
|
captured: tags,
|
||||||
layout: arena.alloc(Layout::Union(tag_arguments.into_bump_slice())),
|
layout: arena.alloc(Layout::Union(UnionLayout::NonRecursive(
|
||||||
|
tag_arguments.into_bump_slice(),
|
||||||
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,7 +281,7 @@ impl<'a> ClosureLayout<'a> {
|
||||||
|
|
||||||
Ok(Expr::Struct(symbols))
|
Ok(Expr::Struct(symbols))
|
||||||
}
|
}
|
||||||
Layout::Union(tags) => {
|
Layout::Union(UnionLayout::NonRecursive(tags)) => {
|
||||||
// NOTE it's very important that this Union consists of Closure tags
|
// NOTE it's very important that this Union consists of Closure tags
|
||||||
// and is not an unpacked 1-element record
|
// and is not an unpacked 1-element record
|
||||||
|
|
||||||
|
@ -284,7 +292,7 @@ impl<'a> ClosureLayout<'a> {
|
||||||
.unwrap() as _;
|
.unwrap() as _;
|
||||||
|
|
||||||
let expr = Expr::Tag {
|
let expr = Expr::Tag {
|
||||||
tag_layout: Layout::Union(tags),
|
tag_layout: Layout::Union(UnionLayout::NonRecursive(tags)),
|
||||||
tag_name: TagName::Closure(original),
|
tag_name: TagName::Closure(original),
|
||||||
tag_id,
|
tag_id,
|
||||||
union_size: tags.len() as u8,
|
union_size: tags.len() as u8,
|
||||||
|
@ -459,17 +467,23 @@ impl<'a> Layout<'a> {
|
||||||
Struct(fields) => fields
|
Struct(fields) => fields
|
||||||
.iter()
|
.iter()
|
||||||
.all(|field_layout| field_layout.safe_to_memcpy()),
|
.all(|field_layout| field_layout.safe_to_memcpy()),
|
||||||
Union(tags) => tags
|
Union(variant) => {
|
||||||
|
use UnionLayout::*;
|
||||||
|
|
||||||
|
match variant {
|
||||||
|
NonRecursive(tags) => tags
|
||||||
.iter()
|
.iter()
|
||||||
.all(|tag_layout| tag_layout.iter().all(|field| field.safe_to_memcpy())),
|
.all(|tag_layout| tag_layout.iter().all(|field| field.safe_to_memcpy())),
|
||||||
RecursiveUnion(_) => {
|
Recursive(_) => {
|
||||||
// a recursive union will always contain a pointer, and is thus not safe to memcpy
|
// a recursive union will always contain a pointer, and is thus not safe to memcpy
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
NullableUnion { .. } => {
|
NullableWrapped { .. } => {
|
||||||
// a nullable union will always contain a pointer, and is thus not safe to memcpy
|
// a nullable union will always contain a pointer, and is thus not safe to memcpy
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
FunctionPointer(_, _) => {
|
FunctionPointer(_, _) => {
|
||||||
// Function pointers are immutable and can always be safely copied
|
// Function pointers are immutable and can always be safely copied
|
||||||
true
|
true
|
||||||
|
@ -513,7 +527,11 @@ impl<'a> Layout<'a> {
|
||||||
|
|
||||||
sum
|
sum
|
||||||
}
|
}
|
||||||
Union(fields) => fields
|
Union(variant) => {
|
||||||
|
use UnionLayout::*;
|
||||||
|
|
||||||
|
match variant {
|
||||||
|
NonRecursive(fields) => fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tag_layout| {
|
.map(|tag_layout| {
|
||||||
tag_layout
|
tag_layout
|
||||||
|
@ -523,7 +541,7 @@ impl<'a> Layout<'a> {
|
||||||
})
|
})
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
RecursiveUnion(fields) => fields
|
Recursive(fields) => fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tag_layout| {
|
.map(|tag_layout| {
|
||||||
tag_layout
|
tag_layout
|
||||||
|
@ -533,7 +551,9 @@ impl<'a> Layout<'a> {
|
||||||
})
|
})
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
NullableUnion { foo: fields, .. } => fields
|
NullableWrapped {
|
||||||
|
other_tags: fields, ..
|
||||||
|
} => fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tag_layout| {
|
.map(|tag_layout| {
|
||||||
tag_layout
|
tag_layout
|
||||||
|
@ -543,6 +563,8 @@ impl<'a> Layout<'a> {
|
||||||
})
|
})
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
Closure(_, closure_layout, _) => pointer_size + closure_layout.stack_size(pointer_size),
|
Closure(_, closure_layout, _) => pointer_size + closure_layout.stack_size(pointer_size),
|
||||||
FunctionPointer(_, _) => pointer_size,
|
FunctionPointer(_, _) => pointer_size,
|
||||||
RecursivePointer => pointer_size,
|
RecursivePointer => pointer_size,
|
||||||
|
@ -557,20 +579,30 @@ impl<'a> Layout<'a> {
|
||||||
.map(|x| x.alignment_bytes(pointer_size))
|
.map(|x| x.alignment_bytes(pointer_size))
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
Layout::Union(tags) => tags
|
|
||||||
|
Layout::Union(variant) => {
|
||||||
|
use UnionLayout::*;
|
||||||
|
|
||||||
|
match variant {
|
||||||
|
NonRecursive(tags) => tags
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.iter())
|
.map(|x| x.iter())
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|x| x.alignment_bytes(pointer_size))
|
.map(|x| x.alignment_bytes(pointer_size))
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
Layout::RecursiveUnion(tags) | Layout::NullableUnion { foo: tags, .. } => tags
|
Recursive(tags)
|
||||||
|
| NullableWrapped {
|
||||||
|
other_tags: tags, ..
|
||||||
|
} => tags
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.iter())
|
.map(|x| x.iter())
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|x| x.alignment_bytes(pointer_size))
|
.map(|x| x.alignment_bytes(pointer_size))
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(pointer_size),
|
.unwrap_or(pointer_size),
|
||||||
|
}
|
||||||
|
}
|
||||||
Layout::Builtin(builtin) => builtin.alignment_bytes(pointer_size),
|
Layout::Builtin(builtin) => builtin.alignment_bytes(pointer_size),
|
||||||
Layout::PhantomEmptyStruct => 0,
|
Layout::PhantomEmptyStruct => 0,
|
||||||
Layout::RecursivePointer => pointer_size,
|
Layout::RecursivePointer => pointer_size,
|
||||||
|
@ -583,7 +615,22 @@ impl<'a> Layout<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_refcounted(&self) -> bool {
|
pub fn is_refcounted(&self) -> bool {
|
||||||
matches!(self, Layout::Builtin(Builtin::List(MemoryMode::Refcounted, _)) | Layout::Builtin(Builtin::Str) | Layout::RecursiveUnion(_) | Layout::RecursivePointer | Layout::NullableUnion { .. })
|
use self::Builtin::*;
|
||||||
|
use Layout::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Union(variant) => {
|
||||||
|
use UnionLayout::*;
|
||||||
|
|
||||||
|
matches!(variant, Recursive(_)| NullableWrapped { .. } )
|
||||||
|
}
|
||||||
|
|
||||||
|
RecursivePointer => true,
|
||||||
|
|
||||||
|
Builtin(List(MemoryMode::Refcounted, _)) | Builtin(Str) => true,
|
||||||
|
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Even if a value (say, a record) is not itself reference counted,
|
/// Even if a value (say, a record) is not itself reference counted,
|
||||||
|
@ -596,13 +643,19 @@ impl<'a> Layout<'a> {
|
||||||
Builtin(builtin) => builtin.is_refcounted(),
|
Builtin(builtin) => builtin.is_refcounted(),
|
||||||
PhantomEmptyStruct => false,
|
PhantomEmptyStruct => false,
|
||||||
Struct(fields) => fields.iter().any(|f| f.contains_refcounted()),
|
Struct(fields) => fields.iter().any(|f| f.contains_refcounted()),
|
||||||
Union(fields) => fields
|
Union(variant) => {
|
||||||
|
use UnionLayout::*;
|
||||||
|
|
||||||
|
match variant {
|
||||||
|
NonRecursive(fields) => fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|ls| ls.iter())
|
.map(|ls| ls.iter())
|
||||||
.flatten()
|
.flatten()
|
||||||
.any(|f| f.contains_refcounted()),
|
.any(|f| f.contains_refcounted()),
|
||||||
RecursiveUnion(_) => true,
|
Recursive(_) => true,
|
||||||
NullableUnion { .. } => true,
|
NullableWrapped { .. } => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
Closure(_, closure_layout, _) => closure_layout.contains_refcounted(),
|
Closure(_, closure_layout, _) => closure_layout.contains_refcounted(),
|
||||||
FunctionPointer(_, _) | RecursivePointer | Pointer(_) => false,
|
FunctionPointer(_, _) | RecursivePointer | Pointer(_) => false,
|
||||||
}
|
}
|
||||||
|
@ -1067,15 +1120,17 @@ fn layout_from_flat_type<'a>(
|
||||||
tag_layouts.push(tag_layout.into_bump_slice());
|
tag_layouts.push(tag_layout.into_bump_slice());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((tag_id, tag_id_layout)) = nullable {
|
let union_layout = if let Some((tag_id, tag_id_layout)) = nullable {
|
||||||
Ok(Layout::NullableUnion {
|
UnionLayout::NullableWrapped {
|
||||||
nullable_id: tag_id,
|
nullable_id: tag_id,
|
||||||
nullable_layout: tag_id_layout,
|
nullable_layout: tag_id_layout,
|
||||||
foo: tag_layouts.into_bump_slice(),
|
other_tags: tag_layouts.into_bump_slice(),
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Ok(Layout::RecursiveUnion(tag_layouts.into_bump_slice()))
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
UnionLayout::Recursive(tag_layouts.into_bump_slice())
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Layout::Union(union_layout))
|
||||||
}
|
}
|
||||||
EmptyTagUnion => {
|
EmptyTagUnion => {
|
||||||
panic!("TODO make Layout for empty Tag Union");
|
panic!("TODO make Layout for empty Tag Union");
|
||||||
|
@ -1500,7 +1555,7 @@ pub fn layout_from_tag_union<'a>(
|
||||||
let variant = union_sorted_tags_help(arena, tags_vec, opt_rec_var, subs);
|
let variant = union_sorted_tags_help(arena, tags_vec, opt_rec_var, subs);
|
||||||
|
|
||||||
match variant {
|
match variant {
|
||||||
Never => Layout::Union(&[]),
|
Never => Layout::Union(UnionLayout::NonRecursive(&[])),
|
||||||
Unit | UnitWithArguments => Layout::Struct(&[]),
|
Unit | UnitWithArguments => Layout::Struct(&[]),
|
||||||
BoolUnion { .. } => Layout::Builtin(Builtin::Int1),
|
BoolUnion { .. } => Layout::Builtin(Builtin::Int1),
|
||||||
ByteUnion(_) => Layout::Builtin(Builtin::Int8),
|
ByteUnion(_) => Layout::Builtin(Builtin::Int8),
|
||||||
|
@ -1521,7 +1576,7 @@ pub fn layout_from_tag_union<'a>(
|
||||||
let mut tag_layouts = Vec::with_capacity_in(tags.len(), arena);
|
let mut tag_layouts = Vec::with_capacity_in(tags.len(), arena);
|
||||||
tag_layouts.extend(tags.iter().map(|r| r.1));
|
tag_layouts.extend(tags.iter().map(|r| r.1));
|
||||||
|
|
||||||
Layout::Union(tag_layouts.into_bump_slice())
|
Layout::Union(UnionLayout::NonRecursive(tag_layouts.into_bump_slice()))
|
||||||
}
|
}
|
||||||
|
|
||||||
Recursive {
|
Recursive {
|
||||||
|
@ -1530,7 +1585,7 @@ pub fn layout_from_tag_union<'a>(
|
||||||
let mut tag_layouts = Vec::with_capacity_in(tags.len(), arena);
|
let mut tag_layouts = Vec::with_capacity_in(tags.len(), arena);
|
||||||
tag_layouts.extend(tags.iter().map(|r| r.1));
|
tag_layouts.extend(tags.iter().map(|r| r.1));
|
||||||
|
|
||||||
Layout::RecursiveUnion(tag_layouts.into_bump_slice())
|
Layout::Union(UnionLayout::Recursive(tag_layouts.into_bump_slice()))
|
||||||
}
|
}
|
||||||
|
|
||||||
NullableWrapped {
|
NullableWrapped {
|
||||||
|
@ -1541,11 +1596,11 @@ pub fn layout_from_tag_union<'a>(
|
||||||
let mut tag_layouts = Vec::with_capacity_in(tags.len(), arena);
|
let mut tag_layouts = Vec::with_capacity_in(tags.len(), arena);
|
||||||
tag_layouts.extend(tags.iter().map(|r| r.1));
|
tag_layouts.extend(tags.iter().map(|r| r.1));
|
||||||
|
|
||||||
Layout::NullableUnion {
|
Layout::Union(UnionLayout::NullableWrapped {
|
||||||
nullable_id,
|
nullable_id,
|
||||||
nullable_layout: TAG_SIZE,
|
nullable_layout: TAG_SIZE,
|
||||||
foo: tag_layouts.into_bump_slice(),
|
other_tags: tag_layouts.into_bump_slice(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
NullableUnwrapped { .. } => todo!(),
|
NullableUnwrapped { .. } => todo!(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue