# The type inference for \`T\` cannot be done when the matched type has the form of \`T::Output\` and the trait is user-defined but it can be done for \`FnTrait\`

**URL:** <https://internals.rust-lang.org/t/the-type-inference-for-t-cannot-be-done-when-the-matched-type-has-the-form-of-t-output-and-the-trait-is-user-defined-but-it-can-be-done-for-fntrait/19455>\
**Category:** Uncategorized\
**Created:** [August 31, 2023, 11:58am UTC](https://internals.rust-lang.org/t/the-type-inference-for-t-cannot-be-done-when-the-matched-type-has-the-form-of-t-output-and-the-trait-is-user-defined-but-it-can-be-done-for-fntrait/19455 "2023-08-31T11:58:19Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![xmh0511](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/xmh0511/32/9874_2.png) [@xmh0511](https://internals.rust-lang.org/u/xmh0511)\
**Post date:** [August 31, 2023, 11:58am UTC](https://internals.rust-lang.org/t/the-type-inference-for-t-cannot-be-done-when-the-matched-type-has-the-form-of-t-output-and-the-trait-is-user-defined-but-it-can-be-done-for-fntrait/19455/1 "2023-08-31T11:58:19Z")

</div>

```rust
trait MyTrait<T> {
    type Output;
}
impl<T> MyTrait<T> for T {
    type Output = T;
}
fn show<T: MyTrait<T, Output = T> + Default>() -> T::Output {
    T::default()
}

fn main() {
    let i: i32 = show();
}

```

In this example, even thought I have implies that `T::Output` is `T` in the trait bound `T: MyTrait<T, Output = T>`, however, the compiler cannot infer type for `T`. If I change the return type to `T`, the compiler can infer `T` to `i32`. In contrast, the compiler can infer `FnTrait::Output`, for example:

```rust
fn infer_output<F,U:Default>(_:F)->F::Output
where F:Fn()->U
{
   U::default()
}
fn function<U:Default>()->U{
    U::default()
}
fn main() {
    let i:i32 = infer_output(function);
}

```

Similar to the first case, the trait bound `F:Fn()->U` implies that `F::Output` is `U`, and the compiler can infer `U` to `i32` as what is expected.

I think the compiler should enhance the type inference for the first example to make the type inference behave the same as that of the second case.

---

<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:** [August 31, 2023, 12:15pm UTC](https://internals.rust-lang.org/t/the-type-inference-for-t-cannot-be-done-when-the-matched-type-has-the-form-of-t-output-and-the-trait-is-user-defined-but-it-can-be-done-for-fntrait/19455/2 "2023-08-31T12:15:19Z")

</div>

I never knew there were cases where you could directly refer to the `Output` type of an `FnOnce` without `#![feature(unboxed_closures)]`!

---

<div class="post-metadata">

**Author:** ![xmh0511](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/xmh0511/32/9874_2.png) [@xmh0511](https://internals.rust-lang.org/u/xmh0511)\
**Post date:** [August 31, 2023, 12:56pm UTC](https://internals.rust-lang.org/t/the-type-inference-for-t-cannot-be-done-when-the-matched-type-has-the-form-of-t-output-and-the-trait-is-user-defined-but-it-can-be-done-for-fntrait/19455/3 "2023-08-31T12:56:23Z")

</div>

> **[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8946771fb7f645a82d02e5dc7c70edfc)**
>
> A browser interface to the Rust compiler to experiment with the language

This code does not need to use `#![feature(unboxed_closures)]`

---

<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:** [August 31, 2023, 12:57pm UTC](https://internals.rust-lang.org/t/the-type-inference-for-t-cannot-be-done-when-the-matched-type-has-the-form-of-t-output-and-the-trait-is-user-defined-but-it-can-be-done-for-fntrait/19455/4 "2023-08-31T12:57:03Z")

</div>

I know, that’s what I was surprised about 😉

---

<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:** [August 31, 2023, 9:47pm UTC](https://internals.rust-lang.org/t/the-type-inference-for-t-cannot-be-done-when-the-matched-type-has-the-form-of-t-output-and-the-trait-is-user-defined-but-it-can-be-done-for-fntrait/19455/5 "2023-08-31T21:47:42Z")

</div>

> [@xmh0511](#):
>
> In contrast,

The examples are different. I don't think it's that `Fn` is special here, I think it's that you have a different set of generic types, implementations on said types, and a different calling pattern. One or more of those accounts for the difference.

[In the `Fn` version,](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=ec9f6e1cc4b665630aebf9c5eb98152c) you're passing in `function`, and the compiler has something like

```rust
let i: i32 = infer_output::<typeof(function)::<U?>, U?>(function);

```

and can constrain `typeof(function)::<U?>: Fn<(), Output = i32>` from the signature and the `i32` annotation, and then use the notional implementation of `FnOnce`/`Fn` to figure out `U? = i32`.

[If I adjust your non`-Fn` example to match,](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=cbb33d3e82ed35695392bbdd9ea8bada) it similarly succeeds.

If you remove the argument (so that `T` isn't an input), it fails. However, I had to make other changes to align the two examples, so maybe the thing you care about is part of those changes.

* * *

> [@xmh0511](#):
>
> I think the compiler should enhance the type inference for the first example to make the type inference behave the same as that of the second case.

Let me assume the `Fn` stuff was just a distraction / misunderstanding and go back to your non-compiling code. There you have something like

```rust
let i: i32 = show::<T?>();

```

And the compiler can\[1\] constrain

```rust
T?: MyTrait<T?, Output = i32>

```

but apparently can't "work backward" from the `Output = T?` portion of the original bound to infer `T = i32`. I think that's what your feature request is really about. \[2\]

(In contrast, if you change the return type to `T` instead of `T::Output`, then `T? = i32` can be applied directly and works today).

* * *

I'd be sort of surprised if there's not an existing issue about this, but I didn't find one offhand. You could create one.

* * *

1. hypothetically, i.e., I don't know that it bothers to get this far when `T?` isn't an input at the call site 

2. Mostly guessing, but perhaps it could be summed up as "consider projections to be input parameters when an associated type bound makes them equal to an input parameter" or "eagerly replace projections with parameters given an equality bound" or something like that.

---

<div class="post-metadata">

**Author:** ![xmh0511](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/xmh0511/32/9874_2.png) [@xmh0511](https://internals.rust-lang.org/u/xmh0511)\
**Post date:** [September 1, 2023, 3:26am UTC](https://internals.rust-lang.org/t/the-type-inference-for-t-cannot-be-done-when-the-matched-type-has-the-form-of-t-output-and-the-trait-is-user-defined-but-it-can-be-done-for-fntrait/19455/6 "2023-09-01T03:26:03Z")

</div>

> <https://github.com/rust-lang/rust/issues/115406>
>
> \`\`\`\`rust
> trait MyTrait\<T\> {
> type Output;
> }
> impl\<T\> MyTrait\<T\> for T {
> … type Output = T;
> }
> fn show\<T: MyTrait\<T, Output = T\> + Default\>() -\> T::Output {
> T::default()
> }
> 
> fn main() {
> let i: i32 = show();
> }
> \`\`\`\`
> In this case, the compiler cannot infer the type for \`T\`, however, as specified in the trait bound \`T: MyTrait\<T, Output = T\>\`, which implies that \`T::Output\` is just \`T\`. If we change \`T::Output\` to \`T\`, then the compiler will infer \`T\` as \`i32\`. 
> 
> In contrast, the compiler can infer \`Fn::Output\`, for example:
> \`\`\`\`rust
> fn infer\_output\<F,U:Default\>(\_:F)-\>F::Output
> where F:Fn()-\>U
> {
> U::default()
> }
> fn function\<U:Default\>()-\>U{
> U::default()
> }
> fn main() {
> let i:i32 = infer\_output(function);
> }
> \`\`\`\`
> In this example, the compiler can know that \`F::Output\` is \`U\`, and infer \`U\` with type \`i32\`. The compiler may enhance type inference to make it more powerful for the first example.

I posted the issue to rust-lang.

---

<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:** [November 30, 2023, 3:26am UTC](https://internals.rust-lang.org/t/the-type-inference-for-t-cannot-be-done-when-the-matched-type-has-the-form-of-t-output-and-the-trait-is-user-defined-but-it-can-be-done-for-fntrait/19455/7 "2023-11-30T03:26:48Z")

</div>

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