Skip to content

Commit

Permalink
new lint proper_safety_comment
Browse files Browse the repository at this point in the history
  • Loading branch information
roberthree committed Dec 28, 2024
1 parent 553a381 commit 2c5b3f4
Show file tree
Hide file tree
Showing 14 changed files with 1,134 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5914,6 +5914,7 @@ Released 2018-09-13
[`print_stdout`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout
[`print_with_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_with_newline
[`println_empty_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#println_empty_string
[`proper_safety_comment`]: https://rust-lang.github.io/rust-clippy/master/index.html#proper_safety_comment
[`ptr_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg
[`ptr_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr
[`ptr_cast_constness`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_cast_constness
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::returns::LET_AND_RETURN_INFO,
crate::returns::NEEDLESS_RETURN_INFO,
crate::returns::NEEDLESS_RETURN_WITH_QUESTION_MARK_INFO,
crate::safety::PROPER_SAFETY_COMMENT_INFO,
crate::same_name_method::SAME_NAME_METHOD_INFO,
crate::self_named_constructors::SELF_NAMED_CONSTRUCTORS_INFO,
crate::semicolon_block::SEMICOLON_INSIDE_BLOCK_INFO,
Expand Down
2 changes: 2 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ mod repeat_vec_with_capacity;
mod reserve_after_initialization;
mod return_self_not_must_use;
mod returns;
mod safety;
mod same_name_method;
mod self_named_constructors;
mod semicolon_block;
Expand Down Expand Up @@ -967,4 +968,5 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(|_| Box::new(unnecessary_literal_bound::UnnecessaryLiteralBound));
store.register_late_pass(move |_| Box::new(arbitrary_source_item_ordering::ArbitrarySourceItemOrdering::new(conf)));
// add lints here, do not remove this comment, it's used in `new_lint`
store.register_early_pass(|| Box::new(safety::Safety));
}
110 changes: 110 additions & 0 deletions clippy_lints/src/safety/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
mod proper_safety_comment;

use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::impl_lint_pass;

declare_clippy_lint! {
/// ### What it does
///
/// It requires proper safety comments at the barrier of [Unsafety](https://doc.rust-lang.org/reference/unsafety.html).
/// This includes any part of the [code that needs to satisfy extra safety conditions](https://doc.rust-lang.org/reference/unsafe-keyword.html):
///
/// - unsafe blocks (`unsafe {}`)
/// - unsafe trait implementations (`unsafe impl`)
/// - unsafe external blocks (`unsafe extern`)
/// - unsafe attributes (`#[unsafe(attr)]`)
///
/// Safety comments are [non-doc line comments](https://doc.rust-lang.org/reference/comments.html) starting with `SAFETY:`:
///
/// ```no_run
/// // SAFETY: A safety comment
/// // that can cover
/// // multiple lines.
/// ```
///
/// Furthermore, it detects unnecessary safety comments for non-critical blocks, trait implementations and attributes. However, there can be false negatives.
///
/// [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)
///
/// ### Why restrict this?
///
/// Breaking the safety barrier should not be done carelessly.
/// 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).
/// Thinking about these safety requirements and writing them down can prevent incorrect implementations.
/// On the other hand, unnecessary safety comments are confusing and should not exist.
///
/// ### Example
///
/// ```no_run
/// unsafe fn f1() {}
/// fn f2() {
/// unsafe { f1() }
/// }
///
/// unsafe trait A {}
/// unsafe impl A for ();
///
/// unsafe extern {
/// pub fn g1();
/// pub unsafe fn g2();
/// pub safe fn g3();
/// }
///
/// #[unsafe(no_mangle)]
/// fn h();
/// ```
///
/// Use instead:
///
/// ```no_run
/// unsafe fn f1() {}
/// fn f2() {
/// unsafe {
/// // SAFETY: ...
/// f1()
/// }
/// }
///
/// unsafe trait A {}
/// // SAFETY: ...
/// unsafe impl A for ();
///
/// // SAFETY: ...
/// unsafe extern {
/// // SAFETY: ...
/// pub fn g1();
/// // SAFETY: ...
/// pub unsafe fn g2();
/// // SAFETY: ...
/// pub safe fn g3();
/// }
///
/// // SAFETY: ...
/// #[unsafe(no_mangle)]
/// fn h();
/// ```
#[clippy::version = "1.85.0"]
pub PROPER_SAFETY_COMMENT,
restriction,
"requires proper safety comments at the barrier of unsafety"
}

pub struct Safety;

impl_lint_pass!(Safety => [
PROPER_SAFETY_COMMENT,
]);

impl EarlyLintPass for Safety {
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &rustc_ast::Attribute) {
proper_safety_comment::check_attribute(cx, attr);
}

fn check_block(&mut self, cx: &EarlyContext<'_>, block: &rustc_ast::Block) {
proper_safety_comment::check_block(cx, block);
}

fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
proper_safety_comment::check_item(cx, item);
}
}
Loading

0 comments on commit 2c5b3f4

Please sign in to comment.