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
相关产品推荐
相关产品推荐

