/// Represents the version of the Rust language to target. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] #[repr(transparent)] pubstruct RustTarget(Version);
impl RustTarget { /// Create a new [`RustTarget`] for a stable release of Rust. pubfn stable(minor: u64, patch: u64) -> Result<Self, InvalidRustTarget> { let target = Self(Version::Stable(minor, patch));
if target < EARLIEST_STABLE_RUST { return Err(InvalidRustTarget::TooEarly);
}
constfn is_compatible(&self, other: &Self) -> bool { match (self.0, other.0) {
(Version::Stable(minor, _), Version::Stable(other_minor, _)) => { // We ignore the patch version number as they only include backwards compatible bug // fixes.
minor >= other_minor
} // Nightly is compatible with everything
(Version::Nightly, _) => true, // No stable release is compatible with nightly
(Version::Stable { .. }, Version::Nightly) => false,
}
}
}
impl Default for RustTarget { fn default() -> Self { // Bindgen from build script: default to generating bindings compatible // with the Rust version currently performing this build. #[cfg(not(feature = "__cli"))]
{ use std::env; use std::iter; use std::process::Command; use std::sync::OnceLock;
iflet Some(current_rust) = *CURRENT_RUST.get_or_init(|| { let is_build_script =
env::var_os("CARGO_CFG_TARGET_ARCH").is_some(); if !is_build_script { return None;
}
let rustc = env::var_os("RUSTC")?; let rustc_wrapper = env::var_os("RUSTC_WRAPPER")
.filter(|wrapper| !wrapper.is_empty()); let wrapped_rustc =
rustc_wrapper.iter().chain(iter::once(&rustc));
let output = command.output().ok()?; let string = String::from_utf8(output.stdout).ok()?;
// Version string like "rustc 1.100.0-beta.5 (f0e1d2c3b 2026-10-17)" let last_line = string.lines().last().unwrap_or(&string); let (program, rest) = last_line.trim().split_once(' ')?; if program != "rustc" { if program.starts_with("clippy") && !is_clippy_driver {
is_clippy_driver = true; continue;
} return None;
}
let number = rest.split([' ', '-', '+']).next()?; break RustTarget::from_str(number).ok();
}
}) { return current_rust;
}
}
// Bindgen from CLI, or cannot determine compiler version: default to // generating bindings compatible with the latest stable release of Rust // that Bindgen knows about.
LATEST_STABLE_RUST
}
}
impl RustTarget { /// Returns the latest edition supported by this target. pub(crate) fn latest_edition(self) -> RustEdition {
RustEdition::ALL
.iter()
.rev()
.find(|edition| edition.is_available(self))
.copied()
.expect("bindgen should always support at least one edition")
}
}
impl RustTarget { /// The nightly version of Rust, which introduces the following features:"
$(#[doc = concat!( "- [`", stringify!($nightly_feature), "`]", "(", $("https://github.com/rust-lang/rust/pull/", stringify!($issue),)* ")",
)])* #[deprecated = "The use of this constant is deprecated, please use `RustTarget::nightly` instead."] pubconst Nightly: Self = Self::nightly();
/// The nightly version of Rust, which introduces the following features:"
$(#[doc = concat!( "- [`", stringify!($nightly_feature), "`]", "(", $("https://github.com/rust-lang/rust/pull/", stringify!($issue),)* ")",
)])* pubconstfn nightly() -> Self { Self(Version::Nightly)
}
$( #[doc = concat!("Version 1.", stringify!($minor), " of Rust, which introduced the following features:")]
$(#[doc = concat!( "- [`", stringify!($feature), "`]", "(", $("https://github.com/rust-lang/rust/pull/", stringify!($pull),)* ")",
)])* #[deprecated = "The use of this constant is deprecated, please use `RustTarget::stable` instead."] pubconst $variant: Self = Self(Version::Stable($minor, 0));
)*
impl RustFeatures { /// Compute the features that must be enabled in a specific Rust target with a specific edition. pub(crate) fn new(target: RustTarget, edition: RustEdition) -> Self { letmut features = Self {
$($($feature: false,)*)*
$($nightly_feature: false,)*
};
if target.is_compatible(&RustTarget::nightly()) {
$( let editions: &[RustEdition] = &[$(stringify!($nightly_edition).parse::<RustEdition>().ok().expect("invalid edition"),)*];
// NOTE: When adding or removing features here, make sure to add the stabilization PR // number for the feature if it has been stabilized or the tracking issue number if the feature is // not stable.
define_rust_targets! {
Nightly => {
vectorcall_abi: #124485,
ptr_metadata: #81513,
layout_for_ptr: #69835,
},
Stable_1_82(82) => {
unsafe_extern_blocks: #127921,
},
Stable_1_77(77) => {
offset_of: #106655,
literal_cstr(2021)|(2024): #117472,
},
Stable_1_73(73) => { thiscall_abi: #42202 },
Stable_1_71(71) => { c_unwind_abi: #106075 },
Stable_1_68(68) => { abi_efiapi: #105795 },
Stable_1_64(64) => { core_ffi_c: #94503 },
Stable_1_59(59) => { const_cstr: #54745 },
Stable_1_51(51) => {},
}
/// Latest stable release of Rust that is supported by bindgen pubconst LATEST_STABLE_RUST: RustTarget = { // FIXME: replace all this code by // ``` // RustTarget::stable_releases() // .into_iter() // .max_by_key(|(_, m)| m) // .map(|(t, _)| t) // .unwrap() // ``` // once those operations can be used in constants. let targets = RustTarget::stable_releases();
/// Earliest stable release of Rust that is supported by bindgen pubconst EARLIEST_STABLE_RUST: RustTarget = { // FIXME: replace all this code by // ``` // RustTarget::stable_releases() // .into_iter() // .min_by_key(|(_, m)| m) // .map(|(t, _)| t) // .unwrap_or(LATEST_STABLE_RUST) // ``` // once those operations can be used in constants. let targets = RustTarget::stable_releases();
letmut i = 0; letmut earliest_target = None; let Some(mut earliest_minor) = LATEST_STABLE_RUST.minor() else {
unreachable!()
};
while i < targets.len() { let (target, minor) = targets[i];
if earliest_minor > minor {
earliest_minor = minor;
earliest_target = Some(target);
}
let Some((major_str, tail)) = input.split_once('.') else { return Err(invalid_input(input, "accepted values are of the form \"1.71\", \"1.71.1\" or \"nightly\"." ) );
};
if major_str != "1" { return Err(invalid_input(
input, "The largest major version of Rust released is \"1\"",
));
}
let (minor, patch) = iflet Some((minor_str, patch_str)) =
tail.split_once('.')
{ let Ok(minor) = minor_str.parse::<u64>() else { return Err(invalid_input(input, "the minor version number must be an unsigned 64-bit integer"));
}; let Ok(patch) = patch_str.parse::<u64>() else { return Err(invalid_input(input, "the patch version number must be an unsigned 64-bit integer"));
};
(minor, patch)
} else { let Ok(minor) = tail.parse::<u64>() else { return Err(invalid_input(input, "the minor version number must be an unsigned 64-bit integer"));
};
(minor, 0)
};
impl RustFeatures { /// Compute the features that must be enabled in a specific Rust target with the latest edition /// available in that target. pub(crate) fn new_with_latest_edition(target: RustTarget) -> Self { Self::new(target, target.latest_edition())
}
}
fn test_target(input: &str, expected: RustTarget) { // Two targets are equivalent if they enable the same set of features let expected = RustFeatures::new_with_latest_edition(expected); let found = RustFeatures::new_with_latest_edition(
input.parse::<RustTarget>().unwrap(),
);
assert_eq!(
expected,
found, "target {input} enables features:\n{found:#?}\nand should enable features:\n{expected:#?}"
);
}
fn test_invalid_target(input: &str) {
assert!(
input.parse::<RustTarget>().is_err(), "{input} should be an invalid target"
);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.