Skip to content

Commit 2c5b3f4

Browse files
committed
new lint proper_safety_comment
1 parent 553a381 commit 2c5b3f4

14 files changed

+1134
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5914,6 +5914,7 @@ Released 2018-09-13
59145914
[`print_stdout`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout
59155915
[`print_with_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_with_newline
59165916
[`println_empty_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#println_empty_string
5917+
[`proper_safety_comment`]: https://rust-lang.github.io/rust-clippy/master/index.html#proper_safety_comment
59175918
[`ptr_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg
59185919
[`ptr_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr
59195920
[`ptr_cast_constness`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_cast_constness

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
660660
crate::returns::LET_AND_RETURN_INFO,
661661
crate::returns::NEEDLESS_RETURN_INFO,
662662
crate::returns::NEEDLESS_RETURN_WITH_QUESTION_MARK_INFO,
663+
crate::safety::PROPER_SAFETY_COMMENT_INFO,
663664
crate::same_name_method::SAME_NAME_METHOD_INFO,
664665
crate::self_named_constructors::SELF_NAMED_CONSTRUCTORS_INFO,
665666
crate::semicolon_block::SEMICOLON_INSIDE_BLOCK_INFO,

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ mod repeat_vec_with_capacity;
326326
mod reserve_after_initialization;
327327
mod return_self_not_must_use;
328328
mod returns;
329+
mod safety;
329330
mod same_name_method;
330331
mod self_named_constructors;
331332
mod semicolon_block;
@@ -967,4 +968,5 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
967968
store.register_late_pass(|_| Box::new(unnecessary_literal_bound::UnnecessaryLiteralBound));
968969
store.register_late_pass(move |_| Box::new(arbitrary_source_item_ordering::ArbitrarySourceItemOrdering::new(conf)));
969970
// add lints here, do not remove this comment, it's used in `new_lint`
971+
store.register_early_pass(|| Box::new(safety::Safety));
970972
}

clippy_lints/src/safety/mod.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
mod proper_safety_comment;
2+
3+
use rustc_lint::{EarlyContext, EarlyLintPass};
4+
use rustc_session::impl_lint_pass;
5+
6+
declare_clippy_lint! {
7+
/// ### What it does
8+
///
9+
/// It requires proper safety comments at the barrier of [Unsafety](https://doc.rust-lang.org/reference/unsafety.html).
10+
/// This includes any part of the [code that needs to satisfy extra safety conditions](https://doc.rust-lang.org/reference/unsafe-keyword.html):
11+
///
12+
/// - unsafe blocks (`unsafe {}`)
13+
/// - unsafe trait implementations (`unsafe impl`)
14+
/// - unsafe external blocks (`unsafe extern`)
15+
/// - unsafe attributes (`#[unsafe(attr)]`)
16+
///
17+
/// Safety comments are [non-doc line comments](https://doc.rust-lang.org/reference/comments.html) starting with `SAFETY:`:
18+
///
19+
/// ```no_run
20+
/// // SAFETY: A safety comment
21+
/// // that can cover
22+
/// // multiple lines.
23+
/// ```
24+
///
25+
/// Furthermore, it detects unnecessary safety comments for non-critical blocks, trait implementations and attributes. However, there can be false negatives.
26+
///
27+
/// [Code that defines extra safety conditions](https://doc.rust-lang.org/reference/unsafe-keyword.html) is covered by [`clippy::missing_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc) and [`clippy::unnecessary_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc)
28+
///
29+
/// ### Why restrict this?
30+
///
31+
/// Breaking the safety barrier should not be done carelessly.
32+
/// Proper documentation should be provided as to why each unsafe operation does not introduce [undefined behavior](https://doc.rust-lang.org/reference/behavior-considered-undefined.html).
33+
/// Thinking about these safety requirements and writing them down can prevent incorrect implementations.
34+
/// On the other hand, unnecessary safety comments are confusing and should not exist.
35+
///
36+
/// ### Example
37+
///
38+
/// ```no_run
39+
/// unsafe fn f1() {}
40+
/// fn f2() {
41+
/// unsafe { f1() }
42+
/// }
43+
///
44+
/// unsafe trait A {}
45+
/// unsafe impl A for ();
46+
///
47+
/// unsafe extern {
48+
/// pub fn g1();
49+
/// pub unsafe fn g2();
50+
/// pub safe fn g3();
51+
/// }
52+
///
53+
/// #[unsafe(no_mangle)]
54+
/// fn h();
55+
/// ```
56+
///
57+
/// Use instead:
58+
///
59+
/// ```no_run
60+
/// unsafe fn f1() {}
61+
/// fn f2() {
62+
/// unsafe {
63+
/// // SAFETY: ...
64+
/// f1()
65+
/// }
66+
/// }
67+
///
68+
/// unsafe trait A {}
69+
/// // SAFETY: ...
70+
/// unsafe impl A for ();
71+
///
72+
/// // SAFETY: ...
73+
/// unsafe extern {
74+
/// // SAFETY: ...
75+
/// pub fn g1();
76+
/// // SAFETY: ...
77+
/// pub unsafe fn g2();
78+
/// // SAFETY: ...
79+
/// pub safe fn g3();
80+
/// }
81+
///
82+
/// // SAFETY: ...
83+
/// #[unsafe(no_mangle)]
84+
/// fn h();
85+
/// ```
86+
#[clippy::version = "1.85.0"]
87+
pub PROPER_SAFETY_COMMENT,
88+
restriction,
89+
"requires proper safety comments at the barrier of unsafety"
90+
}
91+
92+
pub struct Safety;
93+
94+
impl_lint_pass!(Safety => [
95+
PROPER_SAFETY_COMMENT,
96+
]);
97+
98+
impl EarlyLintPass for Safety {
99+
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &rustc_ast::Attribute) {
100+
proper_safety_comment::check_attribute(cx, attr);
101+
}
102+
103+
fn check_block(&mut self, cx: &EarlyContext<'_>, block: &rustc_ast::Block) {
104+
proper_safety_comment::check_block(cx, block);
105+
}
106+
107+
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
108+
proper_safety_comment::check_item(cx, item);
109+
}
110+
}

0 commit comments

Comments
 (0)