2017-08-13 13:12:21 -07:00
//! Contains code for selecting features
#![ deny(missing_docs) ]
#![ deny(unused_extern_crates) ]
2022-11-22 12:31:14 -05:00
#![ allow(deprecated) ]
2017-08-13 13:12:21 -07:00
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
2022-11-22 12:31:14 -05:00
#[ deprecated = " This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues " ] = > Stable_1_0 = > 1.0 ;
2021-09-17 11:34:11 +02:00
/// Rust stable 1.17
/// * Static lifetime elision ([RFC 1623](https://github.com/rust-lang/rfcs/blob/master/text/1623-static.md))
2022-11-22 12:31:14 -05:00
#[ deprecated = " This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues " ] = > Stable_1_17 = > 1.17 ;
2017-08-13 13:12:21 -07:00
/// Rust stable 1.19
2019-10-28 20:04:56 +01:00
/// * Untagged unions ([RFC 1444](https://github.com/rust-lang/rfcs/blob/master/text/1444-union.md))
2022-11-22 12:31:14 -05:00
#[ deprecated = " This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues " ] = > Stable_1_19 = > 1.19 ;
2018-04-01 17:46:42 -08:00
/// Rust stable 1.20
2019-10-28 20:04:56 +01:00
/// * Associated constants ([PR](https://github.com/rust-lang/rust/pull/42809))
2022-11-22 12:31:14 -05:00
#[ deprecated = " This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues " ] = > Stable_1_20 = > 1.20 ;
2017-10-14 17:18:38 +03:00
/// Rust stable 1.21
2019-10-28 20:04:56 +01:00
/// * Builtin impls for `Clone` ([PR](https://github.com/rust-lang/rust/pull/43690))
2022-11-22 12:31:14 -05:00
#[ deprecated = " This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues " ] = > Stable_1_21 = > 1.21 ;
2018-03-13 12:22:11 +01:00
/// Rust stable 1.25
2019-10-28 20:04:56 +01:00
/// * `repr(align)` ([PR](https://github.com/rust-lang/rust/pull/47006))
2022-11-22 12:31:14 -05:00
#[ deprecated = " This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues " ] = > Stable_1_25 = > 1.25 ;
2018-09-19 02:36:48 +02:00
/// Rust stable 1.26
2019-10-28 20:04:56 +01:00
/// * [i128 / u128 support](https://doc.rust-lang.org/std/primitive.i128.html)
2022-11-22 12:31:14 -05:00
#[ deprecated = " This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues " ] = > Stable_1_26 = > 1.26 ;
2018-11-26 16:59:18 -08:00
/// Rust stable 1.27
2019-10-28 20:04:56 +01:00
/// * `must_use` attribute on functions ([PR](https://github.com/rust-lang/rust/pull/48925))
2022-11-22 12:31:14 -05:00
#[ deprecated = " This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues " ] = > Stable_1_27 = > 1.27 ;
2019-01-03 13:57:45 -08:00
/// Rust stable 1.28
2019-10-28 20:04:56 +01:00
/// * `repr(transparent)` ([PR](https://github.com/rust-lang/rust/pull/51562))
2022-11-22 12:31:14 -05:00
#[ deprecated = " This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues " ] = > Stable_1_28 = > 1.28 ;
2019-06-04 16:52:47 -07:00
/// Rust stable 1.30
2019-10-28 20:04:56 +01:00
/// * `const fn` support for limited cases ([PR](https://github.com/rust-lang/rust/pull/54835/)
/// * [c_void available in core](https://doc.rust-lang.org/core/ffi/enum.c_void.html)
2022-11-22 12:31:14 -05:00
#[ deprecated = " This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues " ] = > Stable_1_30 = > 1.30 ;
2019-01-07 20:06:34 -08:00
/// Rust stable 1.33
2019-10-28 20:04:56 +01:00
/// * repr(packed(N)) ([PR](https://github.com/rust-lang/rust/pull/57049))
2019-01-07 20:06:34 -08:00
= > Stable_1_33 = > 1.33 ;
2019-11-04 17:41:49 +02:00
/// Rust stable 1.36
/// * `MaybeUninit` instead of `mem::uninitialized()` ([PR](https://github.com/rust-lang/rust/pull/60445))
= > Stable_1_36 = > 1.36 ;
2019-12-19 11:26:23 -07:00
/// Rust stable 1.40
/// * `non_exhaustive` enums/structs ([Tracking issue](https://github.com/rust-lang/rust/issues/44109))
= > Stable_1_40 = > 1.40 ;
2021-07-07 06:37:04 -05:00
/// Rust stable 1.47
/// * `larger_arrays` ([Tracking issue](https://github.com/rust-lang/rust/pull/74060))
= > Stable_1_47 = > 1.47 ;
2022-09-22 11:13:50 -05:00
/// Rust stable 1.64
/// * `core_ffi_c` ([Tracking issue](https://github.com/rust-lang/rust/issues/94501))
= > Stable_1_64 = > 1.64 ;
2017-08-13 13:12:21 -07:00
/// Nightly rust
2019-10-28 20:04:56 +01:00
/// * `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
2022-03-13 12:30:06 +13:00
/// * `vectorcall` calling convention (no tracking issue)
2022-11-04 10:19:28 -05:00
/// * `c_unwind` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/74990))
2017-08-13 13:12:21 -07:00
= > Nightly = > nightly ;
) ;
}
}
rust_target_base! ( rust_target_def ) ;
rust_target_base! ( rust_target_values_def ) ;
/// Latest stable release of Rust
2022-09-22 21:20:05 -10:00
pub const LATEST_STABLE_RUST : RustTarget = RustTarget ::Stable_1_64 ;
2017-08-13 13:12:21 -07:00
/// Create RustFeatures struct definition, new(), and a getter for each field
macro_rules ! rust_feature_def {
2018-07-06 20:39:30 -04:00
(
$( $rust_target :ident {
$( $( #[ $attr:meta ] ) * = > $feature :ident ; ) *
} ) *
) = > {
2017-08-13 13:12:21 -07:00
/// Features supported by a rust target
#[ derive(Debug, Copy, Clone, Eq, PartialEq, Hash) ]
2019-10-28 20:04:56 +01:00
#[ allow(missing_docs) ] // Documentation should go into the relevant variants.
pub ( crate ) struct RustFeatures {
2018-07-06 20:39:30 -04:00
$( $(
2018-03-10 07:15:10 +01:00
$(
#[ $attr ]
) *
pub $feature : bool ,
2018-07-06 20:39:30 -04:00
) * ) *
2017-08-13 13:12:21 -07:00
}
impl RustFeatures {
/// Gives a RustFeatures struct with all features disabled
fn new ( ) -> Self {
RustFeatures {
2018-07-06 20:39:30 -04:00
$( $(
2017-08-13 13:12:21 -07:00
$feature : false ,
2018-07-06 20:39:30 -04:00
) * ) *
2017-08-13 13:12:21 -07:00
}
}
}
2018-07-06 20:39:30 -04:00
impl From < RustTarget > for RustFeatures {
fn from ( rust_target : RustTarget ) -> Self {
let mut features = RustFeatures ::new ( ) ;
2017-08-13 13:12:21 -07:00
2018-07-06 20:39:30 -04:00
$(
if rust_target > = RustTarget ::$rust_target {
$(
features . $feature = true ;
) *
}
) *
2018-03-10 07:06:36 +01:00
2018-07-06 20:39:30 -04:00
features
}
2017-08-13 13:12:21 -07:00
}
}
}
2019-10-28 20:04:56 +01:00
// NOTE(emilio): When adding or removing features here, make sure to update the
// documentation for the relevant variant in the rust_target_base macro
// definition.
2018-07-06 20:39:30 -04:00
rust_feature_def! (
2021-09-17 11:34:11 +02:00
Stable_1_17 {
= > static_lifetime_elision ;
}
2018-07-06 20:39:30 -04:00
Stable_1_19 {
= > untagged_union ;
}
Stable_1_20 {
= > associated_const ;
}
Stable_1_21 {
= > builtin_clone_impls ;
}
Stable_1_25 {
= > repr_align ;
}
2018-09-19 02:36:48 +02:00
Stable_1_26 {
= > i128_and_u128 ;
}
2018-11-26 16:59:18 -08:00
Stable_1_27 {
= > must_use_function ;
}
2019-01-03 13:57:45 -08:00
Stable_1_28 {
= > repr_transparent ;
}
2019-06-04 16:52:47 -07:00
Stable_1_30 {
= > min_const_fn ;
2019-10-11 15:39:17 +02:00
= > core_ffi_c_void ;
2019-06-04 16:52:47 -07:00
}
2019-01-07 20:06:34 -08:00
Stable_1_33 {
= > repr_packed_n ;
}
2019-11-04 17:41:49 +02:00
Stable_1_36 {
= > maybe_uninit ;
}
2019-12-19 11:26:23 -07:00
Stable_1_40 {
= > non_exhaustive ;
}
2021-07-07 06:37:04 -05:00
Stable_1_47 {
= > larger_arrays ;
}
2022-09-22 11:13:50 -05:00
Stable_1_64 {
= > core_ffi_c ;
}
2018-07-06 20:39:30 -04:00
Nightly {
= > thiscall_abi ;
2022-03-13 12:30:06 +13:00
= > vectorcall_abi ;
2022-11-04 10:19:28 -05:00
= > c_unwind_abi ;
2018-07-06 20:39:30 -04:00
}
) ;
2017-08-13 13:12:21 -07:00
impl Default for RustFeatures {
fn default ( ) -> Self {
let default_rust_target : RustTarget = Default ::default ( ) ;
Self ::from ( default_rust_target )
}
}
#[ cfg(test) ]
mod test {
2018-07-06 20:39:30 -04:00
#![ allow(unused_imports) ]
2017-08-13 13:12:21 -07:00
use super ::* ;
2018-07-06 20:39:30 -04:00
#[ test ]
fn target_features ( ) {
let f_1_0 = RustFeatures ::from ( RustTarget ::Stable_1_0 ) ;
assert! (
2021-09-17 11:34:11 +02:00
! f_1_0 . static_lifetime_elision & &
! f_1_0 . core_ffi_c_void & &
2019-10-02 22:29:05 -04:00
! f_1_0 . untagged_union & &
2019-09-17 09:44:06 +09:00
! f_1_0 . associated_const & &
! f_1_0 . builtin_clone_impls & &
! f_1_0 . repr_align & &
2022-03-13 12:30:06 +13:00
! f_1_0 . thiscall_abi & &
! f_1_0 . vectorcall_abi
2018-07-06 20:39:30 -04:00
) ;
let f_1_21 = RustFeatures ::from ( RustTarget ::Stable_1_21 ) ;
assert! (
2021-09-17 11:34:11 +02:00
f_1_21 . static_lifetime_elision & &
! f_1_21 . core_ffi_c_void & &
2019-10-02 22:29:05 -04:00
f_1_21 . untagged_union & &
2019-09-17 09:44:06 +09:00
f_1_21 . associated_const & &
f_1_21 . builtin_clone_impls & &
! f_1_21 . repr_align & &
2022-03-13 12:30:06 +13:00
! f_1_21 . thiscall_abi & &
! f_1_21 . vectorcall_abi
2018-07-06 20:39:30 -04:00
) ;
let f_nightly = RustFeatures ::from ( RustTarget ::Nightly ) ;
assert! (
2021-09-17 11:34:11 +02:00
f_nightly . static_lifetime_elision & &
f_nightly . core_ffi_c_void & &
2019-10-02 22:29:05 -04:00
f_nightly . untagged_union & &
2019-09-17 09:44:06 +09:00
f_nightly . associated_const & &
f_nightly . builtin_clone_impls & &
2019-11-04 17:41:49 +02:00
f_nightly . maybe_uninit & &
2019-09-17 09:44:06 +09:00
f_nightly . repr_align & &
2022-03-13 12:30:06 +13:00
f_nightly . thiscall_abi & &
2022-11-04 10:19:28 -05:00
f_nightly . vectorcall_abi & &
f_nightly . c_unwind_abi
2018-07-06 20:39:30 -04:00
) ;
}
2017-08-13 13:12:21 -07:00
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 ) ;
2021-09-17 11:34:11 +02:00
test_target ( " 1.17 " , RustTarget ::Stable_1_17 ) ;
2017-08-13 13:12:21 -07:00
test_target ( " 1.19 " , RustTarget ::Stable_1_19 ) ;
2017-10-14 17:18:38 +03:00
test_target ( " 1.21 " , RustTarget ::Stable_1_21 ) ;
2018-03-13 12:22:11 +01:00
test_target ( " 1.25 " , RustTarget ::Stable_1_25 ) ;
2017-08-13 13:12:21 -07:00
test_target ( " nightly " , RustTarget ::Nightly ) ;
}
}