Skip to content

Commit 718c406

Browse files
dirkbehmeojeda
authored andcommitted
rust: types: extend Opaque documentation
Update the `Opaque` documentation and add an example as proposed by Miguel Ojeda in [1]. The documentation update is mainly taken from Benno Lossin's description [2]. Cc: Nell Shamrell-Harrington <[email protected]> Suggested-by: Miguel Ojeda <[email protected]> Link: https://rust-for-linux.zulipchat.com/#narrow/stream/291565/topic/x/near/467478085 [1] Link: https://rust-for-linux.zulipchat.com/#narrow/stream/291565/topic/x/near/470498289 [2] Co-developed-by: Benno Lossin <[email protected]> Signed-off-by: Benno Lossin <[email protected]> Signed-off-by: Dirk Behme <[email protected]> Link: https://lore.kernel.org/r/[email protected] [ Used `expect`. Rewrapped docs. Added intra-doc link. Formatted example. Reworded to fix tag typo/order. Fixed `&mut` formatting as discussed. Added Benno's SOB and CDB as discussed. Shortened links. - Miguel ] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent 28e8483 commit 718c406

File tree

1 file changed

+52
-1
lines changed

1 file changed

+52
-1
lines changed

Diff for: rust/kernel/types.rs

+52-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,58 @@ impl<T, F: FnOnce(T)> Drop for ScopeGuard<T, F> {
206206

207207
/// Stores an opaque value.
208208
///
209-
/// This is meant to be used with FFI objects that are never interpreted by Rust code.
209+
/// `Opaque<T>` is meant to be used with FFI objects that are never interpreted by Rust code.
210+
///
211+
/// It is used to wrap structs from the C side, like for example `Opaque<bindings::mutex>`.
212+
/// It gets rid of all the usual assumptions that Rust has for a value:
213+
///
214+
/// * The value is allowed to be uninitialized (for example have invalid bit patterns: `3` for a
215+
/// [`bool`]).
216+
/// * The value is allowed to be mutated, when a `&Opaque<T>` exists on the Rust side.
217+
/// * No uniqueness for mutable references: it is fine to have multiple `&mut Opaque<T>` point to
218+
/// the same value.
219+
/// * The value is not allowed to be shared with other threads (i.e. it is `!Sync`).
220+
///
221+
/// This has to be used for all values that the C side has access to, because it can't be ensured
222+
/// that the C side is adhering to the usual constraints that Rust needs.
223+
///
224+
/// Using `Opaque<T>` allows to continue to use references on the Rust side even for values shared
225+
/// with C.
226+
///
227+
/// # Examples
228+
///
229+
/// ```
230+
/// # #![expect(unreachable_pub, clippy::disallowed_names)]
231+
/// use kernel::types::Opaque;
232+
/// # // Emulate a C struct binding which is from C, maybe uninitialized or not, only the C side
233+
/// # // knows.
234+
/// # mod bindings {
235+
/// # pub struct Foo {
236+
/// # pub val: u8,
237+
/// # }
238+
/// # }
239+
///
240+
/// // `foo.val` is assumed to be handled on the C side, so we use `Opaque` to wrap it.
241+
/// pub struct Foo {
242+
/// foo: Opaque<bindings::Foo>,
243+
/// }
244+
///
245+
/// impl Foo {
246+
/// pub fn get_val(&self) -> u8 {
247+
/// let ptr = Opaque::get(&self.foo);
248+
///
249+
/// // SAFETY: `Self` is valid from C side.
250+
/// unsafe { (*ptr).val }
251+
/// }
252+
/// }
253+
///
254+
/// // Create an instance of `Foo` with the `Opaque` wrapper.
255+
/// let foo = Foo {
256+
/// foo: Opaque::new(bindings::Foo { val: 0xdb }),
257+
/// };
258+
///
259+
/// assert_eq!(foo.get_val(), 0xdb);
260+
/// ```
210261
#[repr(transparent)]
211262
pub struct Opaque<T> {
212263
value: UnsafeCell<MaybeUninit<T>>,

0 commit comments

Comments
 (0)