"into" function parameters

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

  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

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

into the desugared code you want

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