#![forbid(unsafe_op_in_unsafe_fn)]
#![forbid(unsafe_code)]
trait Foo {
unsafe fn dangerous();
}
struct SafeImpl;
impl Foo for SafeImpl {
unsafe fn dangerous() {
println!("this is safe!");
}
}
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=3f3fbdb3494c6770487823f284c303f9
With forbid(unsafe_op_in_unsafe_fn), an unsafe fn's body in principle no longer has an implicit unsafe block. So, unsafe_code should not trigger on an unsafe fn alone: there is not necessarily any unsafe code inside!
This has practical effect. Consider one crate defining interfaces with unsafe methods (e.g. representing an OS API). Another crate wants to create mock implementations of these interfaces that are 100% safe. While any crate consuming these mocks will necessarily contain unsafe {...} blocks, it is nice for the test support crate to declare it itself has only safe code.
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=3f3fbdb3494c6770487823f284c303f9
With
forbid(unsafe_op_in_unsafe_fn), anunsafe fn's body in principle no longer has an implicitunsafeblock. So,unsafe_codeshould not trigger on anunsafe fnalone: there is not necessarily any unsafe code inside!This has practical effect. Consider one crate defining interfaces with unsafe methods (e.g. representing an OS API). Another crate wants to create mock implementations of these interfaces that are 100% safe. While any crate consuming these mocks will necessarily contain
unsafe {...}blocks, it is nice for the test support crate to declare it itself has only safe code.