// The macro won't need to define what it means for other sorts of patterns to
// be sorted. It should be fine to trigger an error if any of the patterns is
// not something that can be compared by path.
//
// Be sure that the resulting error message is understandable and placed
// correctly underlining the unsupported pattern.
#[sorted::check]
fn f(bytes: &[u8]) -> Option<u8> {
#[sorted]
match bytes {
[] => Some(0),
[a] => Some(*a),
[a, b] => Some(a + b),
_other => None,
}
}
fn main() {}
這裡主要說明的是,我們只能排序能排序的。rust
的match
功能十分強大,並非只是簡單的字元列舉匹配,還有很多的資料匹配。
對於這種,我們並不需要完全的支援。
impl syn::visit_mut::VisitMut for MatchVisitor {
fn visit_expr_match_mut(&mut self, i: &mut syn::ExprMatch) {
let mut target_idx: isize = -1;
for (idx, attr) in i.attrs.iter().enumerate() {
if path_to_string(&attr.path) == "sorted" {
target_idx = idx as isize;
break;
}
}
if target_idx != -1 {
i.attrs.remove(target_idx as usize);
let mut match_arm_names: Vec<(String, &dyn quote::ToTokens)> = Vec::new();
for arm in i.arms.iter() {
match &arm.pat {
syn::Pat::Path(p) => {
match_arm_names.push((path_to_string(&p.path), &p.path));
}
syn::Pat::TupleStruct(p) => {
match_arm_names.push((path_to_string(&p.path), &p.path));
}
syn::Pat::Struct(p) => {
match_arm_names.push((path_to_string(&p.path), &p.path));
}
syn::Pat::Ident(p) => {
match_arm_names.push((p.ident.to_string(), &p.ident));
}
syn::Pat::Wild(p) => {
match_arm_names.push(("_".to_string(), &p.underscore_token));
}
_ => {
self.err = std::option::Option::Some(syn::Error::new_spanned(
&arm.pat,
"unsupported by #[sorted]",
));
return;
}
}
}
if let Some(e) = check_order(match_arm_names) {
self.err = std::option::Option::Some(e);
return;
}
}
syn::visit_mut::visit_expr_match_mut(self, i)
}
}
在sorted-5中我們解析其他型別的時候,最後一個分支我們提示了一個錯誤。
其實就是這一關的提示錯誤
error: unsupported by #[sorted]
--> tests/07-unrecognized-pattern.rs:12:9
|
12 | [] => Some(0),
|
雖然我是後續整理合二為一的,但是我相信,只要保持良好的編碼習慣,這種錯誤提示的相似性甚至一致性,是必然的結果。多多努力。
本作品採用《CC 協議》,轉載必須註明作者和本文連結