You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust异步函数返回Result报错:无法转换azure_core错误为String

Rust + Actix + Azure CosmosDB 编译错误:?运算符无法转换错误类型

问题描述

我是Rust新手,正在结合Rust、Actix与Azure CosmosDB开发。编写了一个异步函数,期望连接CosmosDB并返回包含集合名称的Result<String, String>,但遇到编译错误:?运算符无法将azure_core::error::Error转换为std::string::String。

代码

async fn datastuff() -> Result<String, String> {

    let primary_key = std::env::var("COSMOSDB_READKEY").expect("Set env variable COSMOS_PRIMARY_KEY first!");
    let account = std::env::var("COSMOSDB_ACCOUNT").expect("Set env variable COSMOS_ACCOUNT first!");

    let database_name = "azdeployer";
    let collection_name = "resourcetemplates";

    // First, create an authorization token. There are two types of tokens: primary and resource constrained.
    // Please check the Azure documentation or the examples folder on how to create and use token-based permissions.
    let authorization_token = AuthorizationToken::primary_key(&primary_key)?;

    // Next we will create a Cosmos client.
    let client = CosmosClient::new(account, authorization_token);

    // We know the database so we can obtain a database client.
    let database = client.database_client(database_name);
    // We know the collection so we can obtain a collection client.
    let collection = database.collection_client(collection_name);
    //let cosmos_collection_client: CollectionClient = cosmos::cosmosclient::create_collection_client().expect("prutser");
    //let document_client: DocumentClient = cosmos_collection_client.document_client("resourceGroups@2022-09-01", "resourcegroup");
    let documents1 = collection.list_documents();
    let documents = collection.collection_name();
    let result: String = documents.to_string();
    Ok(result)
}

错误信息

错误[E0277]:`?`无法将错误转换为`std::string::String`
   --> src\main.rs:17:76
    |
17  |     let authorization_token = AuthorizationToken::primary_key(&primary_key)?;
    |                                                                           ^ 未为`std::string::String`实现`trait std::convert::From<azure_core::error::Error>`
    |
    = 说明:问号运算符(`?`)会通过`From`trait隐式转换错误值
    = 帮助:以下类型实现了`trait std::convert::From<T>`:
             <std::string::String as std::convert::From<char>>
             <std::string::String as std::convert::From<bytestring::ByteString>>
             <std::string::String as std::convert::From<Box<str>>>
             <std::string::String as std::convert::From<uuid::Uuid>>
             <std::string::String as std::convert::From<Cow<'a, str>>>
             <std::string::String as std::convert::From<url::Url>>
             <std::string::String as std::convert::From<&str>>
             <std::string::String as std::convert::From<&mut str>>
             <std::string::String as std::convert::From<&std::string::String>>
    = 说明:需要`Result<std::string::String, std::string::String>`实现`FromResidual<Result<Infallible, azure_core::error::Error>>`

部分错误有详细解释:E0277, E0425。如需了解错误详情,尝试`rustc --explain E0277`。

解决方案

问题根源

AuthorizationToken::primary_key方法返回的错误类型是azure_core::error::Error,但你的函数声明返回Result<String, String>。?运算符要求错误类型之间必须实现std::convert::Fromtrait以自动转换,而String并没有为azure_core::error::Error实现这个trait,因此编译失败。

解决方法

方法1:直接将错误转为字符串(快速修复)

使用map_err方法把azure_core::error::Error转换为String,替换原代码中的?用法:

let authorization_token = AuthorizationToken::primary_key(&primary_key)
    .map_err(|e| e.to_string())?;

这样错误会被转为字符串形式,符合函数返回的错误类型要求。

方法2:自定义错误类型(推荐,适合大型项目)

定义一个包含所有可能错误的枚举,为其实现From<azure_core::error::Error>、std::fmt::Display和std::error::Errortrait,让?可以自动转换错误类型:

use std::error::Error;
use std::fmt;

#[derive(Debug)]
enum MyError {
    CosmosError(azure_core::error::Error),
    EnvVarError(std::env::VarError),
}

impl From<azure_core::error::Error> for MyError {
    fn from(e: azure_core::error::Error) -> Self {
        MyError::CosmosError(e)
    }
}

impl From<std::env::VarError> for MyError {
    fn from(e: std::env::VarError) -> Self {
        MyError::EnvVarError(e)
    }
}

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            MyError::CosmosError(e) => write!(f, "CosmosDB error: {}", e),
            MyError::EnvVarError(e) => write!(f, "Environment variable error: {}", e),
        }
    }
}

impl Error for MyError {}

// 修改函数返回类型
async fn datastuff() -> Result<String, MyError> {
    let primary_key = std::env::var("COSMOSDB_READKEY")?;
    let account = std::env::var("COSMOSDB_ACCOUNT")?;

    // 后续代码不变,?会自动转换错误到MyError
    let authorization_token = AuthorizationToken::primary_key(&primary_key)?;
    let client = CosmosClient::new(account, authorization_token);
    let database = client.database_client("azdeployer");
    let collection = database.collection_client("resourcetemplates");
    let result = collection.collection_name().to_string();
    Ok(result)
}

内容的提问来源于stack exchange,提问作者Cyriel Lamerigts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 05:44:51