# Move the generic type from the trait Into signature to the into method

**URL:** <https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502>\
**Category:** libs\
**Created:** [March 20, 2024, 4:28am UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502 "2024-03-20T04:28:55Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![10takla](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/10takla/32/11946_2.png) [@10takla](https://internals.rust-lang.org/u/10takla)\
**Post date:** [March 20, 2024, 4:28am UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/1 "2024-03-20T04:28:55Z")

</div>

Trait Into is not convenient.

**Introduction**

One of the most frequently used scenarios with trait Into is converting one type into another.

```rust
// point is of type Point
let vector: Vector = point.into();

```

This code works thanks to the automatic type determination mechanism. In this case, the _Vector_ type is explicitly annotated, and the Into trait uses the corresponding implementation of _Into_ for _Point_.

**Problem**

However, there are situations when automatic type determination does not work.

For example: `SomeOfVector::from(point.into())`

In such cases, it is necessary to explicitly specify the particular implementation of _Into_ for _Point_:

`SomeOfVector::from(<Point as Into<Vector>>::into(point))`

This expression turns out to be redundant and difficult to read.

**Solution**

To simplify usage, one can shift the responsibility for specifying the particular implementation of _Into_ from the trait signature to the method into signature. This is also semantically more correct. Instead of:

```rust
pub trait Into<T> {
   fn into(self) -> T;
}

```

One should use:

```rust
pub trait Into {
   fn into<I: From<Self>>(self) -> I
      where
        Self: Sized;
}

```

Just like in the standard implementation, it is necessary to implement Into for each type that has a From implementation:

```rust
impl<F> Into for F {
   fn into<I: From<F>>(self) -> I {
      I::from(self)
   }
}

```

Now type conversion becomes simpler and cleaner for any usage scenarios:

```rust
let vector: Vector = point.into();
let vector = point.into::<Vector>();
SomeOfVector::from(point.into::<Vector>())

```

---

<div class="post-metadata">

**Author:** ![quinedot](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/quinedot/32/7294_2.png) [@quinedot](https://internals.rust-lang.org/u/quinedot)\
**Post date:** [March 20, 2024, 4:57am UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/2 "2024-03-20T04:57:12Z")

</div>

> [@10takla](#):
>
> Solution

That's a massively breaking change.

There could be a standalone, turbofishable generic function in `std`, though.

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [March 20, 2024, 7:50am UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/3 "2024-03-20T07:50:12Z")

</div>

Is there a reason you can’t just use `From` instead when you need to annotate the target type?

```rust
SomeOfVector::from(Vector::from(point))

```

---

<div class="post-metadata">

**Author:** ![10takla](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/10takla/32/11946_2.png) [@10takla](https://internals.rust-lang.org/u/10takla)\
**Post date:** [March 20, 2024, 11:48am UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/4 "2024-03-20T11:48:55Z")

</div>

The reason is solely convenience. Your question seems to rather challenge the existence of the `Into` trait itself; I am merely suggesting its convenient implementation. Instances of using Into instead of `From` are purely idiomatic, and I would not like to forsake them due to an inconvenient implementation.

Here are examples where it can be convenient:

`.map(|rect| rect.into::<[Rc<Triangle>; 2]>())`

```rust
(Line::from([a, b]) - vector).into::<[Rc<Vector>; 2]>()

```

```rust
let [a, b, c] = [
   self.cab.ba.a.into::<i32>(),
   self.abc.ba.a.into::<i32>(),
   self.bca.ba.a.into::<i32>(),
];

```

The example I provided (`SomeOfVector::from(point.into::<Vector>()`)) is also semantically convenient when we say that we are transforming a point into something that `SomeOfVector` consumes.

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [March 20, 2024, 11:58am UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/5 "2024-03-20T11:58:09Z")

</div>

> [@10takla](#):
>
> Your question seems to rather challenge the existence of the _Into_ trait itself;

No, `.into()` is useful in places where inference can handle it. There's a similar relationship between `.collect()` and `Vec::from_iter`, if inference works `.collect()` is simpler and shorter, if it doesn't then `Vec::from_iter` is normally better. `collect` _does_ agree with your premise that having the generic on the method is more useful, as there are a few rare situations where it can be preferable, but how rarely that happens IMO means trying to do anything in the standard library to change this is not worth it (even if some non-breaking change is found).

I would personally not use turbofished-`into` for any of the situations you highlight

```rust
// these first two would likely have shorter type aliases
// avoiding the outer `<>` if they are common types

.map(<[Rc::<Triangle>; 2]>::from)

<[Rc<Vector>; 2]>::from(Line::from([a, b]) - vector)

let [a, b, c]: [i32; 3] = [
   self.cab.ba.a.into(),
   self.abc.ba.a.into(),
   self.bca.ba.a.into(),
];

```

(There was a reason for the separately implementable trait in the past, which made a generic method impossible, but afaik since the orphan rule changes there's no situation where you should be implementing `Into` directly).

---

<div class="post-metadata">

**Author:** ![kpreid](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kpreid/32/8484_2.png) [@kpreid](https://internals.rust-lang.org/u/kpreid)\
**Post date:** [March 20, 2024, 3:22pm UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/6 "2024-03-20T15:22:13Z")

</div>

A possibility would be to **modify the _language_ so that trait generic arguments can be specified on method calls** , as long as the method has no generic parameters itself. This would allow `.into::<T>()` while remaining compatible; it would also work for other sometimes-ambiguous methods like `AsRef::as_ref()` and `Borrow::borrow()`.

There is even a sort of precedent for this syntactic relationship: generic arguments to an _enum_ can be specified when naming a _variant_ of the enum (e.g. `None::<usize>`), as I was just reminded by @steffahn's [URLO post today](https://users.rust-lang.org/t/ambiguous-associated-type-fix/108609/6?u=kpreid).

However, this would be ambiguous if we wanted to also add

- type parameter defaults for functions, and
- official sealed traits,

because then it would be considered backwards-compatible to introduce a defaulted type parameter to a sealed trait's method, changing the meaning of the generic arguments on the call.

---

<div class="post-metadata">

**Author:** ![eggyal](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eggyal/32/7947_2.png) [@eggyal](https://internals.rust-lang.org/u/eggyal)\
**Post date:** [March 20, 2024, 5:16pm UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/7 "2024-03-20T17:16:15Z")

</div>

> [@10takla](#):
>
> In such cases, it is necessary to explicitly specify the particular implementation of _Into_ for _Point_:
> 
> `SomeOfVector::from(<Point as Into<Vector>>::into(point))`

It's possible to just identify the trait without naming the `Self` type:

```rust
Into::<Vector>::into(point)

```

A small improvement, but still more verbose than a turbofish on the function call.

---

<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:** [March 20, 2024, 9:25pm UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/8 "2024-03-20T21:25:20Z")

</div>

I think opt-in is optimal to avoid any breakage. E.g. if we had a feature of declaring a type parameter “`=Other`” that just unifies with another existing type parameter, we could changer `Into` to be defined as

```rust
pub trait Into<T> {
   fn into<=T>(self) -> T;
}

```

(I don't _really_ care about the precise syntax, and a MVP might as well just cover the case of supporting nothing but a trait’s parameter being repeated on a trait item.)

The functionality of this would be that `into` gains an optional type parameter and if this parameter is explicitly given, the given type is simply unified with the parameter in question. If nothing is explicitly given, then it’s the same as if `_` was given, which contributes nothing to restricting or disambiguating the parameter in question.

_Edit:_ Also, it would need to be allowed to _not_ repeat the declaration of such a `=T` parameter in a trait implementation for `Into`.

E.g. the most complex case of unification would also support fun cases like

```rust
let x: (bool, _, _) = Into::<(_, i32, _)>::into::<(_, _, f64)>(foo);

```

and the compiler would combine all the type information to deduce that the target type is `(bool, i32, f64)`; though the more common use-case of course would be of the form

```rust
let x = foo.into::<(bool, i32, f64)>();

```

---

<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:** [March 20, 2024, 10:44pm UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/9 "2024-03-20T22:44:59Z")

</div>

I have mixed feelings about this because it adds even more syntax variations to generics, which already are a complex feature (deciding between args on the type, or associated types, or args on methods), and even methods alone already have syntax with multiple confusingly similar ways of doing the same thing (e.g. generic args before function arguments vs impl Trait in args vs where clauses). So yet another variant of turbofish and yet another combination of arguments on type vs method make already messy situation even messier.

I’d prefer some different approach. Maybe add operators for `into` and `try_into` that could include type that looks more like a type cast. Maybe revisit type ascription with a new syntax.

---

<div class="post-metadata">

**Author:** ![10takla](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/10takla/32/11946_2.png) [@10takla](https://internals.rust-lang.org/u/10takla)\
**Post date:** [March 21, 2024, 3:50am UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/10 "2024-03-21T03:50:54Z")

</div>

I've thought about this too when I observed that we can further restrict generics in trait methods using `where`.

```rust
trait Trait<T> {
    fn method<F>() -> F
        where T: AnyTrait;
}

```

Then why couldn't we also specify the impl more concretely when calling. For example, it could be possible to reassign generics:

```rust
trait Trait<T> {
    fn method<T>() -> T;
}

```

But this would not be very explicit.

Then it could be possible to limit generics by other generics:

```rust
trait Trait<T> {
    fn method<F: T>() -> F
}

```

saying that `F` is the same as `T`, if `F` is specified when calling the method, it shadows `T`.

---

<div class="post-metadata">

**Author:** ![branpk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/branpk/32/8221_2.png) [@branpk](https://internals.rust-lang.org/u/branpk)\
**Post date:** [March 22, 2024, 9:14pm UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/11 "2024-03-22T21:14:28Z")

</div>

You can maybe do this:

```rust
pub trait Id {
    type This;
}

impl<T> Id for T {
    type This = Self;
}

pub trait Into<T>: Sized {
    fn into(self) -> T;

    fn into_generic<R: Id<This = T>>(self) -> T {
        self.my_into()
    }
}

```

[Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=197401029657503fb2ae56e11ec0bf0a)

---

<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:** [March 22, 2024, 9:33pm UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/12 "2024-03-22T21:33:20Z")

</div>

FWIW, I do feel like this is a problem worth solving. It's a bummer that when type inference fails, you're also deprived of the ability to use method chaining.

I don't know that any of the solutions proposed so far are worth the cost, though… I feel like there should be a more "thorough" approach to allowing things in postfix notation, but I'm not sure what it would be

---

<div class="post-metadata">

**Author:** ![branpk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/branpk/32/8221_2.png) [@branpk](https://internals.rust-lang.org/u/branpk)\
**Post date:** [March 22, 2024, 10:05pm UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/13 "2024-03-22T22:05:41Z")

</div>

A postfix type ascription syntax would solve this too: `x.into().as::<i64>()`

---

<div class="post-metadata">

**Author:** ![quaternic](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/quaternic/32/10440_2.png) [@quaternic](https://internals.rust-lang.org/u/quaternic)\
**Post date:** [March 22, 2024, 10:09pm UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/14 "2024-03-22T22:09:10Z")

</div>

In [Weird syntax idea(s) for UMCS](https://internals.rust-lang.org/t/weird-syntax-idea-s-for-umcs/19200) , there was a proposal for syntax that would let you call any function as if it was a method of its first parameter. In summary, `x.(foo)(y)` would be like `foo(x, y)`, except with the usual auto-(de)refs applied to `x`.

Something like that would be primarily useful for functions that aren't methods, but should also allow using the fully qualified syntax within method chains:

```rust
42
.(<i8 as Into<i16>>::into)()
.(Into::<i32>::into)()

```

---

<div class="post-metadata">

**Author:** ![Ratatouille](https://avatars.discourse-cdn.com/v4/letter/r/57b2e6/32.png) [@Ratatouille](https://internals.rust-lang.org/u/Ratatouille)\
**Post date:** [March 23, 2024, 4:41pm UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/15 "2024-03-23T16:41:31Z")

</div>

Just goes to show how good was this idea, did anyone write an RFC about it?

---

<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:** [March 24, 2024, 4:07pm UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/16 "2024-03-24T16:07:35Z")

</div>

I believe not. I'm a bit burnt out on putting forward actual proposal RFCs without preexisting team buyin, as that's mostly just a good way to put in a lot of effort for no result except a PR sitting open for years.

That said, I do think it's still a decent idea and would help write up the full RFC given someone on T-lang offering to shepherd it to get discussed and/or a compiler contributor offering to implement it experimentally.

`into`/`from` was actually on the mind when I wrote the idea out, although I'd expect `num.(i32::from)()` more than `num.(Into::<i32>::into)()`. These should access the same set of possible impls, _would_ were `Into` have the generic on the method, and `?` using `From` encodes the expectation into std that `From` is the trait to use, `Into` the (usually) convenient postfix method syntax sugar.

Aside: there's some momentum behind wanting to be able to do `use Default::default`. While `Into::into::<T>` is unlikely to just be possible, `use Trait::method` would synthesize a free function by prepending any trait generics to the method's generic list. `Option::<>::None` is a non-generic unit variant. `Option::*` is special and different from `Option::<>::*`, but `Trait::*` is always `Trait::<>::*`. (Bonus fun: `::<>` isn't "zero generics," it's "infer any/all generics," i.e. identical to no turbofish for any item other than a generic enum.)

---

<div class="post-metadata">

**Author:** ![farnz](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/farnz/32/6587_2.png) [@farnz](https://internals.rust-lang.org/u/farnz)\
**Post date:** [March 25, 2024, 9:10am UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/17 "2024-03-25T09:10:12Z")

</div>

> [@quaternic](#):
>
> In [Weird syntax idea(s) for UMCS](https://internals.rust-lang.org/t/weird-syntax-idea-s-for-umcs/19200) , there was a proposal for syntax that would let you call any function as if it was a method of its first parameter. In summary, `x.(foo)(y)` would be like `foo(x, y)`, except with the usual auto-(de)refs applied to `x`.

One of the interesting interactions to work out there would be with designs like [`Arc::into_inner`](https://doc.rust-lang.org/std/sync/struct.Arc.html#method.into_inner) which is deliberately not a method to avoid any ambiguity with the inner item. The goal is to force you to write `Arc::into_inner(arced)` if you really want to use that functionality, and not `arced.into_inner()`.

I'm confident that it's a fixable interaction, but it would need some thinking about - not least asking the question whether this is simply an acceptable loss of expressiveness to enable more expressive code elsewhere?

---

<div class="post-metadata">

**Author:** ![eggyal](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eggyal/32/7947_2.png) [@eggyal](https://internals.rust-lang.org/u/eggyal)\
**Post date:** [March 25, 2024, 9:13am UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/18 "2024-03-25T09:13:00Z")

</div>

It seems to me this proposal would allow `arced.(Arc::into_inner)` and that's perfectly okay because it's unambiguous.

---

<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:** [March 26, 2024, 5:30pm UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/19 "2024-03-26T17:30:08Z")

</div>

Instead of modifying the `Into` trait, which would be breaking; or coming up with additional syntax, which would take a lot of time to design properly; we can also just add a new trait.

An example of this is in the [tap](https://docs.rs/tap/latest/tap/) crate. Which offers the [`Conv`](https://docs.rs/tap/latest/tap/trait.Conv.html) trait.

```rust
trait Conv {
    fn conv<T>(self) -> T
    where
        Self: Into<T>,
        T: Sized,
    {
        self.into()
    }
}

impl<T> Conv for T {}

```

---

<div class="post-metadata">

**Author:** ![mdHMUpeyf8yluPfXI](https://avatars.discourse-cdn.com/v4/letter/m/58f4c7/32.png) [@mdHMUpeyf8yluPfXI](https://internals.rust-lang.org/u/mdHMUpeyf8yluPfXI)\
**Post date:** [March 27, 2024, 12:53pm UTC](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502/20 "2024-03-27T12:53:21Z")

</div>

What about allowing

```rust
pub trait Into<T> {
   fn into<T2=T>(self) -> T2;
}

```

With the semantics that the method has a type parameter `T2` that would default to `T`.

[Next page](https://internals.rust-lang.org/t/move-the-generic-type-from-the-trait-into-signature-to-the-into-method/20502.md?page=2)
