Breaking change to remove `unsafe` from a function?

Let's say I have a library with the following function:

pub unsafe fn foo() {}

And later on, I discover that the function didn't actually need to be unsafe, so I change the function to:

pub fn foo() {}

Would that be considered a breaking change (and if so, how "big" of a breaking change would it be)?

My first guess would be that something like this would break, but it seems to still work:

unsafe fn foo() {}

fn bar(_f: unsafe fn()) {}

fn main() {
    bar(foo);
}

People will get a warning about unnecessary unsafe { foo() }, and that will break in local builds only if the crate has the footgun of #[deny(warnings)].

It won't break in dependencies, because of the cap lints mechanism.

4 Likes

Something useful to know is that you can assign a fn() to an unsafe fn() variable, so removing the unsafe modifier won't break code that passes foo around as a function pointer.

4 Likes

Wonderful, good to know that that's the only breakage (which I personally wouldn't consider breakage).

Would it make sense to note some of this in SemVer Compatibility - The Cargo Book?