Rust 为什么与match guard编译相同的const结构,而不是作为匹配模式编译?

Rust 为什么与match guard编译相同的const结构,而不是作为匹配模式编译?,rust,Rust,我在努力处理来自postgres板条箱的错误。具体来说,postgres::error中的SqlState。因为常量使用的是Cow,所以我没有在匹配模式中以简单的方式使用它 例如,UNIQUE\u违规定义为 /// 23505 pub const UNIQUE_VIOLATION: SqlState = SqlState(Cow::Borrowed("23505")); 我最后做了以下几点,但我相信有一种更符合人体工程学/规范的方法来匹配错误 let maybe_user: p

我在努力处理来自
postgres
板条箱的错误。具体来说,
postgres::error
中的
SqlState
。因为常量使用的是
Cow
,所以我没有在匹配模式中以简单的方式使用它

例如,
UNIQUE\u违规
定义为

/// 23505
pub const UNIQUE_VIOLATION: SqlState = SqlState(Cow::Borrowed("23505"));
我最后做了以下几点,但我相信有一种更符合人体工程学/规范的方法来匹配错误

        let maybe_user: postgres::Result<User> = create_user(&conn, email);
        match maybe_user {
            Err(e) => {
                // e.code() returns Option<&postgres::SqlState>
                match e.code() {
                    None => panic!("not a sql error"),
                    Some(sqlstate) if sqlstate == &UNIQUE_VIOLATION => {
                        // do something...
                    },
                    Some(sqlstate) => panic!("unexpected error"),
                }
            }
            Ok(user) => {
                assert_eq!(user.email, email);
            }
        }
所以,我的问题是,有没有更简单、更符合人体工程学的方法来匹配这些错误

更新:我尝试了什么 @edwardw的建议是我想要实现的,但我尝试的一切都没有编译

  • 在匹配模式中使用
    UNIQUE\u违规
    ,会产生错误:
  • 在匹配模式中使用
    &UNIQUE\u违规
    ,会出现错误:
  • 更新2:最小示例 下面是一个快速重现错误的最小示例:

    use postgres::error::UNIQUE_VIOLATION;
    use postgres::Result;
    
    fn example() {
        let sql_state = &UNIQUE_VIOLATION;
    
        match sql_state {
            // this match arm works
            s if s == &UNIQUE_VIOLATION => {
                // do something...
            }
            // this match arm does not compile
            &UNIQUE_VIOLATION => {},
            _ => panic!("unexpected state"),
        }
    }
    
    需要
    postgres
    作为
    Cargo.toml中的依赖项

    [dependencies]
    postgres = "0.15.2"
    

    不,恐怕你没有比这更好的了。一个“明显”的改进似乎是:

    match e.code().expect(“非sql错误”){
    &唯一的\u冲突=>{
    //做点什么
    },
    _=>恐慌!(“意外错误”),
    }
    
    但它无法编译,错误如下:

    错误:要在模式中使用类型为
    std::borrow::Cow
    的常量,
    std::borrow::Cow
    必须用
    #[派生(PartialEq,Eq)]
    注释

    它失败的原因并不明显。Rust参考文件包含以下内容:

    (…在路径模式中…)结构和枚举常量必须具有
    #[派生(PartialEq,Eq)]
    (而不仅仅是实现的)

    事实证明,这是rustc的深思熟虑。解释原因和方式。总之,

    将结构或枚举类型的常量扩展为等效模式时,要求该结构或枚举类型用
    #[structural_match]
    修饰

    特性门
    #[结构匹配]
    将保持不稳定。仅当结构或枚举标记为
    #[派生(Eq)]
    时,此功能门才会自动应用,但如果手动实现,则不会自动应用。您试图匹配的
    std::borrow::Cow
    struct是
    SqlState
    的一部分,不幸的是,它属于后面的类别


    然而,
    =
    运算符不受此类限制。因此,常量结构或枚举仍然可以在match Guard中使用,就像您在问题中所做的那样。

    不,恐怕您没有比这更好的了。一个“明显”的改进似乎是:

    match e.code().expect(“非sql错误”){
    &唯一的\u冲突=>{
    //做点什么
    },
    _=>恐慌!(“意外错误”),
    }
    
    但它无法编译,错误如下:

    错误:要在模式中使用类型为
    std::borrow::Cow
    的常量,
    std::borrow::Cow
    必须用
    #[派生(PartialEq,Eq)]
    注释

    它失败的原因并不明显。Rust参考文件包含以下内容:

    (…在路径模式中…)结构和枚举常量必须具有
    #[派生(PartialEq,Eq)]
    (而不仅仅是实现的)

    事实证明,这是rustc的深思熟虑。解释原因和方式。总之,

    将结构或枚举类型的常量扩展为等效模式时,要求该结构或枚举类型用
    #[structural_match]
    修饰

    特性门
    #[结构匹配]
    将保持不稳定。仅当结构或枚举标记为
    #[派生(Eq)]
    时,此功能门才会自动应用,但如果手动实现,则不会自动应用。您试图匹配的
    std::borrow::Cow
    struct是
    SqlState
    的一部分,不幸的是,它属于后面的类别


    然而,
    =
    运算符不受此类限制。因此,常量结构或枚举仍然可以像您在问题中所做的那样在匹配保护中使用。

    True,使用expect使其更加简洁。不过,匹配不起作用
    code
    返回对
    SqlState
    的引用:``预期的
    &postgres\u共享::错误::SqlState::SqlState
    ,当我尝试匹配引用
    和唯一的\u冲突时,``找到结构
    postgres\u共享::错误::SqlState::SqlState
    ,我明白了:``错误:要在模式中使用类型为
    std::borrow::Cow
    的常量,
    std::borrow::Cow
    必须用
    #[derivate(PartialEq,Eq)]
    注释。``很酷,感谢您的解释。我被卡住了,找不到任何好的解释。遗憾的是,这些错误必须以如此繁琐的方式处理。的确,使用expect使其更加简洁。不过,匹配不起作用
    code
    返回对
    SqlState
    的引用:``预期的
    &postgres\u共享::错误::SqlState::SqlState
    ,当我尝试匹配引用
    和唯一的\u冲突时,``找到结构
    postgres\u共享::错误::SqlState::SqlState
    ,我明白了:``错误:要在模式中使用类型为
    std::borrow::Cow
    的常量,
    std::borrow::Cow
    必须用
    #[derivate(PartialEq,Eq)]
    注释。``很酷,感谢您的解释。我被卡住了,找不到任何好的解释。遗憾的是,这些错误必须以如此繁琐的方式处理。实际上,最好做一个@Stargateur添加的最小示例您首先谈论的是一个设计问题,而不是一个编译错误问题。请保留您的原始答案。不要继续/修改问题,因为有答案。选择。我没有改变问题。完全一样。我只是更清楚地说明了为匹配错误而提出更好的解决方案所面临的挑战。我还添加了一个最小的示例,没有更改任何其他内容,
    error: to use a constant of type std::borrow::Cow in a pattern, std::borrow::Cow must be annotated with #[derive(PartialEq, Eq)] 
    
    use postgres::error::UNIQUE_VIOLATION;
    use postgres::Result;
    
    fn example() {
        let sql_state = &UNIQUE_VIOLATION;
    
        match sql_state {
            // this match arm works
            s if s == &UNIQUE_VIOLATION => {
                // do something...
            }
            // this match arm does not compile
            &UNIQUE_VIOLATION => {},
            _ => panic!("unexpected state"),
        }
    }
    
    [dependencies]
    postgres = "0.15.2"