mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Merge remote-tracking branch 'origin/main' into glue-getters-rtfeldman
This commit is contained in:
commit
0d4135c57a
95 changed files with 5408 additions and 1860 deletions
|
@ -100,8 +100,14 @@ pub fn infer_borrow<'a>(
|
|||
// host-exposed functions must always own their arguments.
|
||||
let is_host_exposed = host_exposed_procs.contains(&key.0);
|
||||
|
||||
let param_offset = param_map.get_param_offset(key.0, key.1);
|
||||
env.collect_proc(&mut param_map, proc, param_offset, is_host_exposed);
|
||||
let param_offset = param_map.get_param_offset(interner, key.0, key.1);
|
||||
env.collect_proc(
|
||||
interner,
|
||||
&mut param_map,
|
||||
proc,
|
||||
param_offset,
|
||||
is_host_exposed,
|
||||
);
|
||||
}
|
||||
|
||||
if !env.modified {
|
||||
|
@ -167,6 +173,7 @@ impl<'a> DeclarationToIndex<'a> {
|
|||
|
||||
fn get_param_offset(
|
||||
&self,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
needle_symbol: Symbol,
|
||||
needle_layout: ProcLayout<'a>,
|
||||
) -> ParamOffset {
|
||||
|
@ -181,12 +188,14 @@ impl<'a> DeclarationToIndex<'a> {
|
|||
.elements
|
||||
.iter()
|
||||
.filter_map(|(Declaration { symbol, layout }, _)| {
|
||||
(*symbol == needle_symbol).then_some(layout)
|
||||
(*symbol == needle_symbol)
|
||||
.then_some(layout)
|
||||
.map(|l| l.dbg_deep(interner))
|
||||
})
|
||||
.collect::<std::vec::Vec<_>>();
|
||||
unreachable!(
|
||||
"symbol/layout {:?} {:#?} combo must be in DeclarationToIndex\nHowever {} similar layouts were found:\n{:#?}",
|
||||
needle_symbol, needle_layout, similar.len(), similar
|
||||
needle_symbol, needle_layout.dbg_deep(interner), similar.len(), similar,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -206,13 +215,24 @@ pub struct ParamMap<'a> {
|
|||
}
|
||||
|
||||
impl<'a> ParamMap<'a> {
|
||||
pub fn get_param_offset(&self, symbol: Symbol, layout: ProcLayout<'a>) -> ParamOffset {
|
||||
self.declaration_to_index.get_param_offset(symbol, layout)
|
||||
pub fn get_param_offset(
|
||||
&self,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
symbol: Symbol,
|
||||
layout: ProcLayout<'a>,
|
||||
) -> ParamOffset {
|
||||
self.declaration_to_index
|
||||
.get_param_offset(interner, symbol, layout)
|
||||
}
|
||||
|
||||
pub fn get_symbol(&self, symbol: Symbol, layout: ProcLayout<'a>) -> Option<&[Param<'a>]> {
|
||||
pub fn get_symbol(
|
||||
&self,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
symbol: Symbol,
|
||||
layout: ProcLayout<'a>,
|
||||
) -> Option<&[Param<'a>]> {
|
||||
// let index: usize = self.declaration_to_index[&(symbol, layout)].into();
|
||||
let index: usize = self.get_param_offset(symbol, layout).into();
|
||||
let index: usize = self.get_param_offset(interner, symbol, layout).into();
|
||||
|
||||
self.declarations.get(index..index + layout.arguments.len())
|
||||
}
|
||||
|
@ -292,7 +312,7 @@ impl<'a> ParamMap<'a> {
|
|||
return;
|
||||
}
|
||||
|
||||
let index: usize = self.get_param_offset(key.0, key.1).into();
|
||||
let index: usize = self.get_param_offset(interner, key.0, key.1).into();
|
||||
|
||||
for (i, param) in Self::init_borrow_args(arena, interner, proc.args)
|
||||
.iter()
|
||||
|
@ -312,7 +332,7 @@ impl<'a> ParamMap<'a> {
|
|||
proc: &Proc<'a>,
|
||||
key: (Symbol, ProcLayout<'a>),
|
||||
) {
|
||||
let index: usize = self.get_param_offset(key.0, key.1).into();
|
||||
let index: usize = self.get_param_offset(interner, key.0, key.1).into();
|
||||
|
||||
for (i, param) in Self::init_borrow_args_always_owned(arena, proc.args)
|
||||
.iter()
|
||||
|
@ -534,7 +554,13 @@ impl<'a> BorrowInfState<'a> {
|
|||
///
|
||||
/// and determines whether z and which of the symbols used in e
|
||||
/// must be taken as owned parameters
|
||||
fn collect_call(&mut self, param_map: &mut ParamMap<'a>, z: Symbol, e: &crate::ir::Call<'a>) {
|
||||
fn collect_call(
|
||||
&mut self,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
param_map: &mut ParamMap<'a>,
|
||||
z: Symbol,
|
||||
e: &crate::ir::Call<'a>,
|
||||
) {
|
||||
use crate::ir::CallType::*;
|
||||
|
||||
let crate::ir::Call {
|
||||
|
@ -553,7 +579,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
|
||||
// get the borrow signature of the applied function
|
||||
let ps = param_map
|
||||
.get_symbol(name.name(), top_level)
|
||||
.get_symbol(interner, name.name(), top_level)
|
||||
.expect("function is defined");
|
||||
|
||||
// the return value will be owned
|
||||
|
@ -595,11 +621,14 @@ impl<'a> BorrowInfState<'a> {
|
|||
niche: passed_function.name.niche(),
|
||||
};
|
||||
|
||||
let function_ps =
|
||||
match param_map.get_symbol(passed_function.name.name(), closure_layout) {
|
||||
Some(function_ps) => function_ps,
|
||||
None => unreachable!(),
|
||||
};
|
||||
let function_ps = match param_map.get_symbol(
|
||||
interner,
|
||||
passed_function.name.name(),
|
||||
closure_layout,
|
||||
) {
|
||||
Some(function_ps) => function_ps,
|
||||
None => unreachable!(),
|
||||
};
|
||||
|
||||
match op {
|
||||
ListMap { xs } => {
|
||||
|
@ -671,7 +700,13 @@ impl<'a> BorrowInfState<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn collect_expr(&mut self, param_map: &mut ParamMap<'a>, z: Symbol, e: &Expr<'a>) {
|
||||
fn collect_expr(
|
||||
&mut self,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
param_map: &mut ParamMap<'a>,
|
||||
z: Symbol,
|
||||
e: &Expr<'a>,
|
||||
) {
|
||||
use Expr::*;
|
||||
|
||||
match e {
|
||||
|
@ -724,7 +759,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
self.own_var(z);
|
||||
}
|
||||
|
||||
Call(call) => self.collect_call(param_map, z, call),
|
||||
Call(call) => self.collect_call(interner, param_map, z, call),
|
||||
|
||||
Literal(_) | RuntimeErrorFunction(_) => {}
|
||||
|
||||
|
@ -757,6 +792,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
#[allow(clippy::many_single_char_names)]
|
||||
fn preserve_tail_call(
|
||||
&mut self,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
param_map: &mut ParamMap<'a>,
|
||||
x: Symbol,
|
||||
v: &Expr<'a>,
|
||||
|
@ -782,7 +818,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
if self.current_proc == g.name() && x == *z {
|
||||
// anonymous functions (for which the ps may not be known)
|
||||
// can never be tail-recursive, so this is fine
|
||||
if let Some(ps) = param_map.get_symbol(g.name(), top_level) {
|
||||
if let Some(ps) = param_map.get_symbol(interner, g.name(), top_level) {
|
||||
self.own_params_using_args(ys, ps)
|
||||
}
|
||||
}
|
||||
|
@ -801,7 +837,12 @@ impl<'a> BorrowInfState<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn collect_stmt(&mut self, param_map: &mut ParamMap<'a>, stmt: &Stmt<'a>) {
|
||||
fn collect_stmt(
|
||||
&mut self,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
param_map: &mut ParamMap<'a>,
|
||||
stmt: &Stmt<'a>,
|
||||
) {
|
||||
use Stmt::*;
|
||||
|
||||
match stmt {
|
||||
|
@ -813,11 +854,11 @@ impl<'a> BorrowInfState<'a> {
|
|||
} => {
|
||||
let old = self.param_set.clone();
|
||||
self.update_param_set(ys);
|
||||
self.collect_stmt(param_map, v);
|
||||
self.collect_stmt(interner, param_map, v);
|
||||
self.param_set = old;
|
||||
self.update_param_map_join_point(param_map, *j);
|
||||
|
||||
self.collect_stmt(param_map, b);
|
||||
self.collect_stmt(interner, param_map, b);
|
||||
}
|
||||
|
||||
Let(x, v, _, mut b) => {
|
||||
|
@ -830,17 +871,17 @@ impl<'a> BorrowInfState<'a> {
|
|||
stack.push((*symbol, expr));
|
||||
}
|
||||
|
||||
self.collect_stmt(param_map, b);
|
||||
self.collect_stmt(interner, param_map, b);
|
||||
|
||||
let mut it = stack.into_iter().rev();
|
||||
|
||||
// collect the final expr, and see if we need to preserve a tail call
|
||||
let (x, v) = it.next().unwrap();
|
||||
self.collect_expr(param_map, x, v);
|
||||
self.preserve_tail_call(param_map, x, v, b);
|
||||
self.collect_expr(interner, param_map, x, v);
|
||||
self.preserve_tail_call(interner, param_map, x, v, b);
|
||||
|
||||
for (x, v) in it {
|
||||
self.collect_expr(param_map, x, v);
|
||||
self.collect_expr(interner, param_map, x, v);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -859,21 +900,21 @@ impl<'a> BorrowInfState<'a> {
|
|||
..
|
||||
} => {
|
||||
for (_, _, b) in branches.iter() {
|
||||
self.collect_stmt(param_map, b);
|
||||
self.collect_stmt(interner, param_map, b);
|
||||
}
|
||||
self.collect_stmt(param_map, default_branch.1);
|
||||
self.collect_stmt(interner, param_map, default_branch.1);
|
||||
}
|
||||
|
||||
Dbg { remainder, .. } => {
|
||||
self.collect_stmt(param_map, remainder);
|
||||
self.collect_stmt(interner, param_map, remainder);
|
||||
}
|
||||
|
||||
Expect { remainder, .. } => {
|
||||
self.collect_stmt(param_map, remainder);
|
||||
self.collect_stmt(interner, param_map, remainder);
|
||||
}
|
||||
|
||||
ExpectFx { remainder, .. } => {
|
||||
self.collect_stmt(param_map, remainder);
|
||||
self.collect_stmt(interner, param_map, remainder);
|
||||
}
|
||||
|
||||
Refcounting(_, _) => unreachable!("these have not been introduced yet"),
|
||||
|
@ -891,6 +932,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
|
||||
fn collect_proc(
|
||||
&mut self,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
param_map: &mut ParamMap<'a>,
|
||||
proc: &Proc<'a>,
|
||||
param_offset: ParamOffset,
|
||||
|
@ -912,7 +954,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
owned_entry.extend(params.iter().map(|p| p.symbol));
|
||||
}
|
||||
|
||||
self.collect_stmt(param_map, &proc.body);
|
||||
self.collect_stmt(interner, param_map, &proc.body);
|
||||
self.update_param_map_declaration(param_map, param_offset, proc.args.len());
|
||||
|
||||
self.param_set = old;
|
||||
|
|
|
@ -731,8 +731,7 @@ fn refcount_list<'a>(
|
|||
let arena = root.arena;
|
||||
|
||||
// A "Box" layout (heap pointer to a single list element)
|
||||
let box_union_layout = UnionLayout::NonNullableUnwrapped(arena.alloc([elem_layout]));
|
||||
let box_layout = layout_interner.insert(Layout::Union(box_union_layout));
|
||||
let box_layout = layout_interner.insert(Layout::Boxed(elem_layout));
|
||||
|
||||
//
|
||||
// Check if the list is empty
|
||||
|
@ -803,7 +802,7 @@ fn refcount_list<'a>(
|
|||
layout_interner,
|
||||
elem_layout,
|
||||
LAYOUT_UNIT,
|
||||
box_union_layout,
|
||||
box_layout,
|
||||
len,
|
||||
elements,
|
||||
get_rc_and_modify_list,
|
||||
|
@ -853,7 +852,7 @@ fn refcount_list_elems<'a>(
|
|||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
elem_layout: InLayout<'a>,
|
||||
ret_layout: InLayout<'a>,
|
||||
box_union_layout: UnionLayout<'a>,
|
||||
box_layout: InLayout<'a>,
|
||||
length: Symbol,
|
||||
elements: Symbol,
|
||||
following: Stmt<'a>,
|
||||
|
@ -913,17 +912,11 @@ fn refcount_list_elems<'a>(
|
|||
|
||||
// Cast integer to box pointer
|
||||
let box_ptr = root.create_symbol(ident_ids, "box");
|
||||
let box_layout = layout_interner.insert(Layout::Union(box_union_layout));
|
||||
let box_stmt = |next| let_lowlevel(arena, box_layout, box_ptr, PtrCast, &[addr], next);
|
||||
|
||||
// Dereference the box pointer to get the current element
|
||||
let elem = root.create_symbol(ident_ids, "elem");
|
||||
let elem_expr = Expr::UnionAtIndex {
|
||||
structure: box_ptr,
|
||||
union_layout: box_union_layout,
|
||||
tag_id: 0,
|
||||
index: 0,
|
||||
};
|
||||
let elem_expr = Expr::ExprUnbox { symbol: box_ptr };
|
||||
let elem_stmt = |next| Stmt::Let(elem, elem_expr, elem_layout, next);
|
||||
|
||||
//
|
||||
|
|
|
@ -605,7 +605,7 @@ impl<'a, 'i> Context<'a, 'i> {
|
|||
// get the borrow signature
|
||||
let ps = self
|
||||
.param_map
|
||||
.get_symbol(name.name(), top_level)
|
||||
.get_symbol(self.layout_interner, name.name(), top_level)
|
||||
.expect("function is defined");
|
||||
|
||||
let v = Expr::Call(crate::ir::Call {
|
||||
|
@ -653,10 +653,11 @@ impl<'a, 'i> Context<'a, 'i> {
|
|||
niche: passed_function.name.niche(),
|
||||
};
|
||||
|
||||
let function_ps = match self
|
||||
.param_map
|
||||
.get_symbol(passed_function.name.name(), function_layout)
|
||||
{
|
||||
let function_ps = match self.param_map.get_symbol(
|
||||
self.layout_interner,
|
||||
passed_function.name.name(),
|
||||
function_layout,
|
||||
) {
|
||||
Some(function_ps) => function_ps,
|
||||
None => unreachable!(),
|
||||
};
|
||||
|
@ -1510,19 +1511,28 @@ pub fn visit_procs<'a, 'i>(
|
|||
};
|
||||
|
||||
for (key, proc) in procs.iter_mut() {
|
||||
visit_proc(arena, &mut codegen, param_map, &ctx, proc, key.1);
|
||||
visit_proc(
|
||||
arena,
|
||||
layout_interner,
|
||||
&mut codegen,
|
||||
param_map,
|
||||
&ctx,
|
||||
proc,
|
||||
key.1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_proc<'a, 'i>(
|
||||
arena: &'a Bump,
|
||||
interner: &STLayoutInterner<'a>,
|
||||
codegen: &mut CodegenTools<'i>,
|
||||
param_map: &'a ParamMap<'a>,
|
||||
ctx: &Context<'a, 'i>,
|
||||
proc: &mut Proc<'a>,
|
||||
layout: ProcLayout<'a>,
|
||||
) {
|
||||
let params = match param_map.get_symbol(proc.name.name(), layout) {
|
||||
let params = match param_map.get_symbol(interner, proc.name.name(), layout) {
|
||||
Some(slice) => slice,
|
||||
None => Vec::from_iter_in(
|
||||
proc.args.iter().cloned().map(|(layout, symbol)| Param {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,5 @@
|
|||
use crate::ir::Parens;
|
||||
use crate::layout::intern::NeedsRecursionPointerFixup;
|
||||
use bitvec::vec::BitVec;
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
|
@ -491,7 +492,9 @@ impl<'a> RawFunctionLayout<'a> {
|
|||
let structure_content = env.subs.get_content_without_compacting(structure);
|
||||
Self::new_help(env, structure, *structure_content)
|
||||
}
|
||||
LambdaSet(lset) => Self::layout_from_lambda_set(env, lset),
|
||||
LambdaSet(_) => {
|
||||
internal_error!("lambda set should only appear under a function, where it's handled independently.");
|
||||
}
|
||||
Structure(flat_type) => Self::layout_from_flat_type(env, flat_type),
|
||||
RangedNumber(..) => Layout::new_help(env, var, content).then(Self::ZeroArgumentThunk),
|
||||
|
||||
|
@ -564,15 +567,6 @@ impl<'a> RawFunctionLayout<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn layout_from_lambda_set(
|
||||
_env: &mut Env<'a, '_>,
|
||||
_lset: subs::LambdaSet,
|
||||
) -> Cacheable<RawFunctionLayoutResult<'a>> {
|
||||
unreachable!()
|
||||
// Lambda set is just a tag union from the layout's perspective.
|
||||
// Self::layout_from_flat_type(env, lset.as_tag_union())
|
||||
}
|
||||
|
||||
fn layout_from_flat_type(
|
||||
env: &mut Env<'a, '_>,
|
||||
flat_type: FlatType,
|
||||
|
@ -1319,6 +1313,14 @@ impl<'a> Niche<'a> {
|
|||
]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dbg_deep<'r, I: LayoutInterner<'a>>(
|
||||
&'r self,
|
||||
interner: &'r I,
|
||||
) -> crate::layout::intern::dbg::DbgFields<'a, 'r, I> {
|
||||
let NichePriv::Captures(caps) = &self.0;
|
||||
interner.dbg_deep_iter(caps)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
|
@ -1883,12 +1885,16 @@ impl<'a> LambdaSet<'a> {
|
|||
);
|
||||
cache_criteria.and(criteria);
|
||||
|
||||
let needs_recursive_fixup = NeedsRecursionPointerFixup(
|
||||
opt_recursion_var.is_some() && set_captures_have_naked_rec_ptr,
|
||||
);
|
||||
|
||||
let lambda_set = env.cache.interner.insert_lambda_set(
|
||||
env.arena,
|
||||
fn_args,
|
||||
ret,
|
||||
env.arena.alloc(set.into_bump_slice()),
|
||||
set_captures_have_naked_rec_ptr,
|
||||
needs_recursive_fixup,
|
||||
representation,
|
||||
);
|
||||
|
||||
|
@ -1902,7 +1908,7 @@ impl<'a> LambdaSet<'a> {
|
|||
fn_args,
|
||||
ret,
|
||||
&(&[] as &[(Symbol, &[InLayout])]),
|
||||
false,
|
||||
NeedsRecursionPointerFixup(false),
|
||||
Layout::UNIT,
|
||||
);
|
||||
Cacheable(Ok(lambda_set), cache_criteria)
|
||||
|
@ -2368,7 +2374,9 @@ impl<'a> Layout<'a> {
|
|||
let structure_content = env.subs.get_content_without_compacting(structure);
|
||||
Self::new_help(env, structure, *structure_content)
|
||||
}
|
||||
LambdaSet(lset) => layout_from_lambda_set(env, lset),
|
||||
LambdaSet(_) => {
|
||||
internal_error!("lambda set should only appear under a function, where it's handled independently.");
|
||||
}
|
||||
Structure(flat_type) => layout_from_flat_type(env, flat_type),
|
||||
|
||||
Alias(symbol, _args, actual_var, _) => {
|
||||
|
@ -3019,37 +3027,6 @@ impl<'a> Builtin<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn layout_from_lambda_set<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
lset: subs::LambdaSet,
|
||||
) -> Cacheable<LayoutResult<'a>> {
|
||||
// Lambda set is just a tag union from the layout's perspective.
|
||||
let subs::LambdaSet {
|
||||
solved,
|
||||
recursion_var,
|
||||
unspecialized,
|
||||
ambient_function: _,
|
||||
} = lset;
|
||||
|
||||
if !unspecialized.is_empty() {
|
||||
internal_error!(
|
||||
"unspecialized lambda sets remain during layout generation for {:?}",
|
||||
roc_types::subs::SubsFmtContent(&Content::LambdaSet(lset), env.subs)
|
||||
);
|
||||
}
|
||||
|
||||
match recursion_var.into_variable() {
|
||||
None => {
|
||||
let labels = solved.unsorted_lambdas(env.subs);
|
||||
layout_from_non_recursive_union(env, &labels).map(Ok)
|
||||
}
|
||||
Some(rec_var) => {
|
||||
let labels = solved.unsorted_lambdas(env.subs);
|
||||
layout_from_recursive_union(env, rec_var, &labels)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn layout_from_flat_type<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
flat_type: FlatType,
|
||||
|
|
|
@ -121,6 +121,13 @@ impl<'a> Layout<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Whether a recursive lambda set being inserted into an interner needs fixing-up of naked
|
||||
/// recursion pointers in the capture set.
|
||||
/// Applicable only if
|
||||
/// - the lambda set is indeed recursive, and
|
||||
/// - its capture set contain naked pointer references
|
||||
pub struct NeedsRecursionPointerFixup(pub bool);
|
||||
|
||||
pub trait LayoutInterner<'a>: Sized {
|
||||
/// Interns a value, returning its interned representation.
|
||||
/// If the value has been interned before, the old interned representation will be re-used.
|
||||
|
@ -139,7 +146,7 @@ pub trait LayoutInterner<'a>: Sized {
|
|||
args: &'a &'a [InLayout<'a>],
|
||||
ret: InLayout<'a>,
|
||||
set: &'a &'a [(Symbol, &'a [InLayout<'a>])],
|
||||
set_may_have_naked_rec_ptr: bool,
|
||||
needs_recursive_fixup: NeedsRecursionPointerFixup,
|
||||
representation: InLayout<'a>,
|
||||
) -> LambdaSet<'a>;
|
||||
|
||||
|
@ -358,6 +365,10 @@ pub trait LayoutInterner<'a>: Sized {
|
|||
fn dbg_deep<'r>(&'r self, layout: InLayout<'a>) -> dbg::Dbg<'a, 'r, Self> {
|
||||
dbg::Dbg(self, layout)
|
||||
}
|
||||
|
||||
fn dbg_deep_iter<'r>(&'r self, layouts: &'a [InLayout<'a>]) -> dbg::DbgFields<'a, 'r, Self> {
|
||||
dbg::DbgFields(self, layouts)
|
||||
}
|
||||
}
|
||||
|
||||
/// An interned layout.
|
||||
|
@ -550,7 +561,7 @@ impl<'a> GlobalLayoutInterner<'a> {
|
|||
&self,
|
||||
arena: &'a Bump,
|
||||
normalized: LambdaSet<'a>,
|
||||
set_may_have_naked_rec_ptr: bool,
|
||||
needs_recursive_fixup: NeedsRecursionPointerFixup,
|
||||
normalized_hash: u64,
|
||||
) -> WrittenGlobalLambdaSet<'a> {
|
||||
let mut normalized_lambda_set_map = self.0.normalized_lambda_set_map.lock();
|
||||
|
@ -574,7 +585,7 @@ impl<'a> GlobalLayoutInterner<'a> {
|
|||
let slot = unsafe { InLayout::from_index(vec.len()) };
|
||||
vec.push(Layout::VOID_NAKED);
|
||||
|
||||
let set = if set_may_have_naked_rec_ptr {
|
||||
let set = if needs_recursive_fixup.0 {
|
||||
let mut interner = LockedGlobalInterner {
|
||||
map: &mut map,
|
||||
normalized_lambda_set_map: &mut normalized_lambda_set_map,
|
||||
|
@ -708,7 +719,7 @@ impl<'a> LayoutInterner<'a> for TLLayoutInterner<'a> {
|
|||
args: &'a &'a [InLayout<'a>],
|
||||
ret: InLayout<'a>,
|
||||
set: &'a &'a [(Symbol, &'a [InLayout<'a>])],
|
||||
set_may_have_naked_rec_ptr: bool,
|
||||
needs_recursive_fixup: NeedsRecursionPointerFixup,
|
||||
representation: InLayout<'a>,
|
||||
) -> LambdaSet<'a> {
|
||||
// The tricky bit of inserting a lambda set is we need to fill in the `full_layout` only
|
||||
|
@ -737,7 +748,7 @@ impl<'a> LayoutInterner<'a> for TLLayoutInterner<'a> {
|
|||
} = global.get_or_insert_hashed_normalized_lambda_set(
|
||||
arena,
|
||||
normalized,
|
||||
set_may_have_naked_rec_ptr,
|
||||
needs_recursive_fixup,
|
||||
normalized_hash,
|
||||
);
|
||||
|
||||
|
@ -865,7 +876,7 @@ macro_rules! st_impl {
|
|||
args: &'a &'a [InLayout<'a>],
|
||||
ret: InLayout<'a>,
|
||||
set: &'a &'a [(Symbol, &'a [InLayout<'a>])],
|
||||
set_may_have_naked_rec_ptr: bool,
|
||||
needs_recursive_fixup: NeedsRecursionPointerFixup,
|
||||
representation: InLayout<'a>,
|
||||
) -> LambdaSet<'a> {
|
||||
// IDEA:
|
||||
|
@ -884,7 +895,7 @@ macro_rules! st_impl {
|
|||
let slot = unsafe { InLayout::from_index(self.vec.len()) };
|
||||
self.vec.push(Layout::VOID_NAKED);
|
||||
|
||||
let set = if set_may_have_naked_rec_ptr {
|
||||
let set = if needs_recursive_fixup.0 {
|
||||
reify::reify_lambda_set_captures(arena, self, slot, set)
|
||||
} else {
|
||||
set
|
||||
|
@ -957,7 +968,7 @@ mod reify {
|
|||
|
||||
use crate::layout::{Builtin, LambdaSet, Layout, UnionLayout};
|
||||
|
||||
use super::{InLayout, LayoutInterner};
|
||||
use super::{InLayout, LayoutInterner, NeedsRecursionPointerFixup};
|
||||
|
||||
// TODO: if recursion becomes a problem we could make this iterative
|
||||
pub fn reify_recursive_layout<'a>(
|
||||
|
@ -1103,7 +1114,8 @@ mod reify {
|
|||
arena.alloc(args),
|
||||
ret,
|
||||
arena.alloc(set),
|
||||
true,
|
||||
// All nested recursive pointers should been fixed up, since we just did that above.
|
||||
NeedsRecursionPointerFixup(false),
|
||||
representation,
|
||||
)
|
||||
}
|
||||
|
@ -1266,7 +1278,7 @@ mod equiv {
|
|||
}
|
||||
}
|
||||
|
||||
mod dbg {
|
||||
pub mod dbg {
|
||||
use roc_module::symbol::Symbol;
|
||||
|
||||
use crate::layout::{Builtin, LambdaSet, Layout, UnionLayout};
|
||||
|
@ -1303,7 +1315,7 @@ mod dbg {
|
|||
}
|
||||
}
|
||||
|
||||
struct DbgFields<'a, 'r, I: LayoutInterner<'a>>(&'r I, &'a [InLayout<'a>]);
|
||||
pub struct DbgFields<'a, 'r, I: LayoutInterner<'a>>(pub &'r I, pub &'a [InLayout<'a>]);
|
||||
|
||||
impl<'a, 'r, I: LayoutInterner<'a>> std::fmt::Debug for DbgFields<'a, 'r, I> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
|
@ -1420,7 +1432,7 @@ mod insert_lambda_set {
|
|||
|
||||
use crate::layout::{LambdaSet, Layout};
|
||||
|
||||
use super::{GlobalLayoutInterner, InLayout, LayoutInterner};
|
||||
use super::{GlobalLayoutInterner, InLayout, LayoutInterner, NeedsRecursionPointerFixup};
|
||||
|
||||
const TARGET_INFO: TargetInfo = TargetInfo::default_x86_64();
|
||||
const TEST_SET: &&[(Symbol, &[InLayout])] =
|
||||
|
@ -1428,6 +1440,8 @@ mod insert_lambda_set {
|
|||
const TEST_ARGS: &&[InLayout] = &(&[Layout::UNIT] as &[_]);
|
||||
const TEST_RET: InLayout = Layout::UNIT;
|
||||
|
||||
const FIXUP: NeedsRecursionPointerFixup = NeedsRecursionPointerFixup(true);
|
||||
|
||||
#[test]
|
||||
fn two_threads_write() {
|
||||
for _ in 0..100 {
|
||||
|
@ -1440,7 +1454,7 @@ mod insert_lambda_set {
|
|||
for arena in arenas.iter_mut() {
|
||||
let mut interner = global.fork();
|
||||
handles.push(s.spawn(move || {
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, true, repr)
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, FIXUP, repr)
|
||||
}))
|
||||
}
|
||||
let ins: Vec<LambdaSet> = handles.into_iter().map(|t| t.join().unwrap()).collect();
|
||||
|
@ -1457,7 +1471,7 @@ mod insert_lambda_set {
|
|||
let mut interner = global.fork();
|
||||
|
||||
let lambda_set =
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, TEST_SET, true, Layout::UNIT);
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, TEST_SET, FIXUP, Layout::UNIT);
|
||||
let lambda_set_layout_in = interner.insert(Layout::LambdaSet(lambda_set));
|
||||
assert_eq!(lambda_set.full_layout, lambda_set_layout_in);
|
||||
}
|
||||
|
@ -1471,12 +1485,12 @@ mod insert_lambda_set {
|
|||
|
||||
let in1 = {
|
||||
let mut interner = global.fork();
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, true, repr)
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, FIXUP, repr)
|
||||
};
|
||||
|
||||
let in2 = {
|
||||
let mut st_interner = global.unwrap().unwrap();
|
||||
st_interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, true, repr)
|
||||
st_interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, FIXUP, repr)
|
||||
};
|
||||
|
||||
assert_eq!(in1, in2);
|
||||
|
@ -1491,12 +1505,12 @@ mod insert_lambda_set {
|
|||
let set = TEST_SET;
|
||||
let repr = Layout::UNIT;
|
||||
|
||||
let in1 = st_interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, true, repr);
|
||||
let in1 = st_interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, FIXUP, repr);
|
||||
|
||||
let global = st_interner.into_global();
|
||||
let mut interner = global.fork();
|
||||
|
||||
let in2 = interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, true, repr);
|
||||
let in2 = interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, FIXUP, repr);
|
||||
|
||||
assert_eq!(in1, in2);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#![warn(clippy::dbg_macro)]
|
||||
// See github.com/roc-lang/roc/issues/800 for discussion of the large_enum_variant check.
|
||||
#![allow(clippy::large_enum_variant, clippy::upper_case_acronyms)]
|
||||
// Not a useful lint for us
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
pub mod borrow;
|
||||
pub mod code_gen_help;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue