# Inner function sugar?

**URL:** <https://internals.rust-lang.org/t/inner-function-sugar/15628>\
**Category:** language design\
**Created:** [November 18, 2021, 7:43am UTC](https://internals.rust-lang.org/t/inner-function-sugar/15628 "2021-11-18T07:43:11Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![camsteffen](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/camsteffen/32/3246_2.png) [@camsteffen](https://internals.rust-lang.org/u/camsteffen)\
**Post date:** [November 18, 2021, 7:43am UTC](https://internals.rust-lang.org/t/inner-function-sugar/15628/1 "2021-11-18T07:43:11Z")

</div>

A common pattern in Rust is to use an inner function with fewer generic inputs to contain most of the outer function's implementation without the cost of monomorphization.

```rust
fn with_str(s: impl AsRef<str>) {
    fn inner(s: &str) {
        // lots of code
    }
    inner(s.as_ref());
}

```

This pattern feels pretty "noisy" and easy to resist. It adds a level of indentation to the entire function. Long function signatures have to be basically repeated. And the "first" line is (conventionally) moved to the bottom.

My understanding is that using a closure serves the same purpose, but Rust is currently not very efficient at reducing inherited generics in closures. (?) And closures mostly still have the same issues stated above.

My idea is to create a syntactic sugar for this:

```rust
fn with_str(s: impl AsRef<str>) {
    let s = s.as_ref();

    fn_boundary! // (straw man)
    dbg!(s);
    // lots of code
}

```

You can put the marker `fn_boundary!` anywhere as a statement. The remainder of the block "captures" the environment through a generated function invocation. You're code can be written in normal execution order and you don't have to write a function signature or add indentation. I suppose you could add attributes to the marker and they will be on the generated function.

And it isn't just useful for generics. There are scenarios where the first one or two lines of code are a good candidate to be inlined independently.

Maybe it is equivalent to wrapping the remainder with `move || {..}()`. And so maybe this could be a proc macro, but would a compiler feature be significantly faster? I'd like to hear more informed opinions.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [November 18, 2021, 12:09pm UTC](https://internals.rust-lang.org/t/inner-function-sugar/15628/2 "2021-11-18T12:09:58Z")

</div>

I don't think it needs a syntax. It's an optimization that the compiler should be able to do automatically.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [November 18, 2021, 8:23pm UTC](https://internals.rust-lang.org/t/inner-function-sugar/15628/3 "2021-11-18T20:23:15Z")

</div>

[momo](https://lib.rs/crates/momo) does this as a proc macro

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [November 18, 2021, 8:41pm UTC](https://internals.rust-lang.org/t/inner-function-sugar/15628/4 "2021-11-18T20:41:18Z")

</div>

> [@camsteffen](#):
>
> And the "first" line is (conventionally) moved to the bottom.

To chip away at this slightly, I think this bit we could actually fix. Right now having the inner function at the end counts as the trailing expression in the block, which is kinda weird -- that's certainly not what I expect every time I write it that way.

Maybe someone more familiar with the grammar could chime in and say whether it'd be ok for items at the end of the function body to not count like that?

Though I suppose if I want it at the beginning I can always do

```diff
 pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
+ return inner(path.as_ref())
     fn inner(path: &Path) -> io::Result<String> {
         let mut file = File::open(path)?;
         let mut string = String::with_capacity(initial_buffer_size(&file));
         file.read_to_string(&mut string)?;
         Ok(string)
     }
- inner(path.as_ref())
 }

```

so unless this is a trivial change it's probably not worth doing.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [February 16, 2022, 8:41pm UTC](https://internals.rust-lang.org/t/inner-function-sugar/15628/5 "2022-02-16T20:41:33Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
