More private & unsafe blocks, mut and raw pointers?

Background (limitations of my targets (plural)

  • This is an embedded target, so "no_std" applies.
  • There is no allocator for this target.
  • There is NO rtos for this target, so I do not have mutexes.

So I have a few problems below that I'm not getting past.
I have reduced the app to a few dozen lines (started with several thousand)

a) What is the "more private" thing? Im not following. The EdebugContext is a "driver context' for a C language driver that requires a structure pointer as parameter 0 (think "this pointer" in C++)

b) At the end, (line 34) it wants a raw mut pointer - but when I do that - other things blow up.

c) Sometimes it says I need an unsafe block, I add that - and then it tells me I do not need the unsafe block - Fustrating.

#[repr(C)]
struct EdebugContext {
    dummy : u32, // actual struct is way more complex
}

unsafe extern "C" {
     pub fn EDEBUG_por_init(edebug_ptr: *mut EdebugContext );
     // Example C function 1.
     pub fn EDEBUG_this( edebug_ptr: *mut EdebugContext, value : u32 );
     // there are several more :-(
}

pub static mut global_debug_context : EdebugContext = EdebugContext {dummy : 0};

pub fn edebug2_por_init( ctx : &mut EdebugContext )
{
   unsafe { EDEBUG_por_init( ctx ); }
}

pub fn edebug2_this( ctx : &mut EdebugContext, value : u32 )
{
    unsafe { EDEBUG_this( ctx, value ); }
}

/* Non context functions */

pub fn edebug_por( )
{
   unsafe { edebug2_por_init( &mut global_debug_context ); }
}

pub fn edebug_this( value : u32 )
{
    unsafe { edebug2_this( &mut global_debug_context, value ); }
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
warning: type `EdebugContext` is more private than the item `global_debug_context`
  --> src/lib.rs:13:1
   |
13 | pub static mut global_debug_context : EdebugContext = EdebugContext {dummy : 0};
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ static `global_debug_context` is reachable at visibility `pub`
   |
note: but type `EdebugContext` is only usable at visibility `pub(crate)`
  --> src/lib.rs:2:1
   |
 2 | struct EdebugContext {
   | ^^^^^^^^^^^^^^^^^^^^
   = note: `#[warn(private_interfaces)]` on by default

warning: type `EdebugContext` is more private than the item `edebug2_por_init`
  --> src/lib.rs:15:1
   |
15 | pub fn edebug2_por_init( ctx : &mut EdebugContext )
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `edebug2_por_init` is reachable at visibility `pub`
   |
note: but type `EdebugContext` is only usable at visibility `pub(crate)`
  --> src/lib.rs:2:1
   |
 2 | struct EdebugContext {
   | ^^^^^^^^^^^^^^^^^^^^

warning: type `EdebugContext` is more private than the item `edebug2_this`
  --> src/lib.rs:20:1
   |
20 | pub fn edebug2_this( ctx : &mut EdebugContext, value : u32 )
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `edebug2_this` is reachable at visibility `pub`
   |
note: but type `EdebugContext` is only usable at visibility `pub(crate)`
  --> src/lib.rs:2:1
   |
 2 | struct EdebugContext {
   | ^^^^^^^^^^^^^^^^^^^^

warning: type `EdebugContext` is more private than the item `EDEBUG_por_init`
 --> src/lib.rs:7:6
  |
7 |      pub fn EDEBUG_por_init(edebug_ptr: *mut EdebugContext );
  |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `EDEBUG_por_init` is reachable at visibility `pub`
  |
note: but type `EdebugContext` is only usable at visibility `pub(crate)`
 --> src/lib.rs:2:1
  |
2 | struct EdebugContext {
  | ^^^^^^^^^^^^^^^^^^^^

warning: type `EdebugContext` is more private than the item `EDEBUG_this`
 --> src/lib.rs:9:6
  |
9 |      pub fn EDEBUG_this( edebug_ptr: *mut EdebugContext, value : u32 );
  |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `EDEBUG_this` is reachable at visibility `pub`
  |
note: but type `EdebugContext` is only usable at visibility `pub(crate)`
 --> src/lib.rs:2:1
  |
2 | struct EdebugContext {
  | ^^^^^^^^^^^^^^^^^^^^

warning: static variable `global_debug_context` should have an upper case name
  --> src/lib.rs:13:16
   |
13 | pub static mut global_debug_context : EdebugContext = EdebugContext {dummy : 0};
   |                ^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to upper case: `GLOBAL_DEBUG_CONTEXT`
   |
   = note: `#[warn(non_upper_case_globals)]` on by default

error: creating a mutable reference to mutable static
  --> src/lib.rs:29:31
   |
29 |    unsafe { edebug2_por_init( &mut global_debug_context ); }
   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^ mutable reference to mutable static
   |
   = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
   = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
   = note: `#[deny(static_mut_refs)]` on by default
help: use `&raw mut` instead to create a raw pointer
   |
29 |    unsafe { edebug2_por_init( &raw mut global_debug_context ); }
   |                                +++

error: creating a mutable reference to mutable static
  --> src/lib.rs:34:28
   |
34 |     unsafe { edebug2_this( &mut global_debug_context, value ); }
   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^ mutable reference to mutable static
   |
   = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
   = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
help: use `&raw mut` instead to create a raw pointer
   |
34 |     unsafe { edebug2_this( &raw mut global_debug_context, value ); }
   |                             +++

warning: `playground` (lib) generated 6 warnings
error: could not compile `playground` (lib) due to 2 previous errors; 6 warnings emitted

You have things like

pub fn edebug2_por_init( ctx : &mut EdebugContext )

but if EdebugContext is not pub, there's no way for outside consumers to actually call the function.

Quickest fix without considering what you intend to be public or not:

-struct EdebugContext {
+pub struct EdebugContext {

The real intention is to get you to use something that's not a static mut, because it's so hard to use correctly the experts get it wrong.[1] Your options are more limited than most because you're on embedded. If you just want to get on with it, you can...

unsafe { edebug2_por_init( &mut * &raw mut global_debug_context ); }

...but as the beginning of that issue notes, a newtype using UnsafeCell would have less footguns. Or avoiding static mut some other way.

(&raw mut _ is a way to get a *mut _ to a place without creating a &mut _. So another possibility is sticking with *mut _ in your functions and making them unsafe to call... which may make sense if the only EdebugContext is always going to be unsafe to access.)


  1. Key points are made in the first dozen comments or so. The issue was closed because you have to go through the &raw mut dance now, and more options are also now available in std. â†Šī¸Ž

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.