Please, add attribute "called_from", for strongly checking caller fn. For example, it's needed when all unsafe fn's moved to one module, and each such fn must be called only from relevant fn in another module.
What sort of use case leads to a pub function in one module needing a hard guarantee that only one other specific place in a separate module calls it? That seems like a sign that the module boundaries are simply in the wrong place.
For unsafe functions specifically, unsafe and safe functions should generally be in a module together which exposes a safe boundary. Having a public unsafe function which should only be called from one place in another module does indeed feel like a mistake in design.
Agreed with the above. Also worth noting that #[track_caller] was approved about a year ago and is currently tracked in https://github.com/rust-lang/rust/issues/47809.
But I need this project design, since the attribute #![forbid(unsafe_code)] will be used for the remaining modules
It is not advisable for me to use track_caller, because the verification will have to be done at runtime. But I need a compile time check.
It's possible to use pub(in crate::foo) to make the function only accessible to that specific module. But this only works for parent modules. Maybe that could be extended to work with sibling modules.
It's possible to use
pub(in crate::foo)to make the function only accessible to that specific module. But this only works for parent modules. Maybe that could be extended to work with sibling modules.
It's not solution for me. And I need set visibility on specific function, not module.
Can you give an example of your setup so that we can better understand the situation?
Can you give an example of your setup so that we can better understand the situation?
For example:
#[forbid(unsafe_code)]
mod a{
pub fn foo(){
bar();
}
}
mod unsafe_fns{
//#[called_from(crate::a::foo)]
pub fn bar(){
unsafe{
//do_something, for example, writing to io port;
}
}
}
fundamentally, safe code that is only safe if called from a specific other function isn't safe code.
either make bar actually always be safe or remove the forbid(unsafe_code) from foo and make it use an unsafe block.
It's possible to create proc_macro lib for adding this attribute?
a proc-macro gets tokens as input and had tokens as output. However, using just the tokens of a function as input you cannot read where _else_ in the program that function is called from.
Is there a reason you cannot change how you use this unsafe code? Your proposed design seems very easy to misuse on accident.
Reason: increased security requirements.
All unsafe sections of code can be easily checked when they are in the same module
That doesn't increase security though.
It may look like paranoia, but it is necessary
For code to be marked safe it has to be legal to call from anywhere. If your code can't be called from anywhere don't mark it safe.
Moving it into a module marked safe where all the unsafe blocks go, but that you can't actually be called from everywhere, is just giving yourself more problems.
You should attempt to engineer the code differently. For example you could require the functions take a reference to initialization token to prove that an API has been started properly.
If I will use initialization token, how I can deny moving it to other modules?
the module location doesn't matter.
but also, you could use normal item visibility if you really have to.
Most helpful comment
What sort of use case leads to a
pubfunction in one module needing a hard guarantee that only one other specific place in a separate module calls it? That seems like a sign that the module boundaries are simply in the wrong place.