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

Rust中`_`在match分支与matches!宏中使用差异的报错疑问

问题原因与解决方案

核心原因:_在不同语法场景的作用完全不同

1. 实现代码里的_是非法用法

你在FromStr实现的match分支里写的:

Err(error) => Err(ParsePersonError::ParseInt(_))

这里是构造枚举实例,ParseInt变体要求必须传入一个ParseIntError类型的具体值。Rust里_只有在变量绑定(赋值左侧)或者模式匹配场景才能用来忽略值,构造实例时必须给变体传完整参数,不能用_占位,所以编译器会报错。

2. 测试代码中matches!宏里的_是合法用法

matches!宏的作用是检查表达式是否匹配指定模式,这里的ParsePersonError::ParseInt(_)是一个模式:

Err(ParsePersonError::NoName | ParsePersonError::ParseInt(_))

模式里的_是通配符,意思是“匹配任意ParseIntError值”——只要是ParseInt变体,不管内部错误具体是什么,都能匹配成功。这是Rust模式匹配的标准语法,所以编译器不会报错。

修复后的代码

把构造ParsePersonError::ParseInt的地方换成传入实际的错误值error,同时简化冗余逻辑:

use std::num::ParseIntError;
use std::str::FromStr;

#[derive(Debug, PartialEq)]
struct Person {
    name: String,
    age: usize,
}

#[derive(Debug, PartialEq)]
enum ParsePersonError {
    Empty,
    BadLen,
    NoName,
    ParseInt(ParseIntError),
}

impl FromStr for Person {
    type Err = ParsePersonError;
    fn from_str(s: &str) -> Result<Person, Self::Err> {
        if s.is_empty() {
            return Err(ParsePersonError::Empty);
        }

        let v: Vec<&str> = s.split(",").collect();
        
        if v[0].is_empty() {
            return Err(ParsePersonError::NoName);
        }
        
        if v.len() != 2 {
            return Err(ParsePersonError::BadLen);
        }

        // 用map_err直接转换错误类型,替代冗余的match
        let age = v[1].parse::<usize>().map_err(ParsePersonError::ParseInt)?;
        Ok(Person {
            name: v[0].to_string(),
            age,
        })
    }
}

#[test]
fn missing_name_and_age() {
    assert!(matches!(
        ",".parse::<Person>(),
        Err(ParsePersonError::NoName | ParsePersonError::ParseInt(_))
    ));
}

原代码里match的Ok分支已经return了,后面的Err(ParsePersonError::ParseInt(_))永远不会执行,修复时用map_err简化了错误处理,更符合Rust的惯用写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:55:44