rustc_macros/
current_version.rs
1use proc_macro::TokenStream;
2use proc_macro2::Span;
3use quote::quote;
4
5pub(crate) fn current_version(_input: TokenStream) -> TokenStream {
6 let env_var = "CFG_RELEASE";
7 TokenStream::from(match RustcVersion::parse_cfg_release(env_var) {
8 Ok(RustcVersion { major, minor, patch }) => quote!(
9 Self { major: #major, minor: #minor, patch: #patch }
11 ),
12 Err(err) => syn::Error::new(Span::call_site(), format!("{env_var} env var: {err}"))
13 .into_compile_error(),
14 })
15}
16
17struct RustcVersion {
18 major: u16,
19 minor: u16,
20 patch: u16,
21}
22
23impl RustcVersion {
24 fn parse_cfg_release(env_var: &str) -> Result<Self, Box<dyn std::error::Error>> {
25 let value = proc_macro::tracked_env::var(env_var)?;
26 Self::parse_str(&value)
27 .ok_or_else(|| format!("failed to parse rustc version: {:?}", value).into())
28 }
29
30 fn parse_str(value: &str) -> Option<Self> {
31 let mut components = value.split('-').next().unwrap().splitn(3, '.');
33 let major = components.next()?.parse().ok()?;
34 let minor = components.next()?.parse().ok()?;
35 let patch = components.next().unwrap_or("0").parse().ok()?;
36 Some(RustcVersion { major, minor, patch })
37 }
38}