From 8c5200e9e263747e8ea85db9fcdcda02b763e358 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 20 Jun 2020 14:14:55 +0200 Subject: [PATCH 1/3] add support for using raw_ref macros --- .travis.yml | 2 +- Cargo.toml | 1 + README.md | 11 +++++++++-- ci/miri.sh | 1 + src/lib.rs | 5 ++++- src/offset_of.rs | 23 +++++++++++++++++++++++ 6 files changed, 39 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index f2c919b..6e91a9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/Cargo.toml b/Cargo.toml index cabe0ce..646111d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,3 +18,4 @@ doc-comment = "0.3" [features] default = [] unstable_const = [] +unstable_raw = [] diff --git a/README.md b/README.md index 647302f..e5a5fdb 100644 --- a/README.md +++ b/README.md @@ -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. @@ -78,4 +80,9 @@ struct Foo { } let foo = [0; offset_of!(Foo, b)] -``` \ No newline at end of file +``` + +### 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. diff --git a/ci/miri.sh b/ci/miri.sh index 8873a2c..03ebd73 100644 --- a/ci/miri.sh +++ b/ci/miri.sh @@ -8,3 +8,4 @@ rustup component add miri cargo miri setup cargo miri test +cargo miri test --all-features diff --git a/src/lib.rs b/src/lib.rs index 63960ae..430b597 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,6 +66,10 @@ const_raw_ptr_deref ) )] +#![cfg_attr( + feature = "unstable_raw", + feature(raw_ref_macros) +)] #[macro_use] #[cfg(doctests)] @@ -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; diff --git a/src/offset_of.rs b/src/offset_of.rs index 1607211..25ab88f 100644 --- a/src/offset_of.rs +++ b/src/offset_of.rs @@ -63,6 +63,29 @@ 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 without creating a reference. + // 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) => {{ From a6b5aec20f24e6879dd52b400209d83d364b894d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 20 Jun 2020 15:02:40 +0200 Subject: [PATCH 2/3] fmt --- src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 430b597..39ec097 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,10 +66,7 @@ const_raw_ptr_deref ) )] -#![cfg_attr( - feature = "unstable_raw", - feature(raw_ref_macros) -)] +#![cfg_attr(feature = "unstable_raw", feature(raw_ref_macros))] #[macro_use] #[cfg(doctests)] From 202f1166996d9c1b10bc3795bebdaf582633c63c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 20 Jun 2020 15:09:16 +0200 Subject: [PATCH 3/3] travis config: avoid setting meaningful env vars --- .travis.yml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6e91a9f..646f317 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,12 @@ cache: cargo: true matrix: include: + - name: miri + rust: nightly + os: linux + script: + - sh ci/miri.sh + - rust: 1.19.0 # Oldest supported (first version with numeric fields in struct patterns) - rust: 1.31.0 # Oldest supported with allow(clippy) - rust: 1.36.0 # Oldest supported with MaybeUninit @@ -11,13 +17,7 @@ matrix: - rust: beta - rust: nightly - - env: MIRI - rust: nightly - os: linux - script: - - sh ci/miri.sh - - - env: CONST_OFFSET + - name: all-features rust: nightly os: linux script: # `--lib` added to prevent doctests from being compiled. @@ -25,14 +25,15 @@ matrix: # which the doctests do not have. - cargo test --verbose --all-features --lib - - env: RUSTFMT + - name: rustfmt rust: 1.36.0 install: - rustup component add rustfmt script: - cargo fmt -- --check - - env: RUSTFLAGS="-D warnings" + - name: deny-warnings + env: RUSTFLAGS="-D warnings" rust: 1.33.0 # `stable`: Locking down for consistent behavior script: - cargo check --tests