Skip to content

Commit

Permalink
[unsafe-fields] Add as_ref_checked
Browse files Browse the repository at this point in the history
Makes progress on #1931

gherrit-pr-id: I7ce0c981ed1f1bc1f4ff85dffef2a74114c6e76d
  • Loading branch information
joshlf committed Oct 21, 2024
1 parent f51d666 commit 9092745
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# https://github.com/dtolnay/trybuild/issues/207#issuecomment-131227.594
[workspace]

members = ["unsafe-fields", "zerocopy-derive"]

[workspace.package]
# Inherited by zerocopy and unsafe-fields.
rust-version = "1.65.0"
Expand Down Expand Up @@ -85,7 +87,6 @@ testutil = { path = "testutil" }
# sometimes change the output format slightly, so a version mismatch can cause
# CI test failures.
trybuild = { version = "=1.0.90", features = ["diff"] }
unsafe-fields = { path = "./unsafe-fields" }
# In tests, unlike in production, zerocopy-derive is not optional
zerocopy-derive = { version = "=0.9.0-alpha.0", path = "zerocopy-derive" }
# TODO(#381) Remove this dependency once we have our own layout gadgets.
Expand Down
6 changes: 6 additions & 0 deletions unsafe-fields/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,9 @@ exclude = [".*"]
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"]

[lints.rust]
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(doc_cfg)'] }

[dependencies]
zerocopy_0_8 = { package = "zerocopy", version = "0.8.7", optional = true }
27 changes: 26 additions & 1 deletion unsafe-fields/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
//! the [`Unsafe`] wrapper type. An `Unsafe` is intended to be used to for
//! struct, enum, or union fields which carry safety invariants. All accessors
//! are `unsafe`, which requires any use of an `Unsafe` field to be inside an
//! `unsafe` block.
//! `unsafe` block. One exception is [`Unsafe::as_ref_checked`], which is
//! available when the `zerocopy_0_8` feature is enabled. See its docs for more
//! information.
//!
//! An unsafe field has the type `Unsafe<O, F, const NAME_HASH: u128>`. `O` is
//! the enclosing type (struct, enum, or union), `F` is the type of the field,
Expand All @@ -23,6 +25,8 @@
//! the same enclosing type. Note that swapping the same field between instances
//! of the same type [cannot be prevented](crate#limitations).
//!
//! [immutable]: zerocopy_0_8::Immutable
//!
//! # Examples
//!
//! ```
Expand Down Expand Up @@ -170,6 +174,7 @@
rustdoc::missing_crate_level_docs,
rustdoc::private_intra_doc_links
)]
#![cfg_attr(doc_cfg, feature(doc_cfg))]

use core::marker::PhantomData;

Expand Down Expand Up @@ -220,6 +225,26 @@ impl<O: ?Sized, F: ?Sized, const NAME_HASH: u128> Unsafe<O, F, { NAME_HASH }> {
&self.field
}

/// Gets a reference to the inner value safely so long as the inner value is
/// immutable.
///
/// If [`F: Immutable`][immutable], then `F` does not permit interior
/// mutation, and so it is safe to return a reference to it.
///
/// [immutable]: zerocopy_0_8::Immutable
#[inline(always)]
#[cfg(feature = "zerocopy_0_8")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "zerocopy_0_8")))]
pub const fn as_ref_checked(&self) -> &F
where
F: zerocopy_0_8::Immutable,
{
// SAFETY: `F: Immutable` guarantees that the returned `&F` cannot be
// used to mutate `self`, and so it cannot be used to violate any
// invariant.
unsafe { self.as_ref() }
}

/// Gets a mutable reference to the inner value.
///
/// # Safety
Expand Down

0 comments on commit 9092745

Please sign in to comment.