mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 15:03:46 +00:00
Merge pull request #4851 from JTeeuwissen/main
replace borrowed boolean with ownership enum
This commit is contained in:
commit
61a2091b27
9 changed files with 85 additions and 58 deletions
|
@ -15,12 +15,22 @@ use roc_module::symbol::Symbol;
|
|||
pub(crate) const OWNED: bool = false;
|
||||
pub(crate) const BORROWED: bool = true;
|
||||
|
||||
/// For reference-counted types (lists, (big) strings, recursive tags), owning a value
|
||||
/// means incrementing its reference count. Hence, we prefer borrowing for these types
|
||||
fn should_borrow_layout(layout: &Layout) -> bool {
|
||||
layout.is_refcounted()
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum Ownership {
|
||||
Owned,
|
||||
Borrowed,
|
||||
}
|
||||
|
||||
impl Ownership {
|
||||
/// For reference-counted types (lists, (big) strings, recursive tags), owning a value
|
||||
/// means incrementing its reference count. Hence, we prefer borrowing for these types
|
||||
fn from_layout(layout: &Layout) -> Self {
|
||||
match layout.is_refcounted() {
|
||||
true => Ownership::Borrowed,
|
||||
false => Ownership::Owned,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn infer_borrow<'a>(
|
||||
arena: &'a Bump,
|
||||
procs: &MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||
|
@ -106,7 +116,7 @@ pub struct ParamOffset(usize);
|
|||
|
||||
impl From<ParamOffset> for usize {
|
||||
fn from(id: ParamOffset) -> Self {
|
||||
id.0 as usize
|
||||
id.0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,7 +230,7 @@ impl<'a> ParamMap<'a> {
|
|||
fn init_borrow_params(arena: &'a Bump, ps: &'a [Param<'a>]) -> &'a [Param<'a>] {
|
||||
Vec::from_iter_in(
|
||||
ps.iter().map(|p| Param {
|
||||
borrow: p.layout.is_refcounted(),
|
||||
ownership: Ownership::from_layout(&p.layout),
|
||||
layout: p.layout,
|
||||
symbol: p.symbol,
|
||||
}),
|
||||
|
@ -232,7 +242,7 @@ impl<'a> ParamMap<'a> {
|
|||
fn init_borrow_args(arena: &'a Bump, ps: &'a [(Layout<'a>, Symbol)]) -> &'a [Param<'a>] {
|
||||
Vec::from_iter_in(
|
||||
ps.iter().map(|(layout, symbol)| Param {
|
||||
borrow: should_borrow_layout(layout),
|
||||
ownership: Ownership::from_layout(layout),
|
||||
layout: *layout,
|
||||
symbol: *symbol,
|
||||
}),
|
||||
|
@ -247,7 +257,7 @@ impl<'a> ParamMap<'a> {
|
|||
) -> &'a [Param<'a>] {
|
||||
Vec::from_iter_in(
|
||||
ps.iter().map(|(layout, symbol)| Param {
|
||||
borrow: false,
|
||||
ownership: Ownership::Owned,
|
||||
layout: *layout,
|
||||
symbol: *symbol,
|
||||
}),
|
||||
|
@ -390,12 +400,12 @@ impl<'a> BorrowInfState<'a> {
|
|||
fn update_param_map_help(&mut self, ps: &[Param<'a>]) -> &'a [Param<'a>] {
|
||||
let mut new_ps = Vec::with_capacity_in(ps.len(), self.arena);
|
||||
new_ps.extend(ps.iter().map(|p| {
|
||||
if !p.borrow {
|
||||
if p.ownership == Ownership::Owned {
|
||||
*p
|
||||
} else if self.is_owned(p.symbol) {
|
||||
self.modified = true;
|
||||
let mut p = *p;
|
||||
p.borrow = false;
|
||||
p.ownership = Ownership::Owned;
|
||||
|
||||
p
|
||||
} else {
|
||||
|
@ -412,15 +422,15 @@ impl<'a> BorrowInfState<'a> {
|
|||
start: ParamOffset,
|
||||
length: usize,
|
||||
) {
|
||||
let index: usize = start.into();
|
||||
let ParamOffset(index) = start;
|
||||
let ps = &mut param_map.declarations[index..][..length];
|
||||
|
||||
for p in ps.iter_mut() {
|
||||
if !p.borrow {
|
||||
if p.ownership == Ownership::Owned {
|
||||
// do nothing
|
||||
} else if self.is_owned(p.symbol) {
|
||||
self.modified = true;
|
||||
p.borrow = false;
|
||||
p.ownership = Ownership::Owned;
|
||||
} else {
|
||||
// do nothing
|
||||
}
|
||||
|
@ -440,7 +450,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
debug_assert_eq!(xs.len(), ps.len());
|
||||
|
||||
for (x, p) in xs.iter().zip(ps.iter()) {
|
||||
if !p.borrow {
|
||||
if p.ownership == Ownership::Owned {
|
||||
self.own_var(*x);
|
||||
}
|
||||
}
|
||||
|
@ -568,44 +578,44 @@ impl<'a> BorrowInfState<'a> {
|
|||
match op {
|
||||
ListMap { xs } => {
|
||||
// own the list if the function wants to own the element
|
||||
if !function_ps[0].borrow {
|
||||
if function_ps[0].ownership == Ownership::Owned {
|
||||
self.own_var(*xs);
|
||||
}
|
||||
}
|
||||
ListMap2 { xs, ys } => {
|
||||
// own the lists if the function wants to own the element
|
||||
if !function_ps[0].borrow {
|
||||
if function_ps[0].ownership == Ownership::Owned {
|
||||
self.own_var(*xs);
|
||||
}
|
||||
|
||||
if !function_ps[1].borrow {
|
||||
if function_ps[1].ownership == Ownership::Owned {
|
||||
self.own_var(*ys);
|
||||
}
|
||||
}
|
||||
ListMap3 { xs, ys, zs } => {
|
||||
// own the lists if the function wants to own the element
|
||||
if !function_ps[0].borrow {
|
||||
if function_ps[0].ownership == Ownership::Owned {
|
||||
self.own_var(*xs);
|
||||
}
|
||||
if !function_ps[1].borrow {
|
||||
if function_ps[1].ownership == Ownership::Owned {
|
||||
self.own_var(*ys);
|
||||
}
|
||||
if !function_ps[2].borrow {
|
||||
if function_ps[2].ownership == Ownership::Owned {
|
||||
self.own_var(*zs);
|
||||
}
|
||||
}
|
||||
ListMap4 { xs, ys, zs, ws } => {
|
||||
// own the lists if the function wants to own the element
|
||||
if !function_ps[0].borrow {
|
||||
if function_ps[0].ownership == Ownership::Owned {
|
||||
self.own_var(*xs);
|
||||
}
|
||||
if !function_ps[1].borrow {
|
||||
if function_ps[1].ownership == Ownership::Owned {
|
||||
self.own_var(*ys);
|
||||
}
|
||||
if !function_ps[2].borrow {
|
||||
if function_ps[2].ownership == Ownership::Owned {
|
||||
self.own_var(*zs);
|
||||
}
|
||||
if !function_ps[3].borrow {
|
||||
if function_ps[3].ownership == Ownership::Owned {
|
||||
self.own_var(*ws);
|
||||
}
|
||||
}
|
||||
|
@ -617,7 +627,9 @@ impl<'a> BorrowInfState<'a> {
|
|||
|
||||
// own the closure environment if the function needs to own it
|
||||
let function_env_position = op.function_arity();
|
||||
if let Some(false) = function_ps.get(function_env_position).map(|p| p.borrow) {
|
||||
if let Some(Ownership::Owned) =
|
||||
function_ps.get(function_env_position).map(|p| p.ownership)
|
||||
{
|
||||
self.own_var(passed_function.captured_environment);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use bumpalo::collections::vec::Vec;
|
|||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::{IdentIds, Symbol};
|
||||
|
||||
use crate::borrow::Ownership;
|
||||
use crate::ir::{
|
||||
BranchInfo, Call, CallType, Expr, JoinPointId, Literal, Param, Stmt, UpdateModeId,
|
||||
};
|
||||
|
@ -418,7 +419,7 @@ fn eq_tag_union_help<'a>(
|
|||
} else {
|
||||
let loop_params_iter = operands.iter().map(|arg| Param {
|
||||
symbol: *arg,
|
||||
borrow: true,
|
||||
ownership: Ownership::Borrowed,
|
||||
layout: Layout::Union(union_layout),
|
||||
});
|
||||
|
||||
|
@ -718,13 +719,13 @@ fn eq_list<'a>(
|
|||
|
||||
let param_addr1 = Param {
|
||||
symbol: addr1,
|
||||
borrow: false,
|
||||
ownership: Ownership::Owned,
|
||||
layout: layout_isize,
|
||||
};
|
||||
|
||||
let param_addr2 = Param {
|
||||
symbol: addr2,
|
||||
borrow: false,
|
||||
ownership: Ownership::Owned,
|
||||
layout: layout_isize,
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use roc_module::low_level::{LowLevel, LowLevel::*};
|
|||
use roc_module::symbol::{IdentIds, Symbol};
|
||||
use roc_target::PtrWidth;
|
||||
|
||||
use crate::borrow::Ownership;
|
||||
use crate::code_gen_help::let_lowlevel;
|
||||
use crate::ir::{
|
||||
BranchInfo, Call, CallType, Expr, JoinPointId, Literal, ModifyRc, Param, Stmt, UpdateModeId,
|
||||
|
@ -944,7 +945,7 @@ fn refcount_list_elems<'a>(
|
|||
|
||||
let param_addr = Param {
|
||||
symbol: addr,
|
||||
borrow: false,
|
||||
ownership: Ownership::Owned,
|
||||
layout: layout_isize,
|
||||
};
|
||||
|
||||
|
@ -1602,7 +1603,7 @@ fn refcount_union_tailrec<'a>(
|
|||
|
||||
let jp_param = Param {
|
||||
symbol: next_ptr,
|
||||
borrow: true,
|
||||
ownership: Ownership::Borrowed,
|
||||
layout,
|
||||
};
|
||||
|
||||
|
@ -1622,7 +1623,7 @@ fn refcount_union_tailrec<'a>(
|
|||
let loop_init = Stmt::Jump(tailrec_loop, root.arena.alloc([initial_structure]));
|
||||
let loop_param = Param {
|
||||
symbol: current,
|
||||
borrow: true,
|
||||
ownership: Ownership::Borrowed,
|
||||
layout: Layout::Union(union_layout),
|
||||
};
|
||||
|
||||
|
|
|
@ -347,7 +347,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
|||
for Param {
|
||||
symbol,
|
||||
layout,
|
||||
borrow: _,
|
||||
ownership: _,
|
||||
} in parameters
|
||||
{
|
||||
ctx.insert(*symbol, *layout);
|
||||
|
@ -369,7 +369,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
|||
for (arg, param) in symbols.iter().zip(parameters.iter()) {
|
||||
let Param {
|
||||
symbol: _,
|
||||
borrow: _,
|
||||
ownership: _,
|
||||
layout,
|
||||
} = param;
|
||||
self.check_sym_layout(*arg, *layout, UseKind::JumpArg);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::borrow::Ownership;
|
||||
use crate::ir::{
|
||||
build_list_index_probe, BranchInfo, Call, CallType, DestructType, Env, Expr, JoinPointId,
|
||||
ListIndex, Literal, Param, Pattern, Procs, Stmt,
|
||||
|
@ -1906,7 +1907,7 @@ fn decide_to_branching<'a>(
|
|||
let param = Param {
|
||||
symbol: test_symbol,
|
||||
layout: Layout::Builtin(Builtin::Bool),
|
||||
borrow: false,
|
||||
ownership: Ownership::Owned,
|
||||
};
|
||||
|
||||
let join = Stmt::Join {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::borrow::{ParamMap, BORROWED, OWNED};
|
||||
use crate::borrow::{Ownership, ParamMap, BORROWED, OWNED};
|
||||
use crate::ir::{
|
||||
CallType, Expr, HigherOrderLowLevel, JoinPointId, ModifyRc, Param, Proc, ProcLayout, Stmt,
|
||||
UpdateModeIds,
|
||||
|
@ -61,13 +61,13 @@ impl DataFunction {
|
|||
use DataFunction::*;
|
||||
|
||||
let data_borrowed = !vars[&lowlevel_argument].consume;
|
||||
let function_borrows = passed_function_argument.borrow;
|
||||
let function_ownership = passed_function_argument.ownership;
|
||||
|
||||
match (data_borrowed, function_borrows) {
|
||||
(BORROWED, BORROWED) => DataBorrowedFunctionBorrows,
|
||||
(BORROWED, OWNED) => DataBorrowedFunctionOwns,
|
||||
(OWNED, BORROWED) => DataOwnedFunctionBorrows,
|
||||
(OWNED, OWNED) => DataOwnedFunctionOwns,
|
||||
match (data_borrowed, function_ownership) {
|
||||
(BORROWED, Ownership::Borrowed) => DataBorrowedFunctionBorrows,
|
||||
(BORROWED, Ownership::Owned) => DataBorrowedFunctionOwns,
|
||||
(OWNED, Ownership::Borrowed) => DataOwnedFunctionBorrows,
|
||||
(OWNED, Ownership::Owned) => DataOwnedFunctionOwns,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -302,7 +302,10 @@ where
|
|||
fn is_borrow_param(x: Symbol, ys: &[Symbol], ps: &[Param]) -> bool {
|
||||
// default to owned arguments
|
||||
let is_owned = |i: usize| match ps.get(i) {
|
||||
Some(param) => !param.borrow,
|
||||
Some(param) => match param.ownership {
|
||||
Ownership::Owned => true,
|
||||
Ownership::Borrowed => false,
|
||||
},
|
||||
None => unreachable!("or?"),
|
||||
};
|
||||
is_borrow_param_help(x, ys, is_owned)
|
||||
|
@ -473,7 +476,10 @@ impl<'a, 'i> Context<'a, 'i> {
|
|||
) -> &'a Stmt<'a> {
|
||||
// default to owned arguments
|
||||
let pred = |i: usize| match ps.get(i) {
|
||||
Some(param) => !param.borrow,
|
||||
Some(param) => match param.ownership {
|
||||
Ownership::Owned => true,
|
||||
Ownership::Borrowed => false,
|
||||
},
|
||||
None => unreachable!("or?"),
|
||||
};
|
||||
self.add_inc_before_help(xs, pred, b, live_vars_after)
|
||||
|
@ -992,7 +998,10 @@ impl<'a, 'i> Context<'a, 'i> {
|
|||
for p in ps.iter() {
|
||||
let info = VarInfo {
|
||||
reference: p.layout.contains_refcounted(self.layout_interner),
|
||||
consume: !p.borrow,
|
||||
consume: match p.ownership {
|
||||
Ownership::Owned => true,
|
||||
Ownership::Borrowed => false,
|
||||
},
|
||||
persistent: false,
|
||||
reset: false,
|
||||
};
|
||||
|
@ -1014,7 +1023,7 @@ impl<'a, 'i> Context<'a, 'i> {
|
|||
b_live_vars: &LiveVarSet,
|
||||
) -> &'a Stmt<'a> {
|
||||
for p in ps.iter() {
|
||||
if !p.borrow
|
||||
if p.ownership == Ownership::Owned
|
||||
&& p.layout.contains_refcounted(self.layout_interner)
|
||||
&& !b_live_vars.contains(&p.symbol)
|
||||
{
|
||||
|
@ -1334,7 +1343,7 @@ fn create_holl_call<'a>(
|
|||
arguments: &'a [Symbol],
|
||||
) -> Expr<'a> {
|
||||
let call = crate::ir::Call {
|
||||
call_type: if let Some(OWNED) = param.map(|p| p.borrow) {
|
||||
call_type: if let Some(Ownership::Owned) = param.map(|p| p.ownership) {
|
||||
let mut passed_function = holl.passed_function;
|
||||
passed_function.owns_captured_environment = true;
|
||||
|
||||
|
@ -1519,7 +1528,7 @@ fn visit_proc<'a, 'i>(
|
|||
None => Vec::from_iter_in(
|
||||
proc.args.iter().cloned().map(|(layout, symbol)| Param {
|
||||
symbol,
|
||||
borrow: false,
|
||||
ownership: Ownership::Owned,
|
||||
layout,
|
||||
}),
|
||||
arena,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![allow(clippy::manual_map)]
|
||||
|
||||
use crate::borrow::Ownership;
|
||||
use crate::layout::{
|
||||
self, Builtin, ClosureCallOptions, ClosureRepresentation, EnumDispatch, LambdaName, LambdaSet,
|
||||
Layout, LayoutCache, LayoutInterner, LayoutProblem, Niche, RawFunctionLayout, STLayoutInterner,
|
||||
|
@ -1525,14 +1526,14 @@ pub struct JoinPointId(pub Symbol);
|
|||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct Param<'a> {
|
||||
pub symbol: Symbol,
|
||||
pub borrow: bool,
|
||||
pub ownership: Ownership,
|
||||
pub layout: Layout<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Param<'a> {
|
||||
pub const EMPTY: Self = Param {
|
||||
symbol: Symbol::EMPTY_PARAM,
|
||||
borrow: false,
|
||||
ownership: Ownership::Owned,
|
||||
layout: Layout::UNIT,
|
||||
};
|
||||
}
|
||||
|
@ -4545,7 +4546,7 @@ pub fn with_hole<'a>(
|
|||
let param = Param {
|
||||
symbol: assigned,
|
||||
layout,
|
||||
borrow: false,
|
||||
ownership: Ownership::Owned,
|
||||
};
|
||||
|
||||
Stmt::Join {
|
||||
|
@ -4610,7 +4611,7 @@ pub fn with_hole<'a>(
|
|||
let param = Param {
|
||||
symbol: assigned,
|
||||
layout,
|
||||
borrow: false,
|
||||
ownership: Ownership::Owned,
|
||||
};
|
||||
|
||||
Stmt::Join {
|
||||
|
@ -10402,7 +10403,7 @@ where
|
|||
let param = Param {
|
||||
symbol: assigned,
|
||||
layout: return_layout,
|
||||
borrow: false,
|
||||
ownership: Ownership::Owned,
|
||||
};
|
||||
|
||||
Stmt::Join {
|
||||
|
@ -10626,7 +10627,7 @@ fn union_lambda_set_to_switch<'a>(
|
|||
let param = Param {
|
||||
symbol: assigned,
|
||||
layout: *return_layout,
|
||||
borrow: false,
|
||||
ownership: Ownership::Owned,
|
||||
};
|
||||
|
||||
Stmt::Join {
|
||||
|
@ -10777,7 +10778,7 @@ fn enum_lambda_set_to_switch<'a>(
|
|||
let param = Param {
|
||||
symbol: assigned,
|
||||
layout: *return_layout,
|
||||
borrow: false,
|
||||
ownership: Ownership::Owned,
|
||||
};
|
||||
|
||||
Stmt::Join {
|
||||
|
@ -10880,7 +10881,7 @@ where
|
|||
let param = Param {
|
||||
symbol: assigned,
|
||||
layout: return_layout,
|
||||
borrow: false,
|
||||
ownership: Ownership::Owned,
|
||||
};
|
||||
|
||||
Stmt::Join {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![allow(clippy::manual_map)]
|
||||
|
||||
use crate::borrow::Ownership;
|
||||
use crate::ir::{CallType, Expr, JoinPointId, Param, Stmt};
|
||||
use crate::layout::{LambdaName, Layout};
|
||||
use bumpalo::collections::Vec;
|
||||
|
@ -46,7 +47,7 @@ pub fn make_tail_recursive<'a>(
|
|||
args.iter().map(|(layout, symbol, _)| Param {
|
||||
symbol: *symbol,
|
||||
layout: *layout,
|
||||
borrow: true,
|
||||
ownership: Ownership::Borrowed,
|
||||
}),
|
||||
arena,
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue