Skip to content

Commit 8c71eed

Browse files
author
bors-servo
authored
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.
2 parents 98d7171 + e7fa289 commit 8c71eed

File tree

103 files changed

+8012
-961
lines changed

Some content is hidden

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

103 files changed

+8012
-961
lines changed

src/codegen/mod.rs

+21-9
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ struct CodegenResult<'a> {
8484
/// need to be referenced by anything.
8585
codegen_id: &'a Cell<usize>,
8686

87+
/// Whether a bindgen union has been generated at least once.
88+
saw_bindgen_union: bool,
89+
8790
/// Whether an union has been generated at least once.
8891
saw_union: bool,
8992

@@ -124,6 +127,7 @@ impl<'a> CodegenResult<'a> {
124127
CodegenResult {
125128
items: vec![],
126129
saw_union: false,
130+
saw_bindgen_union: false,
127131
saw_incomplete_array: false,
128132
saw_objc: false,
129133
codegen_id: codegen_id,
@@ -138,6 +142,11 @@ impl<'a> CodegenResult<'a> {
138142
self.saw_union = true;
139143
}
140144

145+
fn saw_bindgen_union(&mut self) {
146+
self.saw_union();
147+
self.saw_bindgen_union = true;
148+
}
149+
141150
fn saw_incomplete_array(&mut self) {
142151
self.saw_incomplete_array = true;
143152
}
@@ -360,7 +369,7 @@ impl CodeGenerator for Module {
360369
}
361370

362371
if item.id() == ctx.root_module() {
363-
if result.saw_union && !ctx.options().unstable_rust {
372+
if result.saw_bindgen_union {
364373
utils::prepend_union_types(ctx, &mut *result);
365374
}
366375
if result.saw_incomplete_array {
@@ -943,8 +952,8 @@ impl<'a> FieldCodegen<'a> for FieldData {
943952
let field_ty = ctx.resolve_type(self.ty());
944953
let ty = self.ty().to_rust_ty_or_opaque(ctx, &());
945954

946-
// NB: In unstable rust we use proper `union` types.
947-
let ty = if parent.is_union() && !ctx.options().unstable_rust {
955+
// NB: If supported, we use proper `union` types.
956+
let ty = if parent.is_union() && !parent.can_be_rust_union(ctx) {
948957
if ctx.options().enable_cxx_namespaces {
949958
quote_ty!(ctx.ext_cx(), root::__BindgenUnionField<$ty>)
950959
} else {
@@ -1077,8 +1086,8 @@ impl BitfieldUnit {
10771086
) -> P<ast::Item> {
10781087
let ctor_name = self.ctor_name(ctx);
10791088

1080-
// If we're generating unstable Rust, add the const.
1081-
let fn_prefix = if ctx.options().unstable_rust {
1089+
// If supported, add the const.
1090+
let fn_prefix = if ctx.options().rust_features().const_fn() {
10821091
quote_tokens!(ctx.ext_cx(), pub const fn)
10831092
} else {
10841093
quote_tokens!(ctx.ext_cx(), pub fn)
@@ -1138,8 +1147,8 @@ impl Bitfield {
11381147
let offset = self.offset_into_unit();
11391148
let mask = self.mask();
11401149

1141-
// If we're generating unstable Rust, add the const.
1142-
let fn_prefix = if ctx.options().unstable_rust {
1150+
// If supported, add the const.
1151+
let fn_prefix = if ctx.options().rust_features().const_fn() {
11431152
quote_tokens!(ctx.ext_cx(), pub const fn)
11441153
} else {
11451154
quote_tokens!(ctx.ext_cx(), pub fn)
@@ -1491,7 +1500,7 @@ impl CodeGenerator for CompInfo {
14911500
}
14921501

14931502
let canonical_name = item.canonical_name(ctx);
1494-
let builder = if is_union && ctx.options().unstable_rust {
1503+
let builder = if is_union && self.can_be_rust_union(ctx) {
14951504
aster::AstBuilder::new()
14961505
.item()
14971506
.pub_()
@@ -1571,6 +1580,9 @@ impl CodeGenerator for CompInfo {
15711580
}
15721581
if is_union {
15731582
result.saw_union();
1583+
if !self.can_be_rust_union(ctx) {
1584+
result.saw_bindgen_union();
1585+
}
15741586
}
15751587

15761588
let layout = item.kind().expect_type().layout(ctx);
@@ -1600,7 +1612,7 @@ impl CodeGenerator for CompInfo {
16001612
);
16011613
}
16021614

1603-
if is_union && !ctx.options().unstable_rust {
1615+
if is_union && !self.can_be_rust_union(ctx) {
16041616
let layout = layout.expect("Unable to get layout information?");
16051617
let ty = BlobTyBuilder::new(layout).build();
16061618
let field = StructFieldBuilder::named("bindgen_union_field")

src/features.rs

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

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
}

src/ir/analysis/derive_hash.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveHash<'ctx, 'gen> {
232232
);
233233

234234
if info.kind() == CompKind::Union {
235-
if self.ctx.options().unstable_rust {
235+
if self.ctx.options().rust_features().untagged_union() {
236236
trace!(" cannot derive Hash for Rust unions");
237237
return self.insert(id);
238238
}

src/ir/comp.rs

+17
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use super::traversal::{EdgeKind, Trace, Tracer};
1010
use super::template::TemplateParameters;
1111
use clang;
1212
use codegen::struct_layout::{align_to, bytes_from_bits_pow2};
13+
use ir::derive::CanDeriveCopy;
1314
use parse::{ClangItemParser, ParseError};
1415
use peeking_take_while::PeekableExt;
1516
use std::cell::Cell;
@@ -1316,6 +1317,22 @@ impl CompInfo {
13161317
pub fn compute_bitfield_units(&mut self, ctx: &BindgenContext) {
13171318
self.fields.compute_bitfield_units(ctx);
13181319
}
1320+
1321+
/// Returns whether the current union can be represented as a Rust `union`
1322+
///
1323+
/// Requirements:
1324+
/// 1. Current RustTarget allows for `untagged_union`
1325+
/// 2. Each field can derive `Copy`
1326+
pub fn can_be_rust_union(&self, ctx: &BindgenContext) -> bool {
1327+
ctx.options().rust_features().untagged_union() &&
1328+
self.fields().iter().all(|f|
1329+
match *f {
1330+
Field::DataMember(ref field_data) => field_data.ty().can_derive_copy(ctx),
1331+
Field::Bitfields(_) => false,
1332+
}
1333+
)
1334+
}
1335+
13191336
}
13201337

13211338
impl DotAttributes for CompInfo {

0 commit comments

Comments
 (0)