Skip to content

Commit

Permalink
Add --rust-target to replace --unstable-rust
Browse files Browse the repository at this point in the history
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 stable 1.0.
  • Loading branch information
tmfink committed Aug 4, 2017
1 parent 59dfffe commit 476d1ea
Show file tree
Hide file tree
Showing 89 changed files with 7,897 additions and 891 deletions.
18 changes: 9 additions & 9 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ impl CodeGenerator for Module {
}

if item.id() == ctx.root_module() {
if result.saw_union && !ctx.options().unstable_rust {
if result.saw_union && !ctx.options().rust_features().untagged_union() {
utils::prepend_union_types(ctx, &mut *result);
}
if result.saw_incomplete_array {
Expand Down Expand Up @@ -911,8 +911,8 @@ impl<'a> FieldCodegen<'a> for FieldData {
let field_ty = ctx.resolve_type(self.ty());
let ty = self.ty().to_rust_ty_or_opaque(ctx, &());

// NB: In unstable rust we use proper `union` types.
let ty = if parent.is_union() && !ctx.options().unstable_rust {
// NB: If supported, we use proper `union` types.
let ty = if parent.is_union() && !ctx.options().rust_features().untagged_union() {
if ctx.options().enable_cxx_namespaces {
quote_ty!(ctx.ext_cx(), root::__BindgenUnionField<$ty>)
} else {
Expand Down Expand Up @@ -1052,8 +1052,8 @@ impl BitfieldUnit {
-> P<ast::Item> {
let ctor_name = self.ctor_name(ctx);

// If we're generating unstable Rust, add the const.
let fn_prefix = if ctx.options().unstable_rust {
// If supported, add the const.
let fn_prefix = if ctx.options().rust_features().const_fn() {
quote_tokens!(ctx.ext_cx(), pub const fn)
} else {
quote_tokens!(ctx.ext_cx(), pub fn)
Expand Down Expand Up @@ -1115,8 +1115,8 @@ impl Bitfield {
let offset = self.offset_into_unit();
let mask = self.mask();

// If we're generating unstable Rust, add the const.
let fn_prefix = if ctx.options().unstable_rust {
// If supported, add the const.
let fn_prefix = if ctx.options().rust_features().const_fn() {
quote_tokens!(ctx.ext_cx(), pub const fn)
} else {
quote_tokens!(ctx.ext_cx(), pub fn)
Expand Down Expand Up @@ -1445,7 +1445,7 @@ impl CodeGenerator for CompInfo {
}

let canonical_name = item.canonical_name(ctx);
let builder = if is_union && ctx.options().unstable_rust {
let builder = if is_union && ctx.options().rust_features().untagged_union() {
aster::AstBuilder::new()
.item()
.pub_()
Expand Down Expand Up @@ -1552,7 +1552,7 @@ impl CodeGenerator for CompInfo {
());
}

if is_union && !ctx.options().unstable_rust {
if is_union && !ctx.options().rust_features().untagged_union() {
let layout = layout.expect("Unable to get layout information?");
let ty = BlobTyBuilder::new(layout).build();
let field = StructFieldBuilder::named("bindgen_union_field")
Expand Down
187 changes: 187 additions & 0 deletions src/features.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
//! 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;

#[allow(dead_code)]
/// 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
#[allow(dead_code)]
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);
}
}
2 changes: 1 addition & 1 deletion src/ir/analysis/derive_copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> {
}

if info.kind() == CompKind::Union {
if !self.ctx.options().unstable_rust {
if !self.ctx.options().rust_features().untagged_union() {
// NOTE: If there's no template parameters we can derive copy
// unconditionally, since arrays are magical for rustc, and
// __BindgenUnionField always implements copy.
Expand Down
2 changes: 1 addition & 1 deletion src/ir/analysis/derive_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
);

if info.kind() == CompKind::Union {
if self.ctx.options().unstable_rust {
if self.ctx.options().rust_features().untagged_union() {
trace!(" cannot derive Debug for Rust unions");
return self.insert(id);
}
Expand Down
2 changes: 1 addition & 1 deletion src/ir/analysis/derive_default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDefault<'ctx, 'gen> {
);

if info.kind() == CompKind::Union {
if self.ctx.options().unstable_rust {
if self.ctx.options().rust_features().untagged_union() {
trace!(" cannot derive Default for Rust unions");
return self.insert(id);
}
Expand Down
Loading

0 comments on commit 476d1ea

Please sign in to comment.