From 51c83a7b02cc2f961c5ba2446f9c3a3814febe8f Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Fri, 10 Aug 2018 20:35:09 +0200 Subject: [PATCH] check for repr(transparent) in build.rs --- build.rs | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +- 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 build.rs diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..0c0d619 --- /dev/null +++ b/build.rs @@ -0,0 +1,117 @@ +// Copyright © 2018 Trevor Spiteri + +// Copying and distribution of this file, with or without +// modification, are permitted in any medium without royalty provided +// the copyright notice and this notice are preserved. This file is +// offered as-is, without any warranty. + +use std::env; +use std::ffi::OsString; +use std::fs::{self, File}; +use std::io::{Result as IoResult, Write}; +use std::path::{Path, PathBuf}; +use std::process::Command; + +struct Environment { + out_dir: PathBuf, + rustc: OsString, +} + +fn main() { + let env = Environment { + out_dir: PathBuf::from(cargo_env("OUT_DIR")), + rustc: cargo_env("RUSTC"), + }; + env.check_feature( + "repr_transparent", + TRY_REPR_TRANSPARENT, + Some("repr_transparent"), + ); +} + +impl Environment { + fn check_feature(&self, name: &str, contents: &str, nightly_features: Option<&str>) { + let try_dir = self.out_dir.join(format!("try_{}", name)); + let filename = format!("try_{}.rs", name); + create_dir_or_panic(&try_dir); + println!("$ cd {:?}", try_dir); + + enum Iteration { + Stable, + Unstable, + } + for i in &[Iteration::Stable, Iteration::Unstable] { + let s; + let file_contents = match *i { + Iteration::Stable => contents, + Iteration::Unstable => match nightly_features { + Some(features) => { + s = format!("#![feature({})]\n{}", features, contents); + &s + } + None => continue, + }, + }; + create_file_or_panic(&try_dir.join(&filename), file_contents); + let mut cmd = Command::new(&self.rustc); + cmd.current_dir(&try_dir) + .args(&[&filename, "--emit=dep-info,metadata"]); + println!("$ {:?}", cmd); + let status = cmd + .status() + .unwrap_or_else(|_| panic!("Unable to execute: {:?}", cmd)); + if status.success() { + println!("cargo:rustc-cfg={}", name); + if let Iteration::Unstable = *i { + println!("cargo:rustc-cfg=nightly_{}", name); + } + break; + } + } + + remove_dir_or_panic(&try_dir); + } +} + +fn cargo_env(name: &str) -> OsString { + env::var_os(name) + .unwrap_or_else(|| panic!("environment variable not found: {}, please use cargo", name)) +} + +fn remove_dir(dir: &Path) -> IoResult<()> { + if !dir.exists() { + return Ok(()); + } + assert!(dir.is_dir(), "Not a directory: {:?}", dir); + println!("$ rm -r {:?}", dir); + fs::remove_dir_all(dir) +} + +fn remove_dir_or_panic(dir: &Path) { + remove_dir(dir).unwrap_or_else(|_| panic!("Unable to remove directory: {:?}", dir)); +} + +fn create_dir(dir: &Path) -> IoResult<()> { + println!("$ mkdir -p {:?}", dir); + fs::create_dir_all(dir) +} + +fn create_dir_or_panic(dir: &Path) { + create_dir(dir).unwrap_or_else(|_| panic!("Unable to create directory: {:?}", dir)); +} + +fn create_file_or_panic(filename: &Path, contents: &str) { + println!("$ printf '%s' {:?}... > {:?}", &contents[0..20], filename); + let mut file = + File::create(filename).unwrap_or_else(|_| panic!("Unable to create file: {:?}", filename)); + file.write_all(contents.as_bytes()) + .unwrap_or_else(|_| panic!("Unable to write to file: {:?}", filename)); +} + +const TRY_REPR_TRANSPARENT: &str = r#"// try_repr_transparent.rs +#[repr(transparent)] +struct Foo(i32); +fn main() { + let _ = Foo(12); +} +"#; diff --git a/src/lib.rs b/src/lib.rs index 354bd4f..4e6c898 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -81,6 +81,7 @@ additional terms or conditions. #![warn(missing_docs)] #![doc(html_root_url = "https://docs.rs/fixed/0.0.1")] #![doc(test(attr(deny(warnings))))] +#![cfg_attr(nightly_repr_transparent, feature(repr_transparent))] extern crate typenum; @@ -415,7 +416,7 @@ macro_rules! fixed { "[const generics]: https://github.com/rust-lang/rust/issues/44580\n", "[typenum crate]: https://crates.io/crates/typenum\n" ), - #[repr(transparent)] + #[cfg_attr(repr_transparent, repr(transparent))] pub struct $Fixed(($Inner, PhantomData)); }