# Block inlining vs method inlining

**URL:** <https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721>\
**Category:** Help & Support\
**Created:** [February 16, 2020, 8:10am UTC](https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721 "2020-02-16T08:10:13Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![fxn](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fxn/32/1128_2.png) [@fxn](https://forum.crystal-lang.org/u/fxn)\
**Post date:** [February 16, 2020, 8:10am UTC](https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721/1 "2020-02-16T08:10:13Z")

</div>

Documentation stresses that blocks are always inlined. So, given this code:

```auto
module M
  def self.s
    t = 0.0

    N.r do |x|
      t += x
    end

    t
  end
end

module N
  F = 7.5

  def self.r
    t = 2.0
    while (x = rand) < 0.8
      yield x*t*F
    end
  end
end

```

if I understand the docs correctly, the method `M.s` ends up being something like this (conceptually):

```auto
def self.s
  t = 0.0

  __t = 2.0
  while (__x = rand) < 0.8
    x = __x*__ t*::N::F
    t += x
  end

  t
end

```

(Of course, the convention `__` is not meant to be literally that way, it means “somehow the variables do not clash”.)

Wouldn’t you call that “method inlining”? That is what I visualize when a compiler optimization inlines functions in C or Erlang.

Would it be more correct to say: “methods that accept a block are inlined”?

---

<div class="post-metadata">

**Author:** ![jhass](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jhass/32/1779_2.png) [@jhass](https://forum.crystal-lang.org/u/jhass)\
**Post date:** [February 16, 2020, 9:32am UTC](https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721/2 "2020-02-16T09:32:22Z")

</div>

No, it works the other way around. `s` will turn into something like

```auto
  def self.s
    t = 0.0

    N.r__1(out t)

    t
  end

```

and a `r` will be generated for each distinct block it’s passed, so `r__1` turns into something like:

```auto
  def self.r__1(__t)
    t = 2.0
    while (x = rand) < 0.8
      __x = x*t*F
      __t +=__ x
    end
  end

```

It’s is very similar to method inlining, just it’s not the block causing a method to be inlined, it itself is the method being inlined.

---

<div class="post-metadata">

**Author:** ![fxn](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fxn/32/1128_2.png) [@fxn](https://forum.crystal-lang.org/u/fxn)\
**Post date:** [February 16, 2020, 9:52am UTC](https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721/3 "2020-02-16T09:52:24Z")

</div>

Really! I believe [this section](https://crystal-lang.org/reference/syntax_and_semantics/blocks_and_procs.html#performance) of the reference is not very clear then.

You really define a function for every single call site of the method? Every `each` call in the whole Crystal stdlib and user’s code creates a distinct `each` method?

Was that `out` pseudo-code for closured variables? What happens with `self`? That connects with the discussion in [Performance struct vs class](https://forum.crystal-lang.org/t/performance-struct-vs-class/1715/14).

---

<div class="post-metadata">

**Author:** ![jhass](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jhass/32/1779_2.png) [@jhass](https://forum.crystal-lang.org/u/jhass)\
**Post date:** [February 16, 2020, 10:01am UTC](https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721/4 "2020-02-16T10:01:15Z")

</div>

> You really define a function for every single call site of the method? Every `each` call in the whole Crystal stdlib and user’s code creates a distinct `each` method?

As far as I’m aware, yes.

> Was that `out` pseudo-code for closured variables? What happens with `self` ?

Yes, consider that very pseudo code, I don’t think there’s valid Crystal code to emulate what really happens :) I just meant to indicate that `__t` is the callside’s `t`. You can imagine the generated method somehow has full access to the callsite’s scope, in the case of a closuring block anyways.

---

<div class="post-metadata">

**Author:** ![fxn](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fxn/32/1128_2.png) [@fxn](https://forum.crystal-lang.org/u/fxn)\
**Post date:** [February 16, 2020, 10:19am UTC](https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721/5 "2020-02-16T10:19:56Z")

</div>

Glad I asked! I had it backwards!

So I went full circle. First, I imagined literal block inlining. Since blocks are generally different, the obvious meaning of “inlining” made no sense, and then the examples in the reference made me think it was the method being inlined. So, I am back at “each call site invokes a copy of the original method with the block inlined and closured vars, constants, self, etc. working as expected”, whatever that technically really translates to.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [February 16, 2020, 10:27am UTC](https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721/6 "2020-02-16T10:27:29Z")

</div>

It actually works as Xavier says. Blocks with yield don’t generate new method definitions. They are inlined.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [February 16, 2020, 10:28am UTC](https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721/7 "2020-02-16T10:28:59Z")

</div>

This can also be seen if you generate LLVM IR code: you won’t find a definition of `r` (nor nothing similar to it). And `s` will have part of `r` inlined in it.

---

<div class="post-metadata">

**Author:** ![fxn](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fxn/32/1128_2.png) [@fxn](https://forum.crystal-lang.org/u/fxn)\
**Post date:** [February 16, 2020, 10:33am UTC](https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721/8 "2020-02-16T10:33:03Z")

</div>

That’s interesting! So since the method that yields is _always_ inlined, the method does not even need to exist at all in the final program.

---

<div class="post-metadata">

**Author:** ![jhass](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jhass/32/1779_2.png) [@jhass](https://forum.crystal-lang.org/u/jhass)\
**Post date:** [February 16, 2020, 10:41am UTC](https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721/9 "2020-02-16T10:41:17Z")

</div>

Oh sorry, I didn’t realize! Ignore everything I said then :D

---

<div class="post-metadata">

**Author:** ![ComputerMage](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/computermage/32/719_2.png) [@ComputerMage](https://forum.crystal-lang.org/u/ComputerMage)\
**Post date:** [February 16, 2020, 12:17pm UTC](https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721/10 "2020-02-16T12:17:28Z")

</div>

When I was working on debugger and debugging compilter I was looking explicitly on

visit(Yield)

> <https://github.com/crystal-lang/crystal/blob/master/src/compiler/crystal/codegen/codegen.cr#L1399>

and

codegen\_with\_block:

> <https://github.com/crystal-lang/crystal/blob/master/src/compiler/crystal/codegen/call.cr#L252>

it was clear that it is inlining in case if it is a block. Also when I was looking into generated IR code for methods with blocks it shows you the code as inlined.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [February 16, 2020, 12:20pm UTC](https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721/11 "2020-02-16T12:20:02Z")

</div>

> [@jhass](#):
>
> Oh sorry, I didn’t realize! Ignore everything I said then :D

No problem! It’s not explained anywhere so you could only guess.

---

<div class="post-metadata">

**Author:** ![ComputerMage](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/computermage/32/719_2.png) [@ComputerMage](https://forum.crystal-lang.org/u/ComputerMage)\
**Post date:** [February 16, 2020, 12:22pm UTC](https://forum.crystal-lang.org/t/block-inlining-vs-method-inlining/1721/12 "2020-02-16T12:22:09Z")

</div>

> [@jhass](#):
>
> Oh sorry, I didn’t realize! Ignore everything I said then :D

It took me a lot of time to realize it as I could not understand at that moment why local block variables was not shown in debugger and why crystal had a bug with methods with blocks when he was jumping somewhere in the local file instead of going into the file that contains the source code for that method.

Some bits and pieces from @asterite helped me to click all pieces to the whole picture.

So that section is correct though.
