Skip to content

Commit

Permalink
add support for using raw_ref macros
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Jun 20, 2020
1 parent 031c41f commit 7639486
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ matrix:
script: # `--lib` added to prevent doctests from being compiled.
# This is due to `unstable_const` requiring extra `feature(...)` directives
# which the doctests do not have.
- cargo test --verbose --features unstable_const --lib
- cargo test --verbose --all-features --lib

- env: RUSTFMT
rust: 1.36.0
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ doc-comment = "0.3"
[features]
default = []
unstable_const = []
unstable_raw = []
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ fn main() {
}
```

## Usage in constants ##
## Feature flags ##

### Usage in constants ###
`memoffset` has **experimental** support for compile-time `offset_of!` on a nightly compiler.

In order to use it, you must enable the `unstable_const` crate feature and several compiler features.
Expand All @@ -78,4 +80,9 @@ struct Foo {
}
let foo = [0; offset_of!(Foo, b)]
```
```

### Raw references ###
Recent nightlies support [a way to create raw pointers](https://github.com/rust-lang/rust/issues/73394) that avoids creating intermediate safe references.
`memoffset` can make use of that feature to avoid what is technically Undefined Behavior.
Use the `unstable_raw` feature to enable this.
1 change: 1 addition & 0 deletions ci/miri.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ rustup component add miri
cargo miri setup

cargo miri test
cargo miri test --all-features
5 changes: 4 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@
const_raw_ptr_deref
)
)]
#![cfg_attr(
feature = "unstable_raw",
feature(raw_ref_macros)
)]

#[macro_use]
#[cfg(doctests)]
Expand All @@ -79,7 +83,6 @@ doctest!("../README.md");
// Doing this enables this crate to function under both std and no-std crates.
#[doc(hidden)]
pub use core::mem;

#[doc(hidden)]
pub use core::ptr;

Expand Down
25 changes: 25 additions & 0 deletions src/offset_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,31 @@ macro_rules! _memoffset__field_check {
///
/// The `base` pointer *must not* be dangling, but it *may* point to
/// uninitialized memory.
#[cfg(feature = "unstable_raw")] // Correct variant that uses `raw_const!`.
#[macro_export(local_inner_macros)]
macro_rules! raw_field {
($base:expr, $parent:path, $field:tt) => {{
_memoffset__field_check!($parent, $field);
let base_ptr: *const $parent = $base;

// Get the field address. This is UB because we are creating a reference to
// the uninitialized field. Will be updated to use `&raw` before rustc
// starts exploiting such UB.
// Crucially, we know that this will not trigger a deref coercion because
// of the `field_check!` we did above.
#[allow(unused_unsafe)] // for when the macro is used in an unsafe block
unsafe {
$crate::ptr::raw_const!((*base_ptr).$field)
}
}};
}

/// Computes a const raw pointer to the given field of the given base pointer
/// to the given parent type.
///
/// The `base` pointer *must not* be dangling, but it *may* point to
/// uninitialized memory.
#[cfg(not(feature = "unstable_raw"))] // Incorrect (UB) variant that creates an intermediate reference.
#[macro_export(local_inner_macros)]
macro_rules! raw_field {
($base:expr, $parent:path, $field:tt) => {{
Expand Down

0 comments on commit 7639486

Please sign in to comment.