Leptos project: "distinct uses of `impl Trait` result in different opaque types"

I am not able to wrap my head around the error message! It looks to me that "expected struct" and "found struct" in the message below are the same!! I am on nightly.

error[E0308]: `match` arms have incompatible types
  --> leptos/src/components/home.rs:16:18
   |
12 |           {move || match is_logged_in.get() {
   |                    ------------------------ `match` arms have incompatible types
13 |               true => view! { 
   |  _____________________-
14 | |                 <Login /> 
15 | |             }.into_view(),
   | |_________________________- this is found to be of type `leptos::prelude::View<leptos::prelude::View<impl leptos::IntoView>>`
16 |               _ => view! { 
   |  __________________^
17 | |                 <AlreadyLoggedIn />
18 | |             }.into_view(),
   | |_________________________^ expected opaque type, found a different opaque type
   |
  ::: leptos/src/components/login.rs:9:19
   |
9  |   pub fn Login() -> impl IntoView {
   |                     ------------- the expected opaque type
...
28 |   pub fn AlreadyLoggedIn() -> impl IntoView {
   |                               ------------- the found opaque type
   |
   = note: expected struct `leptos::prelude::View<leptos::prelude::View<impl leptos::IntoView>>`
              found struct `leptos::prelude::View<leptos::prelude::View<impl leptos::IntoView>>`
   = note: distinct uses of `impl Trait` result in different opaque types

For more information about this error, try `rustc --explain E0308`.
error: could not compile `frontend-leptos` (bin "frontend-leptos") due to 1 previous error

I am playing with leptos crate. The code that emit this error is rust-projects/leptos at 31d0feeef8993f006cc6d7c583c395d3639ceea8 · dilawar/rust-projects · GitHub

Well, following diff fixed the problem but I still don't get the error message.

     view! {
         <h1>"Login"</h1>
-        {move || match is_logged_in.get() {
-            true => view! { 
-                <Login /> 
-            }.into_view(),
-            _ => view! { 
-                <AlreadyLoggedIn />
-            }.into_view(),
-        }}
+
+        <Show when=move || is_logged_in.get() fallback=|| view! { <AlreadyLoggedIn /> }>
+            <Login />
+        </Show>
     }
 }
9  |   pub fn Login() -> impl IntoView {
   |                     ------------- the expected opaque type
...
28 |   pub fn AlreadyLoggedIn() -> impl IntoView {
   |                               ------------- the found opaque type

Just like every closure is a distinct type, every -> impl IntoView is a distinct type. They are opaque aliases for some concrete underlying type that implements IntoView, and could be completely different concrete underlying types. You were trying to use them in such a way that required them to be the same type.[1]

That's what the Rust error message is about. A general fix would be converting the opaque types to some common type somehow.

Unfortunately I'm not familiar with Leptos, so I can't give more appropriately specific advice. Nor can I explain why the diff helps, as macros can do arbitrary things. At a guess it's only trying to return one impl IntoView instead of two, but that's just a guess.


  1. Even if they happen to have the same underlying concrete type, the compiler won't let you know that, as part of the point is allowing the implementation to change without breaking downstream. ↩︎

1 Like

Just found the answer Control Flow

Many thanks for looking into it.