summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-08-20 05:01:56 -0500
committerGitHub <noreply@github.com>2017-08-20 05:01:56 -0500
commit79447a288fe4ae3c9432e61d60818b5a9b526b15 (patch)
treeddbcb12e23f622775669afa7e9abb6ca805a1f88
parent5f627fdb708fe72456222cb497028b424a4b2d78 (diff)
parent22508cea270b5fe2140805ef0f2c685d11d28677 (diff)
Auto merge of #922 - tmfink:doc-unions, r=emilio
Update doc for unions Addresses #832 I also modified the `--help` text to print the default Rust target.
-rw-r--r--book/src/using-unions.md66
-rw-r--r--src/options.rs30
2 files changed, 54 insertions, 42 deletions
diff --git a/book/src/using-unions.md b/book/src/using-unions.md
index 9ee10a92..9a0cc3ee 100644
--- a/book/src/using-unions.md
+++ b/book/src/using-unions.md
@@ -1,10 +1,14 @@
# Using the Union Types Generated by Bindgen
-**NOTE:** As of Rust version 1.17, Rust does not have a stable `union` type. Issue [#32836](https://github.com/rust-lang/rust/issues/32836) tracks the stabilization of a `union` type in Rust.
+**NOTE**: Rust 1.19 stabilized the `union` type (see Rust issue [#32836](https://github.com/rust-lang/rust/issues/32836)).
-By using the flag `--unstable-rust`, bindgen will generate the preliminary unstable `union` type.
+You can pass the `--rust-target` option to tell `bindgen` to target a specific version of Rust.
+By default, `bindgen` will target the latest stable Rust.
+The `--rust-target` option accepts a specific stable version (such as "1.0" or "1.19") or "nightly".
-In general, most interactions with unions (either reading or writing) are unsafe.
+**NOTE**: The `--unstable-rust` option is deprecated; use `--rust-target nightly` instead.
+
+In general, most interactions with unions (either reading or writing) are unsafe, meaning you must surround union accesses in an `unsafe {}` block.
For this discussion, we will use the following C type definitions:
@@ -31,46 +35,47 @@ typedef union {
### Library
-* [`bindgen::Builder::unstable_rust()`](https://docs.rs/bindgen/0.25.3/bindgen/struct.Builder.html#method.unstable_rust)
-* [`bindgen::Builder::derive_default()`](https://docs.rs/bindgen/0.25.3/bindgen/struct.Builder.html#method.derive_default)
+* [`bindgen::Builder::rust_target()`](https://docs.rs/bindgen/0.29.0/bindgen/struct.Builder.html#method.rust_target) <!-- Update when live -->
+* [`bindgen::Builder::derive_default()`](https://docs.rs/bindgen/0.29.0/bindgen/struct.Builder.html#method.derive_default)
### Command Line
-* `--unstable-rust`
+* `--rust-target`
* `--with-derive-default`
-## Using the unstable `union` version
+## Which union type will Bindgen generate?
-With `struct`s generated by bindgen from C, it is possible to initialize fields in a "normal" rust way:
+Bindgen can emit one of two Rust types that correspond to C unions:
-```rust,ignore
-mod bindings;
+* Rust's `union` builtin (only available in Rust >= 1.19, including nightly)
+* Bindgen's `BindgenUnion` (available for all Rust targets)
-fn main() {
- let x = bindings::alpha_t {
- a: 1,
- b: -1,
- };
-}
-```
+Bindgen uses the following logic to determine which Rust union type to emit:
+
+* If the Rust target is >= 1.19 (including nightly) AND each field of the union can derive `Copy`, then generate a `union` builtin.
+* Otherwise, generate a `BindgenUnion`.
+
+## Using the `union` builtin
+
+When using the `union` builtin type, there are two choices for initialization:
-When using the unstable `union` type, there are two choices for initialization: Zeroed, and with a specific variant.
+1. Zero
+2. With a specific variant
```rust,ignore
-#![feature(untagged_unions)]
-mod bindings_unstable;
+mod bindings_builtin_union;
-fn unstable() {
+fn union_builtin() {
// Initalize the union to zero
- let x = bindings_unstable::greek_t::default();
+ let x = bindings_builtin_union::greek_t::default();
// If `--with-derive-default` option is not used, the following may be used
// to initalize the union to zero:
- let x = unsafe{ std::mem::zeroed::<bindings_unstable::greek_t>() };
+ let x = unsafe { std::mem::zeroed::<bindings_builtin_union::greek_t>() };
// Or, it is possible to initialize exactly one variant of the enum:
- let x = bindings_unstable::greek_t {
- alfa: bindings_unstable::alpha_t {
+ let x = bindings_builtin_union::greek_t {
+ alfa: bindings_builtin_union::alpha_t {
a: 1,
b: -1,
},
@@ -83,16 +88,17 @@ fn unstable() {
}
```
-## Using the stable BindgenUnion types
+## Using the `BindgenUnion` type
-For versions of Rust that do not support the new `union` type, bindgen will generate types which provide union-like access to structure fields.
+If the target Rust version does not support the new `union` type or there is a field that cannot derive `Copy`, then bindgen will provide union-like access to a `struct`.
-Interacting with these unions is slightly different than the new `union` types. Whenever a variant of the union is accessed, it must be done through a reference.
+Interacting with these unions is slightly different than the new `union` types.
+You must access union variants through a reference.
```rust,ignore
mod bindings;
-fn stable() {
+fn bindgenunion() {
// `default()` or `zeroed()` may still be used with Bindgen's Union types
let mut x = bindings::greek_t::default();
@@ -116,7 +122,7 @@ fn stable() {
}
```
-If you attempt to access a BindgenUnion field directly, you will see errors like this:
+If you attempt to access a `BindgenUnion` field directly, you will see errors like this:
```text
error[E0308]: mismatched types
diff --git a/src/options.rs b/src/options.rs
index 6640fad4..a6a104d0 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -1,10 +1,9 @@
-
use bindgen::{Builder, CodegenConfig, RUST_TARGET_STRINGS, RustTarget, builder};
use clap::{App, Arg};
use std::fs::File;
use std::io::{self, Error, ErrorKind, Write, stderr};
-use std::str::FromStr;
use std::path::PathBuf;
+use std::str::FromStr;
/// Construct a new [`Builder`](./struct.Builder.html) from command line flags.
pub fn builder_from_flags<I>(
@@ -14,8 +13,10 @@ where
I: Iterator<Item = String>,
{
let rust_target_help = format!(
- "Version of the Rust compiler to target. Valid options are: {:?}.",
- RUST_TARGET_STRINGS);
+ "Version of the Rust compiler to target. Valid options are: {:?}. Defaults to {:?}.",
+ RUST_TARGET_STRINGS,
+ String::from(RustTarget::default())
+ );
let matches = App::new("bindgen")
.version(env!("CARGO_PKG_VERSION"))
@@ -262,8 +263,10 @@ where
if matches.is_present("unstable-rust") {
builder = builder.rust_target(RustTarget::Nightly);
- writeln!(&mut stderr(), "warning: the `--unstable-rust` option is deprecated")
- .expect("Unable to write error message");
+ writeln!(
+ &mut stderr(),
+ "warning: the `--unstable-rust` option is deprecated"
+ ).expect("Unable to write error message");
}
if let Some(rust_target) = matches.value_of("rust-target") {
@@ -487,18 +490,21 @@ where
let path = PathBuf::from(path_str);
if !path.is_absolute() {
- return Err(Error::new(ErrorKind::Other,
- "--rustfmt-configuration--file needs to be an absolute path!"));
+ return Err(Error::new(
+ ErrorKind::Other,
+ "--rustfmt-configuration--file needs to be an absolute path!",
+ ));
}
if path.to_str().is_none() {
- return Err(
- Error::new(ErrorKind::Other,
- "--rustfmt-configuration-file contains non-valid UTF8 characters."));
+ return Err(Error::new(
+ ErrorKind::Other,
+ "--rustfmt-configuration-file contains non-valid UTF8 characters.",
+ ));
}
builder = builder.rustfmt_configuration_file(Some(path));
- }
+ }
let verbose = matches.is_present("verbose");