Skip to content

Commit ef608f1

Browse files
committed
Introduce target_spec_enum macro to avoid duplication
With this macro we only need to enumerate every variant once. This saves a lot of duplication already between the definition, the `FromStr` impl and the `ToJson` impl. It also enables us to do further things with it like JSON schema generation.
1 parent f32b232 commit ef608f1

File tree

2 files changed

+241
-712
lines changed

2 files changed

+241
-712
lines changed

compiler/rustc_target/src/lib.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,63 @@ fn find_relative_libdir(sysroot: &Path) -> std::borrow::Cow<'static, str> {
7272
Some(libdir) => libdir.into(),
7373
}
7474
}
75+
76+
macro_rules! target_spec_enum {
77+
(
78+
$( #[$attr:meta] )*
79+
pub enum $name:ident {
80+
$(
81+
$( #[$variant_attr:meta] )*
82+
$variant:ident = $string:literal,
83+
)*
84+
}
85+
parse_error_type = $parse_error_type:literal;
86+
) => {
87+
$( #[$attr] )*
88+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
89+
pub enum $name {
90+
$(
91+
$( #[$variant_attr] )*
92+
$variant,
93+
)*
94+
}
95+
96+
impl FromStr for $name {
97+
type Err = String;
98+
99+
fn from_str(s: &str) -> Result<Self, Self::Err> {
100+
Ok(match s {
101+
$( $string => Self::$variant, )*
102+
_ => {
103+
let all = [$( concat!("'", $string, "'") ),*].join(", ");
104+
return Err(format!("invalid {}: '{s}'. allowed values: {all}", $parse_error_type));
105+
}
106+
})
107+
}
108+
}
109+
110+
impl $name {
111+
pub fn desc(&self) -> &'static str {
112+
match self {
113+
$( Self::$variant => $string, )*
114+
}
115+
}
116+
}
117+
118+
impl crate::json::ToJson for $name {
119+
fn to_json(&self) -> crate::json::Json {
120+
self.desc().to_json()
121+
}
122+
}
123+
124+
crate::json::serde_deserialize_from_str!($name);
125+
126+
127+
impl std::fmt::Display for $name {
128+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129+
f.write_str(self.desc())
130+
}
131+
}
132+
};
133+
}
134+
use target_spec_enum;

0 commit comments

Comments
 (0)