Zulip Chat Archive

Stream: lean4

Topic: Reference counting instructions for cases


Mario Carneiro (May 07 2021 at 10:32):

I don't have a very good understanding of the reference counting instructions so this may be a misunderstanding on my part, but I think this might be a bug:

set_option trace.compiler.ir.result true in
def foo (x : Option Unit × Unit) : Unit × Unit :=
  match x.1 with
  | none => ((), ())
  | some _ => ((), x.2)

def foo (x_1 : obj) : obj :=
  let x_2 : obj := proj[0] x_1;
  inc x_2;
  case x_2 : obj of
  Option.none 
    dec x_1;
    let x_3 : obj := foo._closed_1;
    ret x_3
  Option.some 
    dec x_2;
    let x_4 : u8 := isShared x_1;
    case x_4 : u8 of
    Bool.false 
      let x_5 : obj := proj[0] x_1;
      dec x_5;
      let x_6 : obj := ctor_0[PUnit.unit];
      set x_1[0] := x_6;
      ret x_1
    Bool.true 
      let x_7 : obj := proj[1] x_1;
      inc x_7;
      dec x_1;
      let x_8 : obj := ctor_0[PUnit.unit];
      let x_9 : obj := ctor_0[Prod.mk] x_8 x_7;
      ret x_9

This has been minimized, but the part I want to point out is that in the none case, inc x_2 is called but there is no corresponding dec x_2 later. This only seems to happen for nullary variants of a data-carrying inductive, like none in this case.

Sebastian Ullrich (May 07 2021 at 11:20):

Option.none is unboxed, so there is nothing to free

Sebastian Ullrich (May 07 2021 at 11:21):

If there was such a fundamental memory leak, I do hope the leak sanitizer would have found it :)

Sebastian Ullrich (May 07 2021 at 11:56):

The inc/dec x_2 could theoretically be elided, but that would need some borrow checker-like analysis of x_2's lifetime being dominated by x_1's.


Last updated: Dec 20 2023 at 11:08 UTC