-
Notifications
You must be signed in to change notification settings - Fork 706
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #892 - tmfink:feature-832-custom-rust-target, r=emilio
Re-add --rust-target option to replace --unstable-rust Re-apply commit. Addresses #832 Instead of specifying whether or not to use stable, specify the Rust release to support (one of several stable/beta releases or nightly). The `--unstable-rust` option is still accepted and implies nightly. The definitions of `RustTarget` and `RustFeatures` are created with macros. For each test that uses unions, there is a version that uses the latest stable and 1.0.
- Loading branch information
Showing
103 changed files
with
8,012 additions
and
961 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
//! Contains code for selecting features | ||
#![deny(missing_docs)] | ||
#![deny(warnings)] | ||
#![deny(unused_extern_crates)] | ||
|
||
use std::io; | ||
use std::str::FromStr; | ||
|
||
/// Define RustTarget struct definition, Default impl, and conversions | ||
/// between RustTarget and String. | ||
macro_rules! rust_target_def { | ||
( $( $( #[$attr:meta] )* => $release:ident => $value:expr; )* ) => { | ||
/// Represents the version of the Rust language to target. | ||
/// | ||
/// To support a beta release, use the corresponding stable release. | ||
/// | ||
/// This enum will have more variants added as necessary. | ||
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Hash)] | ||
#[allow(non_camel_case_types)] | ||
pub enum RustTarget { | ||
$( | ||
$( | ||
#[$attr] | ||
)* | ||
$release, | ||
)* | ||
} | ||
|
||
impl Default for RustTarget { | ||
/// Gives the latest stable Rust version | ||
fn default() -> RustTarget { | ||
LATEST_STABLE_RUST | ||
} | ||
} | ||
|
||
impl FromStr for RustTarget { | ||
type Err = io::Error; | ||
|
||
/// Create a `RustTarget` from a string. | ||
/// | ||
/// * The stable/beta versions of Rust are of the form "1.0", | ||
/// "1.19", etc. | ||
/// * The nightly version should be specified with "nightly". | ||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
match s.as_ref() { | ||
$( | ||
stringify!($value) => Ok(RustTarget::$release), | ||
)* | ||
_ => Err( | ||
io::Error::new( | ||
io::ErrorKind::InvalidInput, | ||
concat!( | ||
"Got an invalid rust target. Accepted values ", | ||
"are of the form ", | ||
"\"1.0\" or \"nightly\"."))), | ||
} | ||
} | ||
} | ||
|
||
impl From<RustTarget> for String { | ||
fn from(target: RustTarget) -> Self { | ||
match target { | ||
$( | ||
RustTarget::$release => stringify!($value), | ||
)* | ||
}.into() | ||
} | ||
} | ||
} | ||
} | ||
|
||
/// Defines an array slice with all RustTarget values | ||
macro_rules! rust_target_values_def { | ||
( $( $( #[$attr:meta] )* => $release:ident => $value:expr; )* ) => { | ||
/// Strings of allowed `RustTarget` values | ||
pub static RUST_TARGET_STRINGS: &'static [&str] = &[ | ||
$( | ||
stringify!($value), | ||
)* | ||
]; | ||
} | ||
} | ||
|
||
/// Defines macro which takes a macro | ||
macro_rules! rust_target_base { | ||
( $x_macro:ident ) => { | ||
$x_macro!( | ||
/// Rust stable 1.0 | ||
=> Stable_1_0 => 1.0; | ||
/// Rust stable 1.19 | ||
=> Stable_1_19 => 1.19; | ||
/// Nightly rust | ||
=> Nightly => nightly; | ||
); | ||
} | ||
} | ||
|
||
rust_target_base!(rust_target_def); | ||
rust_target_base!(rust_target_values_def); | ||
|
||
/// Latest stable release of Rust | ||
pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_19; | ||
|
||
/// Create RustFeatures struct definition, new(), and a getter for each field | ||
macro_rules! rust_feature_def { | ||
( $( $( #[$attr:meta] )* => $feature:ident; )* ) => { | ||
/// Features supported by a rust target | ||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] | ||
pub struct RustFeatures { | ||
$( | ||
$feature: bool, | ||
)* | ||
} | ||
|
||
impl RustFeatures { | ||
/// Gives a RustFeatures struct with all features disabled | ||
fn new() -> Self { | ||
RustFeatures { | ||
$( | ||
$feature: false, | ||
)* | ||
} | ||
} | ||
|
||
$( | ||
$( | ||
#[$attr] | ||
)* | ||
pub fn $feature(&self) -> bool { | ||
self.$feature | ||
} | ||
)* | ||
} | ||
} | ||
} | ||
|
||
rust_feature_def!( | ||
/// Untagged unions ([RFC 1444](https://github.com/rust-lang/rfcs/blob/master/text/1444-union.md)) | ||
=> untagged_union; | ||
/// Constant function ([RFC 911](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md)) | ||
=> const_fn; | ||
); | ||
|
||
impl From<RustTarget> for RustFeatures { | ||
fn from(rust_target: RustTarget) -> Self { | ||
let mut features = RustFeatures::new(); | ||
|
||
if rust_target >= RustTarget::Stable_1_19 { | ||
features.untagged_union = true; | ||
} | ||
|
||
if rust_target >= RustTarget::Nightly { | ||
features.const_fn = true; | ||
} | ||
|
||
features | ||
} | ||
} | ||
|
||
impl Default for RustFeatures { | ||
fn default() -> Self { | ||
let default_rust_target: RustTarget = Default::default(); | ||
Self::from(default_rust_target) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
#![allow(unused_imports)] | ||
use super::*; | ||
|
||
fn test_target(target_str: &str, target: RustTarget) { | ||
let target_string: String = target.into(); | ||
assert_eq!(target_str, target_string); | ||
assert_eq!(target, RustTarget::from_str(target_str).unwrap()); | ||
} | ||
|
||
#[test] | ||
fn str_to_target() { | ||
test_target("1.0", RustTarget::Stable_1_0); | ||
test_target("1.19", RustTarget::Stable_1_19); | ||
test_target("nightly", RustTarget::Nightly); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.