88993


Windows10環境下です。  
Rustのソースをビルドした時、以下のエラーが発生しました。

[code]

    error[E0308]: mismatched types
      --> src\main.rs:25:43
       |
    25 |   let a:Result<Channel, Box<dyn Error>> = example_feed();
       |         -------------------------------   ^^^^^^^^^^^^^^ expected enum `Result`, found opaque type
       |         |
       |         expected due to this
       |
    note: while checking the return type of the `async fn`
      --> src\main.rs:14:28
       |
    14 | async fn example_feed() -> Result<Channel, Box<dyn Error>> {
       |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, found opaque type
       = note:     expected enum `Result<Channel, Box<dyn std::error::Error>>`
               found opaque type `impl Future<Output = Result<Channel, Box<(dyn std::error::Error + 'static)>>>`
    
    For more information about this error, try `rustc --explain E0308`.
    
[/code]

ソースは以下です。

[code]

    async fn example_feed() -> Result<Channel, Box<dyn Error>> {
        let content = reqwest::get("https://www.reddit.com/r/programming/.rss")
            .await?
            .bytes()
            .await?;
        let channel = Channel::read_from(&content[..])?;
        Ok(channel)
    }
    
    #[tauri::command]
    fn get_rss(_state: tauri::State<StateValue>) -> String {
      let a:Result<Channel, Box<dyn Error>> = example_feed();
      match a{
        Ok(result)=> println!("{:?}",result),
        Err(msg)=>println!("No"),
      }
      
      String::from("test")
    }
    
[/code]

掲題の通り、具体的に何をどう修正したら良いのか、わかりません。  
私は何をしたら良いのでしょうか？

*追記

awaitを使用したところ、次から次へとコンパイラから指示が飛び、  
最終的に以下のソースとエラーとなりました。

[code]

    error[E0597]: `__tauri_message__` does not live long enough
      --> src\main.rs:23:1
       |
    23 | #[tauri::command]
       | ^^^^^^^^^^^^^^^^-
       | |               |
       | |               `__tauri_message__` dropped here while still borrowed
       | borrowed value does not live long enough
       | argument requires that `__tauri_message__` is borrowed for `'static`
    ...
    37 |         .invoke_handler(tauri::generate_handler![get_rss])
       |                         --------------------------------- in this macro invocation
       |
       = note: this error originates in the macro `__cmd__get_rss` (in Nightly builds, run with -Z macro-backtrace for more info)
    
    For more information about this error, try `rustc --explain E0597`.
    warning: `app` (bin "app") generated 1 warning
    error: could not compile `app` due to previous error; 1 warning emitted
    
[/code]

ソース

[code]

    #![cfg_attr(
        all(not(debug_assertions), target_os = "windows"),
        windows_subsystem = "windows"
    )]
    
    use std::error::Error;
    use rss::Channel;
    struct StateValue(i32);
    
    async fn example_feed() -> Result<Channel, Box<dyn Error>> {
        let content = reqwest::get("https://www.reddit.com/r/programming/.rss")
            .await?
            .bytes()
            .await?;
        let channel = Channel::read_from(&content[..])?;
        Ok(channel)
    }
    
    #[tauri::command]
    async fn get_rss(_state: tauri::State<'_,StateValue>) -> String {
      let a:Result<Channel, Box<dyn Error>> = example_feed().await;
      match a{
        Ok(result)=> println!("{:?}",result),
        Err(msg)=>println!("No"),
      }
      
      String::from("test")
    }
    
    fn main() {
        tauri::Builder::default()
            .manage(StateValue(0))
            .invoke_handler(tauri::generate_handler![get_rss])
            .run(tauri::generate_context!())
            .expect("error while running tauri application");
    }
    
    
[/code]

何をどうしたら良いのか、さっぱりわかりません……


CC BY-SA 4.0
2022-05-23T01:11:19.307
88987
2022-05-23T18:18:44.723
2022-05-23T02:43:51.797
52754
52754
question
rust
Rustでミスマッチタイプエラーが発生したが、具体的に何をしたら良いのかわからない


rustは存じ上げませんが、example_feed()をawaitしてみてはいかがでしょうか？


CC BY-SA 4.0
2022-05-23T02:24:31.233
88988
2022-05-23T02:24:31.233
52757
88987
answer


Tauriには詳しくないですが、手元で実験してみた感じでは`#[tauri::command]`を付ける関数は`async`にできないようです。

つまり、`example_feed()`を`async`でない通常の関数に書き換えるか、あるいは`async`関数が返してくる`Future`を解決してやる必要があります。

  1. `example_feed()`を書き換えるパターン  
`reqwest`には[`async`を使わない`blocking`という機能](https://github.com/seanmonstar/reqwest#blocking-
client)があります。  
この機能を有効にすると`example_feed()`は通常の関数として書けます。

[code]

    fn example_feed() -> Result<Channel, Box<dyn Error>> {
        let content = reqwest::blocking::get("https://www.reddit.com/r/programming/.rss")?
            .bytes()?;
        let channel = Channel::read_from(&content[..])?;
        Ok(channel)
    }
    
[/code]

  2. `Future`を解決するパターン  
`Future`から値を取り出すには、非同期ランタイムに`Future`を渡して実行してもらう必要があります。  
`tauri`は運よく非同期ランタイムを持っているので、それを使って`Future`を解決できます。

[code]

    #[tauri::command]
    fn get_rss(_state: tauri::State<'_, StateValue>) -> String {
        // tauri::async_runtime::block_on で Future を解決
        let a: Result<Channel, Box<dyn Error>> = tauri::async_runtime::block_on(example_feed());
        match a {
            Ok(result) => println!("{:?}", result),
            Err(msg) => println!("No"),
        }
    
        String::from("test")
    }
    
    
[/code]


CC BY-SA 4.0
2022-05-23T07:38:28.407
88993
2022-05-23T07:38:28.407
8826
88987
answer


  * [ Compile error for async stateful commands that don't return a Result #2533](https://github.com/tauri-apps/tauri/issues/2533)

という不具合があり、ワークアラウンドとしては、次のいずれかを行えば良いようです。

  * `async` を使わない
  * (使っていないのであれば) state 引数を除去する
  * 戻り値の型を `Result` にする

改めて見直してみると、公式のサンプルコードでは確かに戻り値は `Result` 型になっています。

  * <https://tauri.studio/v1/guides/features/command/#complete-example>
  * <https://github.com/tauri-apps/tauri/blob/f1637d6/examples/commands/main.rs#L114-L121>

[code]

    async fn example_feed() -> Result<Channel, Box<dyn Error>> {
        let content = reqwest::get("https://www.soumu.go.jp/news.rdf")
            .await?
            .bytes()
            .await?;
        let channel = Channel::read_from(&content[..])?;
        Ok(channel)
    }
    
    #[tauri::command]
    async fn get_rss(_state: tauri::State<'_, StateValue>) -> Result<String, ()> {
        let a: Result<Channel, Box<dyn Error>> = example_feed().await;
        match a {
            Ok(result) => {
                println!("{:?}", result);
            }
            Err(msg) => {
                println!("No");
            }
        }
    
        Ok(String::from("test"))
    }
    
[/code]

あるいは

[code]

    async fn example_feed() -> Result<Channel, Box<dyn Error>> {
        // 略
    }
    
    #[tauri::command]
    async fn get_rss() -> String {
        let a: Result<Channel, Box<dyn Error>> = example_feed().await;
        match a {
            Ok(result) => {
                println!("{:?}", result);
            }
            Err(msg) => {
                println!("No");
            }
        }
    
        String::from("test")
    }
    
[/code]

(`async` を外す例は[別回答](https://ja.stackoverflow.com/a/88993/2808)にあるので省略)


CC BY-SA 4.0
2022-05-23T09:57:58.557
88999
2022-05-23T18:18:44.723
2022-05-23T18:18:44.723
2808
2808
88987
answer