Skip to content

Commit de180c4

Browse files
author
bors-servo
authored
Auto merge of #859 - tmfink:feature-832-custom-rust-target, r=fitzgen
Feature 832 custom rust target 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 `--rust-target nightly`. The definitions of `RustTarget` and `RustFeatures` are created with macros. In order to keep the test outputs the same, `bindgen-flags: --rust-target 1.0` was added to test headers. **Todo:** - [x] Create `RustFeatures`/`RustTarget` structs - [x] Replace uses of `unstable` with `RustFeatures` query - [x] Add new tests - [x] Fix doc comments TODOs
2 parents 04fdb10 + 0bb7b9f commit de180c4

File tree

89 files changed

+7897
-891
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+7897
-891
lines changed

src/codegen/mod.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ impl CodeGenerator for Module {
350350
}
351351

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

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

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

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

14471447
let canonical_name = item.canonical_name(ctx);
1448-
let builder = if is_union && ctx.options().unstable_rust {
1448+
let builder = if is_union && ctx.options().rust_features().untagged_union() {
14491449
aster::AstBuilder::new()
14501450
.item()
14511451
.pub_()
@@ -1552,7 +1552,7 @@ impl CodeGenerator for CompInfo {
15521552
());
15531553
}
15541554

1555-
if is_union && !ctx.options().unstable_rust {
1555+
if is_union && !ctx.options().rust_features().untagged_union() {
15561556
let layout = layout.expect("Unable to get layout information?");
15571557
let ty = BlobTyBuilder::new(layout).build();
15581558
let field = StructFieldBuilder::named("bindgen_union_field")

src/features.rs

+187
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
//! Contains code for selecting features
2+
3+
#![deny(missing_docs)]
4+
#![deny(warnings)]
5+
#![deny(unused_extern_crates)]
6+
7+
use std::io;
8+
use std::str::FromStr;
9+
10+
/// Define RustTarget struct definition, Default impl, and conversions
11+
/// between RustTarget and String.
12+
macro_rules! rust_target_def {
13+
( $( $( #[$attr:meta] )* => $release:ident => $value:expr; )* ) => {
14+
/// Represents the version of the Rust language to target.
15+
///
16+
/// To support a beta release, use the corresponding stable release.
17+
///
18+
/// This enum will have more variants added as necessary.
19+
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Hash)]
20+
#[allow(non_camel_case_types)]
21+
pub enum RustTarget {
22+
$(
23+
$(
24+
#[$attr]
25+
)*
26+
$release,
27+
)*
28+
}
29+
30+
impl Default for RustTarget {
31+
/// Gives the latest stable Rust version
32+
fn default() -> RustTarget {
33+
LATEST_STABLE_RUST
34+
}
35+
}
36+
37+
impl FromStr for RustTarget {
38+
type Err = io::Error;
39+
40+
#[allow(dead_code)]
41+
/// Create a `RustTarget` from a string.
42+
///
43+
/// * The stable/beta versions of Rust are of the form "1.0",
44+
/// "1.19", etc.
45+
/// * The nightly version should be specified with "nightly".
46+
fn from_str(s: &str) -> Result<Self, Self::Err> {
47+
match s.as_ref() {
48+
$(
49+
stringify!($value) => Ok(RustTarget::$release),
50+
)*
51+
_ => Err(
52+
io::Error::new(
53+
io::ErrorKind::InvalidInput,
54+
concat!(
55+
"Got an invalid rust target. Accepted values ",
56+
"are of the form ",
57+
"\"1.0\" or \"nightly\"."))),
58+
}
59+
}
60+
}
61+
62+
impl From<RustTarget> for String {
63+
fn from(target: RustTarget) -> Self {
64+
match target {
65+
$(
66+
RustTarget::$release => stringify!($value),
67+
)*
68+
}.into()
69+
}
70+
}
71+
}
72+
}
73+
74+
/// Defines an array slice with all RustTarget values
75+
macro_rules! rust_target_values_def {
76+
( $( $( #[$attr:meta] )* => $release:ident => $value:expr; )* ) => {
77+
/// Strings of allowed `RustTarget` values
78+
#[allow(dead_code)]
79+
pub static RUST_TARGET_STRINGS: &'static [&str] = &[
80+
$(
81+
stringify!($value),
82+
)*
83+
];
84+
}
85+
}
86+
87+
/// Defines macro which takes a macro
88+
macro_rules! rust_target_base {
89+
( $x_macro:ident ) => {
90+
$x_macro!(
91+
/// Rust stable 1.0
92+
=> Stable_1_0 => 1.0;
93+
/// Rust stable 1.19
94+
=> Stable_1_19 => 1.19;
95+
/// Nightly rust
96+
=> Nightly => nightly;
97+
);
98+
}
99+
}
100+
101+
rust_target_base!(rust_target_def);
102+
rust_target_base!(rust_target_values_def);
103+
104+
/// Latest stable release of Rust
105+
pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_19;
106+
107+
/// Create RustFeatures struct definition, new(), and a getter for each field
108+
macro_rules! rust_feature_def {
109+
( $( $( #[$attr:meta] )* => $feature:ident; )* ) => {
110+
/// Features supported by a rust target
111+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
112+
pub struct RustFeatures {
113+
$(
114+
$feature: bool,
115+
)*
116+
}
117+
118+
impl RustFeatures {
119+
/// Gives a RustFeatures struct with all features disabled
120+
fn new() -> Self {
121+
RustFeatures {
122+
$(
123+
$feature: false,
124+
)*
125+
}
126+
}
127+
128+
$(
129+
$(
130+
#[$attr]
131+
)*
132+
pub fn $feature(&self) -> bool {
133+
self.$feature
134+
}
135+
)*
136+
}
137+
}
138+
}
139+
140+
rust_feature_def!(
141+
/// Untagged unions ([RFC 1444](https://github.com/rust-lang/rfcs/blob/master/text/1444-union.md))
142+
=> untagged_union;
143+
/// Constant function ([RFC 911](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md))
144+
=> const_fn;
145+
);
146+
147+
impl From<RustTarget> for RustFeatures {
148+
fn from(rust_target: RustTarget) -> Self {
149+
let mut features = RustFeatures::new();
150+
151+
if rust_target >= RustTarget::Stable_1_19 {
152+
features.untagged_union = true;
153+
}
154+
155+
if rust_target >= RustTarget::Nightly {
156+
features.const_fn = true;
157+
}
158+
159+
features
160+
}
161+
}
162+
163+
impl Default for RustFeatures {
164+
fn default() -> Self {
165+
let default_rust_target: RustTarget = Default::default();
166+
Self::from(default_rust_target)
167+
}
168+
}
169+
170+
#[cfg(test)]
171+
mod test {
172+
#![allow(unused_imports)]
173+
use super::*;
174+
175+
fn test_target(target_str: &str, target: RustTarget) {
176+
let target_string: String = target.into();
177+
assert_eq!(target_str, target_string);
178+
assert_eq!(target, RustTarget::from_str(target_str).unwrap());
179+
}
180+
181+
#[test]
182+
fn str_to_target() {
183+
test_target("1.0", RustTarget::Stable_1_0);
184+
test_target("1.19", RustTarget::Stable_1_19);
185+
test_target("nightly", RustTarget::Nightly);
186+
}
187+
}

src/ir/analysis/derive_copy.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> {
207207
}
208208

209209
if info.kind() == CompKind::Union {
210-
if !self.ctx.options().unstable_rust {
210+
if !self.ctx.options().rust_features().untagged_union() {
211211
// NOTE: If there's no template parameters we can derive copy
212212
// unconditionally, since arrays are magical for rustc, and
213213
// __BindgenUnionField always implements copy.

src/ir/analysis/derive_debug.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
208208
);
209209

210210
if info.kind() == CompKind::Union {
211-
if self.ctx.options().unstable_rust {
211+
if self.ctx.options().rust_features().untagged_union() {
212212
trace!(" cannot derive Debug for Rust unions");
213213
return self.insert(id);
214214
}

src/ir/analysis/derive_default.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDefault<'ctx, 'gen> {
242242
);
243243

244244
if info.kind() == CompKind::Union {
245-
if self.ctx.options().unstable_rust {
245+
if self.ctx.options().rust_features().untagged_union() {
246246
trace!(" cannot derive Default for Rust unions");
247247
return self.insert(id);
248248
}

0 commit comments

Comments
 (0)