diff --git a/compiler/mono/src/borrow.rs b/compiler/mono/src/borrow.rs index 70720c9130..780073ca16 100644 --- a/compiler/mono/src/borrow.rs +++ b/compiler/mono/src/borrow.rs @@ -261,6 +261,16 @@ impl<'a> BorrowInfState<'a> { } } + fn own_arg(&mut self, x: Symbol) { + self.own_var(x); + } + + fn own_args(&mut self, xs: &[Symbol]) { + for x in xs.iter() { + self.own_arg(*x); + } + } + /// For each xs[i], if xs[i] is owned, then mark ps[i] as owned. /// We use this action to preserve tail calls. That is, if we have /// a tail call `f xs`, if the i-th parameter is borrowed, but `xs[i]` is owned @@ -308,31 +318,33 @@ impl<'a> BorrowInfState<'a> { } = e; match call_type { - ByName { - name, arg_layouts, .. - } - | ByPointer { - name, arg_layouts, .. - } => { + ByName { name, .. } => { // get the borrow signature of the applied function - let ps = match self.param_map.get_symbol(*name) { - Some(slice) => slice, - None => Vec::from_iter_in( - arg_layouts.iter().cloned().map(|layout| Param { - symbol: Symbol::UNDERSCORE, - borrow: false, - layout, - }), - self.arena, - ) - .into_bump_slice(), - }; + match self.param_map.get_symbol(*name) { + Some(ps) => { + // the return value will be owned + self.own_var(z); + // if the function exects an owned argument (ps), the argument must be owned (args) + self.own_args_using_params(arguments, ps); + } + None => { + // this is really an indirect call, but the function was bound to a symbol + // the return value will be owned + self.own_var(z); + + // if the function exects an owned argument (ps), the argument must be owned (args) + self.own_args(arguments); + } + } + } + + ByPointer { .. } => { // the return value will be owned self.own_var(z); // if the function exects an owned argument (ps), the argument must be owned (args) - self.own_args_using_params(arguments, ps); + self.own_args(arguments); } LowLevel { op } => { diff --git a/compiler/mono/src/inc_dec.rs b/compiler/mono/src/inc_dec.rs index c8fb776ac9..a7413a9c60 100644 --- a/compiler/mono/src/inc_dec.rs +++ b/compiler/mono/src/inc_dec.rs @@ -466,35 +466,46 @@ impl<'a> Context<'a> { &*self.arena.alloc(Stmt::Let(z, v, l, b)) } - ByName { - name, arg_layouts, .. - } - | ByPointer { - name, arg_layouts, .. - } => { + ByName { name, .. } => { // get the borrow signature - let ps = match self.param_map.get_symbol(*name) { - Some(slice) => slice, - None => Vec::from_iter_in( - arg_layouts.iter().cloned().map(|layout| Param { - symbol: Symbol::UNDERSCORE, - borrow: false, - layout, - }), - self.arena, - ) - .into_bump_slice(), - }; + match self.param_map.get_symbol(*name) { + Some(ps) => { + let v = Expr::Call(crate::ir::Call { + call_type, + arguments, + }); + let b = self.add_dec_after_application(arguments, ps, b, b_live_vars); + let b = self.arena.alloc(Stmt::Let(z, v, l, b)); + + self.add_inc_before(arguments, ps, b, b_live_vars) + } + None => { + // an indirect call that was bound to a name + let v = Expr::Call(crate::ir::Call { + call_type, + arguments, + }); + + self.add_inc_before_consume_all( + arguments, + self.arena.alloc(Stmt::Let(z, v, l, b)), + b_live_vars, + ) + } + } + } + ByPointer { .. } => { let v = Expr::Call(crate::ir::Call { call_type, arguments, }); - let b = self.add_dec_after_application(arguments, ps, b, b_live_vars); - let b = self.arena.alloc(Stmt::Let(z, v, l, b)); - - self.add_inc_before(arguments, ps, b, b_live_vars) + self.add_inc_before_consume_all( + arguments, + self.arena.alloc(Stmt::Let(z, v, l, b)), + b_live_vars, + ) } } }