rustc_hir/
version.rs

1use std::borrow::Cow;
2use std::fmt::{self, Display};
3use std::sync::OnceLock;
4
5use rustc_error_messages::{DiagArgValue, IntoDiagArg};
6use rustc_macros::{
7    Decodable, Encodable, HashStable_Generic, PrintAttribute, current_rustc_version,
8};
9
10use crate::attrs::PrintAttribute;
11
12#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[derive(HashStable_Generic, PrintAttribute)]
14pub struct RustcVersion {
15    pub major: u16,
16    pub minor: u16,
17    pub patch: u16,
18}
19
20impl RustcVersion {
21    pub const CURRENT: Self = current_rustc_version!();
22    pub fn current_overridable() -> Self {
23        *CURRENT_OVERRIDABLE.get_or_init(|| {
24            if let Ok(override_var) = std::env::var("RUSTC_OVERRIDE_VERSION_STRING")
25                && let Some(override_) = Self::parse_str(&override_var)
26            {
27                override_
28            } else {
29                Self::CURRENT
30            }
31        })
32    }
33    fn parse_str(value: &str) -> Option<Self> {
34        // Ignore any suffixes such as "-dev" or "-nightly".
35        let mut components = value.split('-').next().unwrap().splitn(3, '.');
36        let major = components.next()?.parse().ok()?;
37        let minor = components.next()?.parse().ok()?;
38        let patch = components.next().unwrap_or("0").parse().ok()?;
39        Some(RustcVersion { major, minor, patch })
40    }
41}
42
43static CURRENT_OVERRIDABLE: OnceLock<RustcVersion> = OnceLock::new();
44
45impl Display for RustcVersion {
46    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
47        write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)
48    }
49}
50
51impl IntoDiagArg for RustcVersion {
52    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
53        DiagArgValue::Str(Cow::Owned(self.to_string()))
54    }
55}