# "into" function parameters

**URL:** <https://internals.rust-lang.org/t/into-function-parameters/17870>\
**Category:** language design\
**Created:** [November 29, 2022, 1:49pm UTC](https://internals.rust-lang.org/t/into-function-parameters/17870 "2022-11-29T13:49:21Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![jvcmarcenes](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jvcmarcenes/32/11971_2.png) [@jvcmarcenes](https://internals.rust-lang.org/u/jvcmarcenes)\
**Post date:** [November 29, 2022, 1:49pm UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/1 "2022-11-29T13:49:21Z")

</div>

i very often find myself doing the following for ergonomics:

```rust
fn foo(a: impl Into<A>, b: impl Into<B>) {
  let a: A = a.into();
  let b: B = b.into();
  // ...
}

```

since rust doesn't allow for function overloading (which i think is a great decision), we have to reach for traits such as `Into`, `TryInto`, `AsRef` and etc when we want to allow our function to take more than one type, it's a clever pattern, but it can become boilerplaity and annoying to write.

I wish we had syntactical sugar for this, something like:

```rust
fn foo(a: into A, b: into B) {
  // ...
}

```

the above code would be equivalent to the previous `foo` fn. `into` would be a new keyword that could be applied to fn parameters, it would accept any type that implemts `Into<T>`, and would perform the conversion implicitly

---

<div class="post-metadata">

**Author:** ![elidupree](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/elidupree/32/4304_2.png) [@elidupree](https://internals.rust-lang.org/u/elidupree)\
**Post date:** [November 29, 2022, 2:17pm UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/2 "2022-11-29T14:17:47Z")

</div>

I've used this pattern myself! I have some functions that are meaningful to optimize by monomorphizing them with a constant input (I tested), but can't be inlined, so I gave them exactly such a generic parameter, so you can pass a ZST that represents a constant value.

Unfortunately, although the boilerplate is annoying, I don't think it's worth adding a language feature for it. This is a relatively rare pattern with only a small amount of boilerplate, and such a feature would add to the complexity of the language (creating more work for both Rust learners and procedural macro writers).

It would be possible to implement this as a procedural macro, though. If you have a project where you use this a lot, and are willing to dig into the complexity of writing procedural macros, you could make a macro that lets you do this:

```rust
#[auto_into]
fn foo(a: into A, b: into B) {
  // ...
}

```

or perhaps this, so that you don't have to complicate the parsing:

```rust
#[auto_into]
fn foo(a: impl Into<A>, b: impl Into<B>) {
  // the macro just automatically inserts the lines:
  // let a: A = a.into();
  // let b: B = b.into();
  // ...
}

```

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [November 29, 2022, 2:19pm UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/3 "2022-11-29T14:19:00Z")

</div>

> [@jvcmarcenes](#):
>
> but it can become boilerplaity

When I first read this, I thought you were referring to the need to possibly even define your own traits in cases where standard library ones don’t suffice, and/or at least the need to write trait impls for relevant types.

* * *

Just for writing the function signature, the sugar `impl Into<A>` is already sufficient, and also way more general than something like “into A” involving a new keyword and working only with one single trait (`Into`).

Admitted… the implicit conversion part _does_ remove some relevant boilerplate, admitted; but the disadvantage is that you don’t control the `.into` calls so well anymore… the order would be chosen by the compiler, and the calls would happen unconditionally at the beginning at the function. Maybe still fine for `Into`, but you also mention `TryInto` which you would need to do error handling for (or keep a `Result` in the variable?)… and as indicated above, if the proposal is to special-handle _only_ `Into`, then I’d say, `Into` is not really special enough, and also – in my opinion – possibly intended more for manual calls than for function signatures anyways, one reason being that the call can be a bit costly _(e.g. involving allocations and sometimes copying data)_. (E.g. there’s no `impl Into` function arguments in standard library functions as far as I’m aware, whereas `AsRef` ones _do_ exist, particularly around file path APIs.)

To counter the point of usefulness of removing

```rust
  let a: A = a.into();
  let b: B = b.into();

```

boilerplate: quite often you don’t even need it; particularly in case the resulting value has only a single use, it can be inlined there and wouldn’t need the new variable `a`.

Also, Rust’s macro system is quite powerful; I assume it’s quite straightforward (and perhaps a fun exercise if you _do_ find a lot of use-cases) to write a proc-macro using the `syn` crate that can transform something similar-looking, e.g. something as follows

```rust
#[into_sugar]
fn foo(a: #[into] A, b: #[into] B) {
  // ...
}

```

into the desugared code you want

```rust
fn foo(a: impl Into<A>, b: impl Into<B>) {
  let a: A = a.into();
  let b: B = b.into();
  // ...
}
```

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [November 29, 2022, 2:28pm UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/4 "2022-11-29T14:28:23Z")

</div>

As a (way more) general approach, I believe there’s value in some “view-pattern” (stealing Haskell terminology) type feature of applying functions (and possibly pattern matching the result) in patterns. And also a `pattern: Type` syntactic element could be made to support being generated by a single macro call.

If this became a thing, then some syntax… let’s call it “`Into(x)`” as a stand-in (or maybe even an actual user-defined “pattern alias”) could be a pattern that applies `into()`; i.e. `let Into(x) = foo();` is like `let x = Into::into(foo());`, and – if necessary – a trivial `macro_rules` macro could translate something like `foo(into!(a: A))` into `foo(Into(a): impl Into<A>)`.

The downside to view patterns (and maybe a reason we don’t have them? _I would need to look for relevant discussions…_) include the abovementioned aspects of giving up control and not allowing error handling.\[1\]

* * *

1. In comparison, Haskell (a purely functional language) doesn’t have side-effects, and has lazy evaluation, so giving up explicit control about when which things are executed is kind of universally the case anyways, and there aren’t relevant side-effects to worry about either, at least making the order of execution fairly irrelevant.

---

<div class="post-metadata">

**Author:** ![afetisov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/afetisov/32/8508_2.png) [@afetisov](https://internals.rust-lang.org/u/afetisov)\
**Post date:** [November 29, 2022, 4:19pm UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/5 "2022-11-29T16:19:36Z")

</div>

Writing the signature as `fn foo(a: impl Into<A>, b: impl Into<B>)` is an antipattern. You turn a perfectly fine function with concrete type signature into a generic function, which can no longer do type inference (because it isn't known what should be the type which impls `Into`), causes binary bloat and compile time bloat, and can't be used in many contexts, such as methods on trait objects, extern functions or function pointers.

_Very rarely_ it is indeed the best solution, but if you're writing it often enough to want some _minor_ syntax sugar (4 characters instead of 10), then you're designing you API wrong. It's not an issue to call `into()` conversion at use site, it gives more flexibility to the consumer, it doesn't have any syntactic, runtime or compile-time overhead if your already have a variable of correct type, and shouldn't need to happens that often in the first place, if you choose the argument types properly.

If you _really_ often need to use such generic arguments, then there is something big going on, which likely demands a proper solution: enums for option enumeration, or special-case traits which convey the semantics of your operations and are much more controllable than `Into`.

---

<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 29, 2022, 5:42pm UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/6 "2022-11-29T17:42:52Z")

</div>

BTW, you don't need the type hint in `let`, because generics eliminate all other possibilities, so there's only one unambiguous `into()` that you can call on the generic type.

---

<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 29, 2022, 6:08pm UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/7 "2022-11-29T18:08:24Z")

</div>

Remember that you're paying a potentially-not-insubstantial compile-time and monomorphization-bloat cost to save a `.into()` in the caller when doing this. Personally I think it's often an anti-pattern.

If you choose to use a macro for this, be sure it desugars _not_ into

```rust
fn foo(a: impl Into<A>, b: impl Into<B>) {
  let a: A = a.into();
  let b: B = b.into();
  … body …
}

```

but into

```rust
fn foo(a: impl Into<A>, b: impl Into<B>) {
  return inner(a.into(), b.into());
  fn inner(a: A, b: B) {
    … body …
  }
}

```

---

<div class="post-metadata">

**Author:** ![toc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/toc/32/6692_2.png) [@toc](https://internals.rust-lang.org/u/toc)\
**Post date:** [November 29, 2022, 7:11pm UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/8 "2022-11-29T19:11:03Z")

</div>

> [@scottmcm](#):
>
> ```rust
> fn foo(a: impl Into<A>, b: impl Into<B>) {
> return inner(a.into(), b.into());
> fn inner(a: A, b: B) {
> … body …
> }
> }
> 
> ```

I don't know what category this falls into, but this would be a fantastic code size optimization(?) pass.

---

<div class="post-metadata">

**Author:** ![mejrs](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mejrs/32/14434_2.png) [@mejrs](https://internals.rust-lang.org/u/mejrs)\
**Post date:** [November 29, 2022, 7:56pm UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/9 "2022-11-29T19:56:47Z")

</div>

> [@steffahn](#):
>
> E.g. there’s no `impl Into` function arguments in standard library functions as far as I’m aware

[CString in std::ffi - Rust](https://doc.rust-lang.org/std/ffi/struct.CString.html#method.new) is one that I am aware of.

---

<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 29, 2022, 8:34pm UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/10 "2022-11-29T20:34:40Z")

</div>

> [@toc](#):
>
> I don't know what category this falls into

The general pattern is polymorphization ([A-polymorphization](https://github.com/rust-lang/rust/labels/A-polymorphization), [wg-polymorphization](https://rust-lang.github.io/compiler-team/working-groups/polymorphization/)), and rustc does have the experimental capability to do some MIR polymorphization behind the `-Zpolymorphize` flag.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [November 29, 2022, 10:48pm UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/11 "2022-11-29T22:48:43Z")

</div>

Thanks, TIL.

---

<div class="post-metadata">

**Author:** ![samsieber](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/samsieber/32/4671_2.png) [@samsieber](https://internals.rust-lang.org/u/samsieber)\
**Post date:** [November 30, 2022, 12:26am UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/12 "2022-11-30T00:26:10Z")

</div>

Relatedly, there's a macro crate that converts the first form into the second form (roughly speaking):

[https://llogiq.github.io/2019/05/18/momo.html](https://llogiq.github.io/2019/05/18/momo.html)

---

<div class="post-metadata">

**Author:** ![jvcmarcenes](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jvcmarcenes/32/11971_2.png) [@jvcmarcenes](https://internals.rust-lang.org/u/jvcmarcenes)\
**Post date:** [December 1, 2022, 3:18am UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/13 "2022-12-01T03:18:52Z")

</div>

you know what, fair enough. guess there was a lot i didn't know about and i see now why this wouldn't be a desirable feature.

however, i did write that macro: [auto\_into](https://crates.io/crates/auto_into)

---

<div class="post-metadata">

**Author:** ![jvcmarcenes](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jvcmarcenes/32/11971_2.png) [@jvcmarcenes](https://internals.rust-lang.org/u/jvcmarcenes)\
**Post date:** [December 1, 2022, 3:19am UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/14 "2022-12-01T03:19:31Z")

</div>

wait, what's the diference between the 2 code examples here?

> [@scottmcm](#):
>
> If you choose to use a macro for this, be sure it desugars _not_ into
> 
> ```rust
> fn foo(a: impl Into<A>, b: impl Into<B>) {
> let a: A = a.into();
> let b: B = b.into();
> … body …
> }
> 
> ```
> 
> but into
> 
> ```rust
> fn foo(a: impl Into<A>, b: impl Into<B>) {
> return inner(a.into(), b.into());
> fn inner(a: A, b: B) {
> … body …
> }
> }
> 
> ```

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [December 1, 2022, 3:44am UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/15 "2022-12-01T03:44:05Z")

</div>

In the first one, `foo` is a gigantic function and is copied for each distinct input types given. The second is a single inner function for `A` and `B` specifically with some tiny glue code that is copied for each distinct input types given.

---

<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:** [March 1, 2023, 3:44am UTC](https://internals.rust-lang.org/t/into-function-parameters/17870/16 "2023-03-01T03:44:28Z")

</div>

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