Skip to content

Commit 448fc14

Browse files
madsmtmehuss
authored andcommitted
Note that it is not a breaking change to make an unsafe function safe
1 parent 0e93732 commit 448fc14

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/doc/src/reference/semver.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ considered incompatible.
8888
* [Possibly-breaking: introducing a new function type parameter](#fn-generic-new)
8989
* [Minor: generalizing a function to use generics (supporting original type)](#fn-generalize-compatible)
9090
* [Major: generalizing a function to use generics with type mismatch](#fn-generalize-mismatch)
91+
* [Minor: making an `unsafe` function safe](#fn-unsafe-safe)
9192
* Attributes
9293
* [Major: switching from `no_std` support to requiring `std`](#attr-no-std-to-std)
9394
* [Major: adding `non_exhaustive` to an existing enum, variant, or struct with no private fields](#attr-adding-non-exhaustive)
@@ -1080,6 +1081,73 @@ fn main() {
10801081
}
10811082
```
10821083

1084+
<a id="fn-unsafe-safe"></a>
1085+
### Minor: making an `unsafe` function safe
1086+
1087+
It is not a breaking change to make a previously `unsafe` function safe, as in
1088+
the example below.
1089+
1090+
Going the other way (making a safe function `unsafe`) is a breaking change.
1091+
1092+
```rust,ignore
1093+
// MINOR CHANGE
1094+
1095+
///////////////////////////////////////////////////////////
1096+
// Before
1097+
pub unsafe fn foo() {}
1098+
1099+
///////////////////////////////////////////////////////////
1100+
// After
1101+
pub fn foo() {}
1102+
1103+
///////////////////////////////////////////////////////////
1104+
// Example use of the library that will safely work.
1105+
use updated_crate::foo;
1106+
1107+
unsafe fn bar(f: unsafe fn()) {
1108+
f()
1109+
}
1110+
1111+
fn main() {
1112+
unsafe { foo() }; // The `unused_unsafe` lint will trigger here
1113+
unsafe { bar(foo) };
1114+
}
1115+
```
1116+
1117+
Making an a previously `unsafe` associated function or method on structs /
1118+
enums safe is also a minor change, while the same is not true for associated
1119+
function on traits:
1120+
1121+
```rust,ignore
1122+
// MAJOR CHANGE
1123+
1124+
///////////////////////////////////////////////////////////
1125+
// Before
1126+
pub trait Foo {
1127+
unsafe fn foo();
1128+
}
1129+
1130+
///////////////////////////////////////////////////////////
1131+
// After
1132+
pub trait Foo {
1133+
fn foo();
1134+
}
1135+
1136+
///////////////////////////////////////////////////////////
1137+
// Example usage that will break.
1138+
use updated_crate::Foo;
1139+
1140+
struct Bar;
1141+
1142+
impl Foo for Bar {
1143+
unsafe fn foo() {} // Error: method `foo` has an incompatible type for trait
1144+
}
1145+
```
1146+
1147+
Note that local crates that have specified `#![deny(warnings)]` (which is an
1148+
[anti-pattern][deny warnings]) will break, since they've explicitly opted out
1149+
of Rust's stability guarantees.
1150+
10831151
<a id="attr-no-std-to-std"></a>
10841152
### Major: switching from `no_std` support to requiring `std`
10851153

@@ -1487,3 +1555,4 @@ document what your commitments are.
14871555
[SemVer]: https://semver.org/
14881556
[struct literal]: ../../reference/expressions/struct-expr.html
14891557
[wildcard patterns]: ../../reference/patterns.html#wildcard-pattern
1558+
[deny warnings]: https://rust-unofficial.github.io/patterns/anti_patterns/deny-warnings.html

0 commit comments

Comments
 (0)