From f332b4df506de8ce92bc9798aecfc9c9a9eb62c4 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 22 May 2025 15:15:34 -0700 Subject: [PATCH] Add methods to get/set the edition --- src/lib.rs | 36 ++++++++++++++++++++++++++++++++++++ tests/tests.rs | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 55c5b56..69e6ffc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,6 +91,7 @@ pub struct AutoCfg { rustc_version: Version, target: Option, no_std: bool, + edition: Option, rustflags: Vec, uuid: u64, } @@ -203,6 +204,7 @@ impl AutoCfg { rustc_version: rustc_version, target: target, no_std: false, + edition: None, uuid: new_uuid(), }; @@ -246,6 +248,36 @@ impl AutoCfg { self.no_std = no_std; } + /// Returns the `--edition` string that is currently being passed to `rustc`, if any, + /// as configured by the [`set_edition`][Self::set_edition] method. + pub fn edition(&self) -> Option<&str> { + match self.edition { + Some(ref edition) => Some(&**edition), + None => None, + } + } + + /// Sets the `--edition` string that will be passed to `rustc`, + /// or `None` to leave the compiler at its default edition. + /// + /// See also [The Rust Edition Guide](https://doc.rust-lang.org/edition-guide/). + /// + /// **Warning:** Setting an unsupported edition will likely cause **all** subsequent probes to + /// fail! As of this writing, the known editions and their minimum Rust versions are: + /// + /// | Edition | Version | + /// | ------- | ---------- | + /// | 2015 | 1.27.0[^1] | + /// | 2018 | 1.31.0 | + /// | 2021 | 1.56.0 | + /// | 2024 | 1.85.0 | + /// + /// [^1]: Prior to 1.27.0, Rust was effectively 2015 Edition by default, but the concept hadn't + /// been established yet, so the explicit `--edition` flag wasn't supported either. + pub fn set_edition(&mut self, edition: Option) { + self.edition = edition; + } + /// Tests whether the current `rustc` reports a version greater than /// or equal to "`major`.`minor`". pub fn probe_rustc_version(&self, major: usize, minor: usize) -> bool { @@ -282,6 +314,10 @@ impl AutoCfg { .arg(&self.out_dir) .arg("--emit=llvm-ir"); + if let Some(edition) = self.edition.as_ref() { + command.arg("--edition").arg(edition); + } + if let Some(target) = self.target.as_ref() { command.arg("--target").arg(target); } diff --git a/tests/tests.rs b/tests/tests.rs index 8948d32..bd069ee 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -149,3 +149,41 @@ fn probe_cleanup() { // is empty -- i.e. the probe should have removed any output files. std::fs::remove_dir(&dir).unwrap(); } + +#[test] +fn editions() { + let mut ac = autocfg_for_test(); + assert!(ac.edition().is_none()); + assert!(ac.probe_raw("").is_ok()); + + for (edition, minor) in vec![(2015, 27), (2018, 31), (2021, 56), (2024, 85)] { + let edition = edition.to_string(); + ac.set_edition(Some(edition.clone())); + assert_eq!(ac.edition(), Some(&*edition)); + assert_min(&ac, 1, minor, ac.probe_raw("").is_ok()); + } + + ac.set_edition(Some("invalid".into())); + assert_eq!(ac.edition(), Some("invalid")); + assert!(ac.probe_raw("").is_err()); + + ac.set_edition(None); + assert!(ac.edition().is_none()); + assert!(ac.probe_raw("").is_ok()); +} + +#[test] +fn edition_keyword_try() { + let mut ac = autocfg_for_test(); + + if ac.probe_rustc_version(1, 27) { + ac.set_edition(Some(2015.to_string())); + } + assert!(ac.probe_expression("{ let try = 0; try }")); + + if ac.probe_rustc_version(1, 31) { + ac.set_edition(Some(2018.to_string())); + assert!(!ac.probe_expression("{ let try = 0; try }")); + assert!(ac.probe_expression("{ let r#try = 0; r#try }")); + } +}