mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Deal with recursive pointers that pass through non-recursive layouts
This commit is contained in:
parent
92dfccedff
commit
02d5cd7885
6 changed files with 203 additions and 105 deletions
|
@ -279,7 +279,8 @@ fn build_entry_point(
|
||||||
let block = builder.add_block();
|
let block = builder.add_block();
|
||||||
|
|
||||||
// to the modelling language, the arguments appear out of thin air
|
// to the modelling language, the arguments appear out of thin air
|
||||||
let argument_type = build_tuple_type(&mut builder, layout.arguments)?;
|
let argument_type =
|
||||||
|
build_tuple_type(&mut builder, layout.arguments, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
// does not make any assumptions about the input
|
// does not make any assumptions about the input
|
||||||
// let argument = builder.add_unknown_with(block, &[], argument_type)?;
|
// let argument = builder.add_unknown_with(block, &[], argument_type)?;
|
||||||
|
@ -308,7 +309,11 @@ fn build_entry_point(
|
||||||
|
|
||||||
let block = builder.add_block();
|
let block = builder.add_block();
|
||||||
|
|
||||||
let type_id = layout_spec(&mut builder, &Layout::struct_no_name_order(layouts))?;
|
let type_id = layout_spec(
|
||||||
|
&mut builder,
|
||||||
|
&Layout::struct_no_name_order(layouts),
|
||||||
|
&WhenRecursive::Unreachable,
|
||||||
|
)?;
|
||||||
|
|
||||||
let argument = builder.add_unknown_with(block, &[], type_id)?;
|
let argument = builder.add_unknown_with(block, &[], type_id)?;
|
||||||
|
|
||||||
|
@ -352,8 +357,9 @@ fn proc_spec<'a>(proc: &Proc<'a>) -> Result<(FuncDef, MutSet<UnionLayout<'a>>)>
|
||||||
let arg_type_id = layout_spec(
|
let arg_type_id = layout_spec(
|
||||||
&mut builder,
|
&mut builder,
|
||||||
&Layout::struct_no_name_order(&argument_layouts),
|
&Layout::struct_no_name_order(&argument_layouts),
|
||||||
|
&WhenRecursive::Unreachable,
|
||||||
)?;
|
)?;
|
||||||
let ret_type_id = layout_spec(&mut builder, &proc.ret_layout)?;
|
let ret_type_id = layout_spec(&mut builder, &proc.ret_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let spec = builder.build(arg_type_id, ret_type_id, root)?;
|
let spec = builder.build(arg_type_id, ret_type_id, root)?;
|
||||||
|
|
||||||
|
@ -457,10 +463,14 @@ fn stmt_spec<'a>(
|
||||||
let mut type_ids = Vec::new();
|
let mut type_ids = Vec::new();
|
||||||
|
|
||||||
for p in parameters.iter() {
|
for p in parameters.iter() {
|
||||||
type_ids.push(layout_spec(builder, &p.layout)?);
|
type_ids.push(layout_spec(
|
||||||
|
builder,
|
||||||
|
&p.layout,
|
||||||
|
&WhenRecursive::Unreachable,
|
||||||
|
)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ret_type_id = layout_spec(builder, layout)?;
|
let ret_type_id = layout_spec(builder, layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let jp_arg_type_id = builder.add_tuple_type(&type_ids)?;
|
let jp_arg_type_id = builder.add_tuple_type(&type_ids)?;
|
||||||
|
|
||||||
|
@ -500,14 +510,14 @@ fn stmt_spec<'a>(
|
||||||
builder.add_sub_block(block, BlockExpr(cont_block, cont_value_id))
|
builder.add_sub_block(block, BlockExpr(cont_block, cont_value_id))
|
||||||
}
|
}
|
||||||
Jump(id, symbols) => {
|
Jump(id, symbols) => {
|
||||||
let ret_type_id = layout_spec(builder, layout)?;
|
let ret_type_id = layout_spec(builder, layout, &WhenRecursive::Unreachable)?;
|
||||||
let argument = build_tuple_value(builder, env, block, symbols)?;
|
let argument = build_tuple_value(builder, env, block, symbols)?;
|
||||||
|
|
||||||
let jpid = env.join_points[id];
|
let jpid = env.join_points[id];
|
||||||
builder.add_jump(block, jpid, argument, ret_type_id)
|
builder.add_jump(block, jpid, argument, ret_type_id)
|
||||||
}
|
}
|
||||||
RuntimeError(_) => {
|
RuntimeError(_) => {
|
||||||
let type_id = layout_spec(builder, layout)?;
|
let type_id = layout_spec(builder, layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
builder.add_terminate(block, type_id)
|
builder.add_terminate(block, type_id)
|
||||||
}
|
}
|
||||||
|
@ -556,11 +566,15 @@ fn build_recursive_tuple_type(
|
||||||
builder.add_tuple_type(&field_types)
|
builder.add_tuple_type(&field_types)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_tuple_type(builder: &mut impl TypeContext, layouts: &[Layout]) -> Result<TypeId> {
|
fn build_tuple_type(
|
||||||
|
builder: &mut impl TypeContext,
|
||||||
|
layouts: &[Layout],
|
||||||
|
when_recursive: &WhenRecursive,
|
||||||
|
) -> Result<TypeId> {
|
||||||
let mut field_types = Vec::new();
|
let mut field_types = Vec::new();
|
||||||
|
|
||||||
for field in layouts.iter() {
|
for field in layouts.iter() {
|
||||||
field_types.push(layout_spec(builder, field)?);
|
field_types.push(layout_spec(builder, field, when_recursive)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.add_tuple_type(&field_types)
|
builder.add_tuple_type(&field_types)
|
||||||
|
@ -691,7 +705,7 @@ fn call_spec(
|
||||||
.map(|symbol| env.symbols[symbol])
|
.map(|symbol| env.symbols[symbol])
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let result_type = layout_spec(builder, ret_layout)?;
|
let result_type = layout_spec(builder, ret_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
builder.add_unknown_with(block, &arguments, result_type)
|
builder.add_unknown_with(block, &arguments, result_type)
|
||||||
}
|
}
|
||||||
|
@ -761,7 +775,8 @@ fn call_spec(
|
||||||
};
|
};
|
||||||
|
|
||||||
let state_layout = argument_layouts[0];
|
let state_layout = argument_layouts[0];
|
||||||
let state_type = layout_spec(builder, &state_layout)?;
|
let state_type =
|
||||||
|
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
|
||||||
let init_state = state;
|
let init_state = state;
|
||||||
|
|
||||||
add_loop(builder, block, state_type, init_state, loop_body)
|
add_loop(builder, block, state_type, init_state, loop_body)
|
||||||
|
@ -782,7 +797,8 @@ fn call_spec(
|
||||||
};
|
};
|
||||||
|
|
||||||
let state_layout = argument_layouts[0];
|
let state_layout = argument_layouts[0];
|
||||||
let state_type = layout_spec(builder, &state_layout)?;
|
let state_type =
|
||||||
|
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
|
||||||
let init_state = state;
|
let init_state = state;
|
||||||
|
|
||||||
add_loop(builder, block, state_type, init_state, loop_body)
|
add_loop(builder, block, state_type, init_state, loop_body)
|
||||||
|
@ -806,7 +822,8 @@ fn call_spec(
|
||||||
};
|
};
|
||||||
|
|
||||||
let state_layout = argument_layouts[0];
|
let state_layout = argument_layouts[0];
|
||||||
let state_type = layout_spec(builder, &state_layout)?;
|
let state_type =
|
||||||
|
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
|
||||||
let init_state = state;
|
let init_state = state;
|
||||||
|
|
||||||
add_loop(builder, block, state_type, init_state, loop_body)
|
add_loop(builder, block, state_type, init_state, loop_body)
|
||||||
|
@ -828,10 +845,12 @@ fn call_spec(
|
||||||
list_append(builder, block, update_mode_var, state, new_element)
|
list_append(builder, block, update_mode_var, state, new_element)
|
||||||
};
|
};
|
||||||
|
|
||||||
let output_element_type = layout_spec(builder, return_layout)?;
|
let output_element_type =
|
||||||
|
layout_spec(builder, return_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let state_layout = Layout::Builtin(Builtin::List(return_layout));
|
let state_layout = Layout::Builtin(Builtin::List(return_layout));
|
||||||
let state_type = layout_spec(builder, &state_layout)?;
|
let state_type =
|
||||||
|
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let init_state = new_list(builder, block, output_element_type)?;
|
let init_state = new_list(builder, block, output_element_type)?;
|
||||||
|
|
||||||
|
@ -851,10 +870,12 @@ fn call_spec(
|
||||||
list_append(builder, block, update_mode_var, state, new_element)
|
list_append(builder, block, update_mode_var, state, new_element)
|
||||||
};
|
};
|
||||||
|
|
||||||
let output_element_type = layout_spec(builder, return_layout)?;
|
let output_element_type =
|
||||||
|
layout_spec(builder, return_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let state_layout = Layout::Builtin(Builtin::List(return_layout));
|
let state_layout = Layout::Builtin(Builtin::List(return_layout));
|
||||||
let state_type = layout_spec(builder, &state_layout)?;
|
let state_type =
|
||||||
|
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let init_state = new_list(builder, block, output_element_type)?;
|
let init_state = new_list(builder, block, output_element_type)?;
|
||||||
|
|
||||||
|
@ -879,7 +900,8 @@ fn call_spec(
|
||||||
};
|
};
|
||||||
|
|
||||||
let state_layout = Layout::Builtin(Builtin::List(&argument_layouts[0]));
|
let state_layout = Layout::Builtin(Builtin::List(&argument_layouts[0]));
|
||||||
let state_type = layout_spec(builder, &state_layout)?;
|
let state_type =
|
||||||
|
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
|
||||||
let init_state = list;
|
let init_state = list;
|
||||||
|
|
||||||
add_loop(builder, block, state_type, init_state, loop_body)
|
add_loop(builder, block, state_type, init_state, loop_body)
|
||||||
|
@ -903,10 +925,12 @@ fn call_spec(
|
||||||
list_append(builder, block, update_mode_var, state, new_element)
|
list_append(builder, block, update_mode_var, state, new_element)
|
||||||
};
|
};
|
||||||
|
|
||||||
let output_element_type = layout_spec(builder, return_layout)?;
|
let output_element_type =
|
||||||
|
layout_spec(builder, return_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let state_layout = Layout::Builtin(Builtin::List(return_layout));
|
let state_layout = Layout::Builtin(Builtin::List(return_layout));
|
||||||
let state_type = layout_spec(builder, &state_layout)?;
|
let state_type =
|
||||||
|
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let init_state = new_list(builder, block, output_element_type)?;
|
let init_state = new_list(builder, block, output_element_type)?;
|
||||||
|
|
||||||
|
@ -936,10 +960,12 @@ fn call_spec(
|
||||||
list_append(builder, block, update_mode_var, state, new_element)
|
list_append(builder, block, update_mode_var, state, new_element)
|
||||||
};
|
};
|
||||||
|
|
||||||
let output_element_type = layout_spec(builder, return_layout)?;
|
let output_element_type =
|
||||||
|
layout_spec(builder, return_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let state_layout = Layout::Builtin(Builtin::List(return_layout));
|
let state_layout = Layout::Builtin(Builtin::List(return_layout));
|
||||||
let state_type = layout_spec(builder, &state_layout)?;
|
let state_type =
|
||||||
|
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let init_state = new_list(builder, block, output_element_type)?;
|
let init_state = new_list(builder, block, output_element_type)?;
|
||||||
|
|
||||||
|
@ -975,10 +1001,12 @@ fn call_spec(
|
||||||
list_append(builder, block, update_mode_var, state, new_element)
|
list_append(builder, block, update_mode_var, state, new_element)
|
||||||
};
|
};
|
||||||
|
|
||||||
let output_element_type = layout_spec(builder, return_layout)?;
|
let output_element_type =
|
||||||
|
layout_spec(builder, return_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let state_layout = Layout::Builtin(Builtin::List(return_layout));
|
let state_layout = Layout::Builtin(Builtin::List(return_layout));
|
||||||
let state_type = layout_spec(builder, &state_layout)?;
|
let state_type =
|
||||||
|
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let init_state = new_list(builder, block, output_element_type)?;
|
let init_state = new_list(builder, block, output_element_type)?;
|
||||||
|
|
||||||
|
@ -1010,7 +1038,8 @@ fn call_spec(
|
||||||
};
|
};
|
||||||
|
|
||||||
let state_layout = Layout::Builtin(Builtin::List(&argument_layouts[0]));
|
let state_layout = Layout::Builtin(Builtin::List(&argument_layouts[0]));
|
||||||
let state_type = layout_spec(builder, &state_layout)?;
|
let state_type =
|
||||||
|
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
|
||||||
let init_state = list;
|
let init_state = list;
|
||||||
|
|
||||||
add_loop(builder, block, state_type, init_state, loop_body)
|
add_loop(builder, block, state_type, init_state, loop_body)
|
||||||
|
@ -1087,11 +1116,13 @@ fn call_spec(
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let output_element_type = layout_spec(builder, &output_element_layout)?;
|
let output_element_type =
|
||||||
|
layout_spec(builder, &output_element_layout, &WhenRecursive::Unreachable)?;
|
||||||
let init_state = new_list(builder, block, output_element_type)?;
|
let init_state = new_list(builder, block, output_element_type)?;
|
||||||
|
|
||||||
let state_layout = Layout::Builtin(Builtin::List(&output_element_layout));
|
let state_layout = Layout::Builtin(Builtin::List(&output_element_layout));
|
||||||
let state_type = layout_spec(builder, &state_layout)?;
|
let state_type =
|
||||||
|
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
add_loop(builder, block, state_type, init_state, loop_body)
|
add_loop(builder, block, state_type, init_state, loop_body)
|
||||||
}
|
}
|
||||||
|
@ -1108,7 +1139,8 @@ fn call_spec(
|
||||||
};
|
};
|
||||||
|
|
||||||
let state_layout = Layout::Builtin(Builtin::Bool);
|
let state_layout = Layout::Builtin(Builtin::Bool);
|
||||||
let state_type = layout_spec(builder, &state_layout)?;
|
let state_type =
|
||||||
|
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let init_state = new_num(builder, block)?;
|
let init_state = new_num(builder, block)?;
|
||||||
|
|
||||||
|
@ -1127,7 +1159,8 @@ fn call_spec(
|
||||||
};
|
};
|
||||||
|
|
||||||
let state_layout = Layout::Builtin(Builtin::Bool);
|
let state_layout = Layout::Builtin(Builtin::Bool);
|
||||||
let state_type = layout_spec(builder, &state_layout)?;
|
let state_type =
|
||||||
|
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let init_state = new_num(builder, block)?;
|
let init_state = new_num(builder, block)?;
|
||||||
|
|
||||||
|
@ -1139,7 +1172,8 @@ fn call_spec(
|
||||||
// ListFindUnsafe returns { value: v, found: Bool=Int1 }
|
// ListFindUnsafe returns { value: v, found: Bool=Int1 }
|
||||||
let output_layouts = vec![argument_layouts[0], Layout::Builtin(Builtin::Bool)];
|
let output_layouts = vec![argument_layouts[0], Layout::Builtin(Builtin::Bool)];
|
||||||
let output_layout = Layout::struct_no_name_order(&output_layouts);
|
let output_layout = Layout::struct_no_name_order(&output_layouts);
|
||||||
let output_type = layout_spec(builder, &output_layout)?;
|
let output_type =
|
||||||
|
layout_spec(builder, &output_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let loop_body = |builder: &mut FuncDefBuilder, block, output| {
|
let loop_body = |builder: &mut FuncDefBuilder, block, output| {
|
||||||
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
|
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
|
||||||
|
@ -1201,7 +1235,7 @@ fn lowlevel_spec(
|
||||||
) -> Result<ValueId> {
|
) -> Result<ValueId> {
|
||||||
use LowLevel::*;
|
use LowLevel::*;
|
||||||
|
|
||||||
let type_id = layout_spec(builder, layout)?;
|
let type_id = layout_spec(builder, layout, &WhenRecursive::Unreachable)?;
|
||||||
let mode = update_mode.to_bytes();
|
let mode = update_mode.to_bytes();
|
||||||
let update_mode_var = UpdateModeVar(&mode);
|
let update_mode_var = UpdateModeVar(&mode);
|
||||||
|
|
||||||
|
@ -1323,8 +1357,8 @@ fn lowlevel_spec(
|
||||||
}
|
}
|
||||||
DictEmpty => match layout {
|
DictEmpty => match layout {
|
||||||
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
|
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
|
||||||
let key_id = layout_spec(builder, key_layout)?;
|
let key_id = layout_spec(builder, key_layout, &WhenRecursive::Unreachable)?;
|
||||||
let value_id = layout_spec(builder, value_layout)?;
|
let value_id = layout_spec(builder, value_layout, &WhenRecursive::Unreachable)?;
|
||||||
new_dict(builder, block, key_id, value_id)
|
new_dict(builder, block, key_id, value_id)
|
||||||
}
|
}
|
||||||
_ => unreachable!("empty array does not have a list layout"),
|
_ => unreachable!("empty array does not have a list layout"),
|
||||||
|
@ -1367,7 +1401,7 @@ fn lowlevel_spec(
|
||||||
// TODO overly pessimstic
|
// TODO overly pessimstic
|
||||||
let arguments: Vec<_> = arguments.iter().map(|symbol| env.symbols[symbol]).collect();
|
let arguments: Vec<_> = arguments.iter().map(|symbol| env.symbols[symbol]).collect();
|
||||||
|
|
||||||
let result_type = layout_spec(builder, layout)?;
|
let result_type = layout_spec(builder, layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
builder.add_unknown_with(block, &arguments, result_type)
|
builder.add_unknown_with(block, &arguments, result_type)
|
||||||
}
|
}
|
||||||
|
@ -1478,7 +1512,8 @@ fn expr_spec<'a>(
|
||||||
|
|
||||||
let value_id = match tag_layout {
|
let value_id = match tag_layout {
|
||||||
UnionLayout::NonRecursive(tags) => {
|
UnionLayout::NonRecursive(tags) => {
|
||||||
let variant_types = non_recursive_variant_types(builder, tags)?;
|
let variant_types =
|
||||||
|
non_recursive_variant_types(builder, tags, &WhenRecursive::Unreachable)?;
|
||||||
let value_id = build_tuple_value(builder, env, block, arguments)?;
|
let value_id = build_tuple_value(builder, env, block, arguments)?;
|
||||||
return builder.add_make_union(block, &variant_types, *tag_id as u32, value_id);
|
return builder.add_make_union(block, &variant_types, *tag_id as u32, value_id);
|
||||||
}
|
}
|
||||||
|
@ -1592,7 +1627,7 @@ fn expr_spec<'a>(
|
||||||
builder.add_get_tuple_field(block, value_id, *index as u32)
|
builder.add_get_tuple_field(block, value_id, *index as u32)
|
||||||
}
|
}
|
||||||
Array { elem_layout, elems } => {
|
Array { elem_layout, elems } => {
|
||||||
let type_id = layout_spec(builder, elem_layout)?;
|
let type_id = layout_spec(builder, elem_layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
let list = new_list(builder, block, type_id)?;
|
let list = new_list(builder, block, type_id)?;
|
||||||
|
|
||||||
|
@ -1619,19 +1654,19 @@ fn expr_spec<'a>(
|
||||||
|
|
||||||
EmptyArray => match layout {
|
EmptyArray => match layout {
|
||||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||||
let type_id = layout_spec(builder, element_layout)?;
|
let type_id = layout_spec(builder, element_layout, &WhenRecursive::Unreachable)?;
|
||||||
new_list(builder, block, type_id)
|
new_list(builder, block, type_id)
|
||||||
}
|
}
|
||||||
_ => unreachable!("empty array does not have a list layout"),
|
_ => unreachable!("empty array does not have a list layout"),
|
||||||
},
|
},
|
||||||
Reset { symbol, .. } => {
|
Reset { symbol, .. } => {
|
||||||
let type_id = layout_spec(builder, layout)?;
|
let type_id = layout_spec(builder, layout, &WhenRecursive::Unreachable)?;
|
||||||
let value_id = env.symbols[symbol];
|
let value_id = env.symbols[symbol];
|
||||||
|
|
||||||
builder.add_unknown_with(block, &[value_id], type_id)
|
builder.add_unknown_with(block, &[value_id], type_id)
|
||||||
}
|
}
|
||||||
RuntimeErrorFunction(_) => {
|
RuntimeErrorFunction(_) => {
|
||||||
let type_id = layout_spec(builder, layout)?;
|
let type_id = layout_spec(builder, layout, &WhenRecursive::Unreachable)?;
|
||||||
|
|
||||||
builder.add_terminate(block, type_id)
|
builder.add_terminate(block, type_id)
|
||||||
}
|
}
|
||||||
|
@ -1658,18 +1693,24 @@ fn literal_spec(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_spec(builder: &mut impl TypeContext, layout: &Layout) -> Result<TypeId> {
|
fn layout_spec(
|
||||||
layout_spec_help(builder, layout, &WhenRecursive::Unreachable)
|
builder: &mut impl TypeContext,
|
||||||
|
layout: &Layout,
|
||||||
|
when_recursive: &WhenRecursive,
|
||||||
|
) -> Result<TypeId> {
|
||||||
|
layout_spec_help(builder, layout, when_recursive)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn non_recursive_variant_types(
|
fn non_recursive_variant_types(
|
||||||
builder: &mut impl TypeContext,
|
builder: &mut impl TypeContext,
|
||||||
tags: &[&[Layout]],
|
tags: &[&[Layout]],
|
||||||
|
// If there is a recursive pointer latent within this layout, coming from a containing layout.
|
||||||
|
when_recursive: &WhenRecursive,
|
||||||
) -> Result<Vec<TypeId>> {
|
) -> Result<Vec<TypeId>> {
|
||||||
let mut result = Vec::with_capacity(tags.len());
|
let mut result = Vec::with_capacity(tags.len());
|
||||||
|
|
||||||
for tag in tags.iter() {
|
for tag in tags.iter() {
|
||||||
result.push(build_tuple_type(builder, tag)?);
|
result.push(build_tuple_type(builder, tag, when_recursive)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
|
@ -1701,7 +1742,7 @@ fn layout_spec_help(
|
||||||
builder.add_tuple_type(&[])
|
builder.add_tuple_type(&[])
|
||||||
}
|
}
|
||||||
UnionLayout::NonRecursive(tags) => {
|
UnionLayout::NonRecursive(tags) => {
|
||||||
let variant_types = non_recursive_variant_types(builder, tags)?;
|
let variant_types = non_recursive_variant_types(builder, tags, when_recursive)?;
|
||||||
builder.add_union_type(&variant_types)
|
builder.add_union_type(&variant_types)
|
||||||
}
|
}
|
||||||
UnionLayout::Recursive(_)
|
UnionLayout::Recursive(_)
|
||||||
|
|
|
@ -1809,7 +1809,39 @@ fn modify_refcount_union_help<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
for (i, field_layout) in field_layouts.iter().enumerate() {
|
for (i, field_layout) in field_layouts.iter().enumerate() {
|
||||||
if let Layout::RecursivePointer = field_layout {
|
if let Layout::RecursivePointer = field_layout {
|
||||||
panic!("non-recursive tag unions cannot contain naked recursion pointers!");
|
let recursive_union_layout = match when_recursive {
|
||||||
|
WhenRecursive::Unreachable => {
|
||||||
|
panic!("non-recursive tag unions cannot contain naked recursion pointers!");
|
||||||
|
}
|
||||||
|
WhenRecursive::Loop(recursive_union_layout) => recursive_union_layout,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This field is a pointer to the recursive pointer.
|
||||||
|
let field_ptr = env
|
||||||
|
.builder
|
||||||
|
.build_struct_gep(cast_tag_data_pointer, i as u32, "modify_tag_field")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// This is the actual pointer to the recursive data.
|
||||||
|
let field_value = env.builder.build_load(field_ptr, "load_recursive_pointer");
|
||||||
|
|
||||||
|
debug_assert!(field_value.is_pointer_value());
|
||||||
|
|
||||||
|
// therefore we must cast it to our desired type
|
||||||
|
let union_type =
|
||||||
|
basic_type_from_layout(env, &Layout::Union(*recursive_union_layout));
|
||||||
|
let recursive_ptr_field_value =
|
||||||
|
cast_basic_basic(env.builder, field_value, union_type);
|
||||||
|
|
||||||
|
modify_refcount_layout_help(
|
||||||
|
env,
|
||||||
|
parent,
|
||||||
|
layout_ids,
|
||||||
|
mode.to_call_mode(fn_val),
|
||||||
|
when_recursive,
|
||||||
|
recursive_ptr_field_value,
|
||||||
|
&Layout::RecursivePointer,
|
||||||
|
)
|
||||||
} else if field_layout.contains_refcounted() {
|
} else if field_layout.contains_refcounted() {
|
||||||
let field_ptr = env
|
let field_ptr = env
|
||||||
.builder
|
.builder
|
||||||
|
|
|
@ -78,7 +78,7 @@ impl<'a> RawFunctionLayout<'a> {
|
||||||
let structure_content = env.subs.get_content_without_compacting(structure);
|
let structure_content = env.subs.get_content_without_compacting(structure);
|
||||||
Self::new_help(env, structure, *structure_content)
|
Self::new_help(env, structure, *structure_content)
|
||||||
}
|
}
|
||||||
Structure(flat_type) => Self::layout_from_flat_type(env, flat_type),
|
Structure(flat_type) => Self::layout_from_flat_type(env, var, flat_type),
|
||||||
RangedNumber(typ, _) => Self::from_var(env, typ),
|
RangedNumber(typ, _) => Self::from_var(env, typ),
|
||||||
|
|
||||||
// Ints
|
// Ints
|
||||||
|
@ -152,6 +152,7 @@ impl<'a> RawFunctionLayout<'a> {
|
||||||
|
|
||||||
fn layout_from_flat_type(
|
fn layout_from_flat_type(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
|
var: Variable,
|
||||||
flat_type: FlatType,
|
flat_type: FlatType,
|
||||||
) -> Result<Self, LayoutProblem> {
|
) -> Result<Self, LayoutProblem> {
|
||||||
use roc_types::subs::FlatType::*;
|
use roc_types::subs::FlatType::*;
|
||||||
|
@ -195,7 +196,7 @@ impl<'a> RawFunctionLayout<'a> {
|
||||||
Self::from_var(env, var)
|
Self::from_var(env, var)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let layout = layout_from_flat_type(env, flat_type)?;
|
let layout = layout_from_flat_type(env, var, flat_type)?;
|
||||||
Ok(Self::ZeroArgumentThunk(layout))
|
Ok(Self::ZeroArgumentThunk(layout))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -959,7 +960,7 @@ impl<'a> Layout<'a> {
|
||||||
let structure_content = env.subs.get_content_without_compacting(structure);
|
let structure_content = env.subs.get_content_without_compacting(structure);
|
||||||
Self::new_help(env, structure, *structure_content)
|
Self::new_help(env, structure, *structure_content)
|
||||||
}
|
}
|
||||||
Structure(flat_type) => layout_from_flat_type(env, flat_type),
|
Structure(flat_type) => layout_from_flat_type(env, var, flat_type),
|
||||||
|
|
||||||
Alias(symbol, _args, actual_var, _) => {
|
Alias(symbol, _args, actual_var, _) => {
|
||||||
if let Some(int_width) = IntWidth::try_from_symbol(symbol) {
|
if let Some(int_width) = IntWidth::try_from_symbol(symbol) {
|
||||||
|
@ -1297,6 +1298,8 @@ impl<'a> LayoutCache<'a> {
|
||||||
target_info: self.target_info,
|
target_info: self.target_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//if true {panic!()}
|
||||||
|
|
||||||
Layout::from_var(&mut env, var)
|
Layout::from_var(&mut env, var)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1570,6 +1573,7 @@ impl<'a> Builtin<'a> {
|
||||||
|
|
||||||
fn layout_from_flat_type<'a>(
|
fn layout_from_flat_type<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
|
var: Variable,
|
||||||
flat_type: FlatType,
|
flat_type: FlatType,
|
||||||
) -> Result<Layout<'a>, LayoutProblem> {
|
) -> Result<Layout<'a>, LayoutProblem> {
|
||||||
use roc_types::subs::FlatType::*;
|
use roc_types::subs::FlatType::*;
|
||||||
|
@ -1731,7 +1735,7 @@ fn layout_from_flat_type<'a>(
|
||||||
|
|
||||||
debug_assert!(ext_var_is_empty_tag_union(subs, ext_var));
|
debug_assert!(ext_var_is_empty_tag_union(subs, ext_var));
|
||||||
|
|
||||||
Ok(layout_from_tag_union(arena, &tags, subs, env.target_info))
|
Ok(layout_from_tag_union(env, &tags))
|
||||||
}
|
}
|
||||||
FunctionOrTagUnion(tag_name, _, ext_var) => {
|
FunctionOrTagUnion(tag_name, _, ext_var) => {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
|
@ -1742,7 +1746,7 @@ fn layout_from_flat_type<'a>(
|
||||||
let union_tags = UnionTags::from_tag_name_index(tag_name);
|
let union_tags = UnionTags::from_tag_name_index(tag_name);
|
||||||
let (tags, _) = union_tags.unsorted_tags_and_ext(subs, ext_var);
|
let (tags, _) = union_tags.unsorted_tags_and_ext(subs, ext_var);
|
||||||
|
|
||||||
Ok(layout_from_tag_union(arena, &tags, subs, env.target_info))
|
Ok(layout_from_tag_union(env, &tags))
|
||||||
}
|
}
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
let (tags, ext_var) = tags.unsorted_tags_and_ext(subs, ext_var);
|
let (tags, ext_var) = tags.unsorted_tags_and_ext(subs, ext_var);
|
||||||
|
@ -1772,6 +1776,7 @@ fn layout_from_flat_type<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env.insert_seen(var);
|
||||||
env.insert_seen(rec_var);
|
env.insert_seen(rec_var);
|
||||||
for (index, &(_name, variables)) in tags_vec.iter().enumerate() {
|
for (index, &(_name, variables)) in tags_vec.iter().enumerate() {
|
||||||
if matches!(nullable, Some(i) if i == index as TagIdIntType) {
|
if matches!(nullable, Some(i) if i == index as TagIdIntType) {
|
||||||
|
@ -1801,6 +1806,7 @@ fn layout_from_flat_type<'a>(
|
||||||
tag_layouts.push(tag_layout.into_bump_slice());
|
tag_layouts.push(tag_layout.into_bump_slice());
|
||||||
}
|
}
|
||||||
env.remove_seen(rec_var);
|
env.remove_seen(rec_var);
|
||||||
|
env.insert_seen(var);
|
||||||
|
|
||||||
let union_layout = if let Some(tag_id) = nullable {
|
let union_layout = if let Some(tag_id) = nullable {
|
||||||
match tag_layouts.into_bump_slice() {
|
match tag_layouts.into_bump_slice() {
|
||||||
|
@ -2071,23 +2077,14 @@ fn is_recursive_tag_union(layout: &Layout) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn union_sorted_tags_help_new<'a>(
|
fn union_sorted_tags_help_new<'a>(
|
||||||
arena: &'a Bump,
|
env: &mut Env<'a, '_>,
|
||||||
tags_list: &[(&'_ TagName, &[Variable])],
|
tags_list: &[(&'_ TagName, &[Variable])],
|
||||||
opt_rec_var: Option<Variable>,
|
opt_rec_var: Option<Variable>,
|
||||||
subs: &Subs,
|
|
||||||
target_info: TargetInfo,
|
|
||||||
) -> UnionVariant<'a> {
|
) -> UnionVariant<'a> {
|
||||||
// sort up front; make sure the ordering stays intact!
|
// sort up front; make sure the ordering stays intact!
|
||||||
let mut tags_list = Vec::from_iter_in(tags_list.iter(), arena);
|
let mut tags_list = Vec::from_iter_in(tags_list.iter(), env.arena);
|
||||||
tags_list.sort_unstable_by(|(a, _), (b, _)| a.cmp(b));
|
tags_list.sort_unstable_by(|(a, _), (b, _)| a.cmp(b));
|
||||||
|
|
||||||
let mut env = Env {
|
|
||||||
arena,
|
|
||||||
subs,
|
|
||||||
seen: Vec::new_in(arena),
|
|
||||||
target_info,
|
|
||||||
};
|
|
||||||
|
|
||||||
match tags_list.len() {
|
match tags_list.len() {
|
||||||
0 => {
|
0 => {
|
||||||
// trying to instantiate a type with no values
|
// trying to instantiate a type with no values
|
||||||
|
@ -2098,18 +2095,19 @@ fn union_sorted_tags_help_new<'a>(
|
||||||
let tag_name = tag_name.clone();
|
let tag_name = tag_name.clone();
|
||||||
|
|
||||||
// just one tag in the union (but with arguments) can be a struct
|
// just one tag in the union (but with arguments) can be a struct
|
||||||
let mut layouts = Vec::with_capacity_in(tags_list.len(), arena);
|
let mut layouts = Vec::with_capacity_in(tags_list.len(), env.arena);
|
||||||
|
|
||||||
// special-case NUM_AT_NUM: if its argument is a FlexVar, make it Int
|
// special-case NUM_AT_NUM: if its argument is a FlexVar, make it Int
|
||||||
match tag_name {
|
match tag_name {
|
||||||
TagName::Private(Symbol::NUM_AT_NUM) => {
|
TagName::Private(Symbol::NUM_AT_NUM) => {
|
||||||
let var = arguments[0];
|
let var = arguments[0];
|
||||||
layouts
|
layouts.push(
|
||||||
.push(unwrap_num_tag(subs, var, target_info).expect("invalid num layout"));
|
unwrap_num_tag(env.subs, var, env.target_info).expect("invalid num layout"),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
for &var in arguments {
|
for &var in arguments {
|
||||||
match Layout::from_var(&mut env, var) {
|
match Layout::from_var(env, var) {
|
||||||
Ok(layout) => {
|
Ok(layout) => {
|
||||||
layouts.push(layout);
|
layouts.push(layout);
|
||||||
}
|
}
|
||||||
|
@ -2129,8 +2127,8 @@ fn union_sorted_tags_help_new<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
layouts.sort_by(|layout1, layout2| {
|
layouts.sort_by(|layout1, layout2| {
|
||||||
let size1 = layout1.alignment_bytes(target_info);
|
let size1 = layout1.alignment_bytes(env.target_info);
|
||||||
let size2 = layout2.alignment_bytes(target_info);
|
let size2 = layout2.alignment_bytes(env.target_info);
|
||||||
|
|
||||||
size2.cmp(&size1)
|
size2.cmp(&size1)
|
||||||
});
|
});
|
||||||
|
@ -2151,7 +2149,7 @@ fn union_sorted_tags_help_new<'a>(
|
||||||
}
|
}
|
||||||
num_tags => {
|
num_tags => {
|
||||||
// default path
|
// default path
|
||||||
let mut answer = Vec::with_capacity_in(tags_list.len(), arena);
|
let mut answer = Vec::with_capacity_in(tags_list.len(), env.arena);
|
||||||
let mut has_any_arguments = false;
|
let mut has_any_arguments = false;
|
||||||
|
|
||||||
let mut nullable: Option<(TagIdIntType, TagName)> = None;
|
let mut nullable: Option<(TagIdIntType, TagName)> = None;
|
||||||
|
@ -2174,17 +2172,19 @@ fn union_sorted_tags_help_new<'a>(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut arg_layouts = Vec::with_capacity_in(arguments.len() + 1, arena);
|
let mut arg_layouts = Vec::with_capacity_in(arguments.len() + 1, env.arena);
|
||||||
|
|
||||||
for &var in arguments {
|
for &var in arguments {
|
||||||
match Layout::from_var(&mut env, var) {
|
match Layout::from_var(env, var) {
|
||||||
Ok(layout) => {
|
Ok(layout) => {
|
||||||
has_any_arguments = true;
|
has_any_arguments = true;
|
||||||
|
|
||||||
// make sure to not unroll recursive types!
|
// make sure to not unroll recursive types!
|
||||||
let self_recursion = opt_rec_var.is_some()
|
let self_recursion = opt_rec_var.is_some()
|
||||||
&& subs.get_root_key_without_compacting(var)
|
&& env.subs.get_root_key_without_compacting(var)
|
||||||
== subs.get_root_key_without_compacting(opt_rec_var.unwrap())
|
== env
|
||||||
|
.subs
|
||||||
|
.get_root_key_without_compacting(opt_rec_var.unwrap())
|
||||||
&& is_recursive_tag_union(&layout);
|
&& is_recursive_tag_union(&layout);
|
||||||
|
|
||||||
if self_recursion {
|
if self_recursion {
|
||||||
|
@ -2207,8 +2207,8 @@ fn union_sorted_tags_help_new<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
arg_layouts.sort_by(|layout1, layout2| {
|
arg_layouts.sort_by(|layout1, layout2| {
|
||||||
let size1 = layout1.alignment_bytes(target_info);
|
let size1 = layout1.alignment_bytes(env.target_info);
|
||||||
let size2 = layout2.alignment_bytes(target_info);
|
let size2 = layout2.alignment_bytes(env.target_info);
|
||||||
|
|
||||||
size2.cmp(&size1)
|
size2.cmp(&size1)
|
||||||
});
|
});
|
||||||
|
@ -2229,7 +2229,7 @@ fn union_sorted_tags_help_new<'a>(
|
||||||
3..=MAX_ENUM_SIZE if !has_any_arguments => {
|
3..=MAX_ENUM_SIZE if !has_any_arguments => {
|
||||||
// type can be stored in a byte
|
// type can be stored in a byte
|
||||||
// needs the sorted tag names to determine the tag_id
|
// needs the sorted tag names to determine the tag_id
|
||||||
let mut tag_names = Vec::with_capacity_in(answer.len(), arena);
|
let mut tag_names = Vec::with_capacity_in(answer.len(), env.arena);
|
||||||
|
|
||||||
for (tag_name, _) in answer {
|
for (tag_name, _) in answer {
|
||||||
tag_names.push(tag_name);
|
tag_names.push(tag_name);
|
||||||
|
@ -2488,27 +2488,15 @@ pub fn union_sorted_tags_help<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_from_newtype<'a>(
|
fn layout_from_newtype<'a>(env: &mut Env<'a, '_>, tags: &UnsortedUnionTags) -> Layout<'a> {
|
||||||
arena: &'a Bump,
|
debug_assert!(tags.is_newtype_wrapper(env.subs));
|
||||||
tags: &UnsortedUnionTags,
|
|
||||||
subs: &Subs,
|
|
||||||
target_info: TargetInfo,
|
|
||||||
) -> Layout<'a> {
|
|
||||||
debug_assert!(tags.is_newtype_wrapper(subs));
|
|
||||||
|
|
||||||
let (tag_name, var) = tags.get_newtype(subs);
|
let (tag_name, var) = tags.get_newtype(env.subs);
|
||||||
|
|
||||||
if tag_name == &TagName::Private(Symbol::NUM_AT_NUM) {
|
if tag_name == &TagName::Private(Symbol::NUM_AT_NUM) {
|
||||||
unwrap_num_tag(subs, var, target_info).expect("invalid Num argument")
|
unwrap_num_tag(env.subs, var, env.target_info).expect("invalid Num argument")
|
||||||
} else {
|
} else {
|
||||||
let mut env = Env {
|
match Layout::from_var(env, var) {
|
||||||
arena,
|
|
||||||
subs,
|
|
||||||
seen: Vec::new_in(arena),
|
|
||||||
target_info,
|
|
||||||
};
|
|
||||||
|
|
||||||
match Layout::from_var(&mut env, var) {
|
|
||||||
Ok(layout) => layout,
|
Ok(layout) => layout,
|
||||||
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
|
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
|
||||||
// If we encounter an unbound type var (e.g. `Ok *`)
|
// If we encounter an unbound type var (e.g. `Ok *`)
|
||||||
|
@ -2525,16 +2513,11 @@ fn layout_from_newtype<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_from_tag_union<'a>(
|
fn layout_from_tag_union<'a>(env: &mut Env<'a, '_>, tags: &UnsortedUnionTags) -> Layout<'a> {
|
||||||
arena: &'a Bump,
|
|
||||||
tags: &UnsortedUnionTags,
|
|
||||||
subs: &Subs,
|
|
||||||
target_info: TargetInfo,
|
|
||||||
) -> Layout<'a> {
|
|
||||||
use UnionVariant::*;
|
use UnionVariant::*;
|
||||||
|
|
||||||
if tags.is_newtype_wrapper(subs) {
|
if tags.is_newtype_wrapper(env.subs) {
|
||||||
return layout_from_newtype(arena, tags, subs, target_info);
|
return layout_from_newtype(env, tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tags_vec = &tags.tags;
|
let tags_vec = &tags.tags;
|
||||||
|
@ -2545,12 +2528,11 @@ fn layout_from_tag_union<'a>(
|
||||||
|
|
||||||
let &var = arguments.iter().next().unwrap();
|
let &var = arguments.iter().next().unwrap();
|
||||||
|
|
||||||
unwrap_num_tag(subs, var, target_info).expect("invalid Num argument")
|
unwrap_num_tag(env.subs, var, env.target_info).expect("invalid Num argument")
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let opt_rec_var = None;
|
let opt_rec_var = None;
|
||||||
let variant =
|
let variant = union_sorted_tags_help_new(env, tags_vec, opt_rec_var);
|
||||||
union_sorted_tags_help_new(arena, tags_vec, opt_rec_var, subs, target_info);
|
|
||||||
|
|
||||||
match variant {
|
match variant {
|
||||||
Never => Layout::VOID,
|
Never => Layout::VOID,
|
||||||
|
@ -2576,7 +2558,7 @@ fn layout_from_tag_union<'a>(
|
||||||
NonRecursive {
|
NonRecursive {
|
||||||
sorted_tag_layouts: tags,
|
sorted_tag_layouts: tags,
|
||||||
} => {
|
} => {
|
||||||
let mut tag_layouts = Vec::with_capacity_in(tags.len(), arena);
|
let mut tag_layouts = Vec::with_capacity_in(tags.len(), env.arena);
|
||||||
tag_layouts.extend(tags.iter().map(|r| r.1));
|
tag_layouts.extend(tags.iter().map(|r| r.1));
|
||||||
|
|
||||||
Layout::Union(UnionLayout::NonRecursive(tag_layouts.into_bump_slice()))
|
Layout::Union(UnionLayout::NonRecursive(tag_layouts.into_bump_slice()))
|
||||||
|
@ -2585,7 +2567,7 @@ fn layout_from_tag_union<'a>(
|
||||||
Recursive {
|
Recursive {
|
||||||
sorted_tag_layouts: tags,
|
sorted_tag_layouts: tags,
|
||||||
} => {
|
} => {
|
||||||
let mut tag_layouts = Vec::with_capacity_in(tags.len(), arena);
|
let mut tag_layouts = Vec::with_capacity_in(tags.len(), env.arena);
|
||||||
tag_layouts.extend(tags.iter().map(|r| r.1));
|
tag_layouts.extend(tags.iter().map(|r| r.1));
|
||||||
|
|
||||||
debug_assert!(tag_layouts.len() > 1);
|
debug_assert!(tag_layouts.len() > 1);
|
||||||
|
@ -2597,7 +2579,7 @@ fn layout_from_tag_union<'a>(
|
||||||
nullable_name: _,
|
nullable_name: _,
|
||||||
sorted_tag_layouts: tags,
|
sorted_tag_layouts: tags,
|
||||||
} => {
|
} => {
|
||||||
let mut tag_layouts = Vec::with_capacity_in(tags.len(), arena);
|
let mut tag_layouts = Vec::with_capacity_in(tags.len(), env.arena);
|
||||||
tag_layouts.extend(tags.iter().map(|r| r.1));
|
tag_layouts.extend(tags.iter().map(|r| r.1));
|
||||||
|
|
||||||
Layout::Union(UnionLayout::NullableWrapped {
|
Layout::Union(UnionLayout::NullableWrapped {
|
||||||
|
|
6
compiler/test_mono/generated/issue_2810.txt
Normal file
6
compiler/test_mono/generated/issue_2810.txt
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
procedure Test.0 ():
|
||||||
|
let Test.16 : [C TODO, C ] = SystemTool ;
|
||||||
|
let Test.14 : TODO = Job Test.16;
|
||||||
|
let Test.13 : [C TODO, C ] = FromJob Test.14;
|
||||||
|
let Test.4 : TODO = Job Test.13;
|
||||||
|
ret Test.4;
|
|
@ -1283,6 +1283,23 @@ fn issue_2583_specialize_errors_behind_unified_branches() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[mono_test]
|
||||||
|
fn issue_2810() {
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Command : [ Command Tool ]
|
||||||
|
|
||||||
|
Job : [ Job Command ]
|
||||||
|
|
||||||
|
Tool : [ SystemTool, FromJob Job ]
|
||||||
|
|
||||||
|
a : Job
|
||||||
|
a = Job (Command (FromJob (Job (Command SystemTool))))
|
||||||
|
a
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[mono_test]
|
#[mono_test]
|
||||||
fn issue_2811() {
|
fn issue_2811() {
|
||||||
indoc!(
|
indoc!(
|
||||||
|
|
|
@ -1138,3 +1138,23 @@ fn issue_2818() {
|
||||||
r"<function> : {} -> List Str",
|
r"<function> : {} -> List Str",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_2810_recursive_layout_inside_nonrecursive() {
|
||||||
|
expect_success(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Command : [ Command Tool ]
|
||||||
|
|
||||||
|
Job : [ Job Command ]
|
||||||
|
|
||||||
|
Tool : [ SystemTool, FromJob Job ]
|
||||||
|
|
||||||
|
a : Job
|
||||||
|
a = Job (Command (FromJob (Job (Command SystemTool))))
|
||||||
|
a
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
"Job (Command (FromJob (Job (Command SystemTool)))) : Job",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue