From 00b4f2819fa4786bb54bd2c4091767f64268d528 Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Sun, 19 Apr 2020 23:11:30 +0200 Subject: [PATCH 1/2] Implement unsafe_derive_deserialize lint --- CHANGELOG.md | 1 + clippy_lints/src/derive.rs | 158 ++++++++++++++++++++-- clippy_lints/src/lib.rs | 3 + clippy_lints/src/utils/diagnostics.rs | 2 +- clippy_lints/src/utils/mod.rs | 2 +- clippy_lints/src/utils/paths.rs | 1 + src/lintlist/mod.rs | 7 + tests/ui/unsafe_derive_deserialize.rs | 60 ++++++++ tests/ui/unsafe_derive_deserialize.stderr | 39 ++++++ 9 files changed, 263 insertions(+), 10 deletions(-) create mode 100644 tests/ui/unsafe_derive_deserialize.rs create mode 100644 tests/ui/unsafe_derive_deserialize.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index e513787a53a6..b97452873a80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1524,6 +1524,7 @@ Released 2018-09-13 [`unneeded_wildcard_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_wildcard_pattern [`unreachable`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreachable [`unreadable_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal +[`unsafe_derive_deserialize`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_derive_deserialize [`unsafe_removed_from_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_removed_from_name [`unsafe_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_vector_initialization [`unseparated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#unseparated_literal_suffix diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index f5a358d424f7..2f7d30674e1f 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,8 +1,13 @@ use crate::utils::paths; -use crate::utils::{is_automatically_derived, is_copy, match_path, span_lint_and_note, span_lint_and_then}; +use crate::utils::{ + is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, span_lint_and_then, +}; use if_chain::if_chain; -use rustc_hir::{Item, ItemKind, TraitRef}; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; +use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; @@ -62,11 +67,45 @@ declare_clippy_lint! { "implementing `Clone` explicitly on `Copy` types" } -declare_lint_pass!(Derive => [EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ]); +declare_clippy_lint! { + /// **What it does:** Checks for deriving `serde::Deserialize` on a type that + /// has methods using `unsafe`. + /// + /// **Why is this bad?** Deriving `serde::Deserialize` will create a constructor + /// that may violate invariants hold by another constructor. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust,ignore + /// use serde::Deserialize; + /// + /// #[derive(Deserialize)] + /// pub struct Foo { + /// // .. + /// } + /// + /// impl Foo { + /// pub fn new() -> Self { + /// // setup here .. + /// } + /// + /// pub unsafe fn parts() -> (&str, &str) { + /// // assumes invariants hold + /// } + /// } + /// ``` + pub UNSAFE_DERIVE_DESERIALIZE, + correctness, + "deriving `serde::Deserialize` on a type that has methods using `unsafe`" +} + +declare_lint_pass!(Derive => [EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ, UNSAFE_DERIVE_DESERIALIZE]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Derive { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { - if let ItemKind::Impl { + fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'_>) { + if let hir::ItemKind::Impl { of_trait: Some(ref trait_ref), .. } = item.kind @@ -76,7 +115,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Derive { check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); - if !is_automatically_derived { + if is_automatically_derived { + check_unsafe_derive_deserialize(cx, item, trait_ref, ty); + } else { check_copy_clone(cx, item, trait_ref, ty); } } @@ -87,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Derive { fn check_hash_peq<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, span: Span, - trait_ref: &TraitRef<'_>, + trait_ref: &hir::TraitRef<'_>, ty: Ty<'tcx>, hash_is_automatically_derived: bool, ) { @@ -134,7 +175,12 @@ fn check_hash_peq<'a, 'tcx>( } /// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. -fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) { +fn check_copy_clone<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + item: &hir::Item<'_>, + trait_ref: &hir::TraitRef<'_>, + ty: Ty<'tcx>, +) { if match_path(&trait_ref.path, &paths::CLONE_TRAIT) { if !is_copy(cx, ty) { return; @@ -173,3 +219,99 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item<'_>, trait ); } } + +/// Implementation of the `UNSAFE_DERIVE_DESERIALIZE` lint. +fn check_unsafe_derive_deserialize<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + item: &hir::Item<'_>, + trait_ref: &hir::TraitRef<'_>, + ty: Ty<'tcx>, +) { + fn item_from_def_id<'tcx>(cx: &LateContext<'_, 'tcx>, def_id: DefId) -> &'tcx hir::Item<'tcx> { + let hir_id = cx.tcx.hir().as_local_hir_id(def_id).unwrap(); + cx.tcx.hir().expect_item(hir_id) + } + + fn has_unsafe<'tcx>(cx: &LateContext<'_, 'tcx>, item: &'tcx hir::Item<'_>) -> bool { + let mut visitor = UnsafeVisitor { cx, has_unsafe: false }; + walk_item(&mut visitor, item); + visitor.has_unsafe + } + + if_chain! { + if match_path(&trait_ref.path, &paths::SERDE_DESERIALIZE); + if let ty::Adt(def, _) = ty.kind; + if def.did.is_local(); + if cx.tcx.inherent_impls(def.did) + .iter() + .map(|imp_did| item_from_def_id(cx, *imp_did)) + .any(|imp| has_unsafe(cx, imp)); + then { + span_lint_and_help( + cx, + UNSAFE_DERIVE_DESERIALIZE, + item.span, + "you are deriving `serde::Deserialize` on a type that has methods using `unsafe`", + None, + "consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html" + ); + } + } +} + +struct UnsafeVisitor<'a, 'tcx> { + cx: &'a LateContext<'a, 'tcx>, + has_unsafe: bool, +} + +impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { + type Map = Map<'tcx>; + + fn visit_fn( + &mut self, + kind: FnKind<'tcx>, + decl: &'tcx hir::FnDecl<'_>, + body_id: hir::BodyId, + span: Span, + id: hir::HirId, + ) { + if self.has_unsafe { + return; + } + + if_chain! { + if let Some(header) = kind.header(); + if let hir::Unsafety::Unsafe = header.unsafety; + then { + self.has_unsafe = true; + } + } + + walk_fn(self, kind, decl, body_id, span, id); + } + + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { + if self.has_unsafe { + return; + } + + if let hir::ExprKind::Block(block, _) = expr.kind { + use hir::{BlockCheckMode, UnsafeSource}; + + match block.rules { + BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) + | BlockCheckMode::PushUnsafeBlock(UnsafeSource::UserProvided) + | BlockCheckMode::PopUnsafeBlock(UnsafeSource::UserProvided) => { + self.has_unsafe = true; + }, + _ => {}, + } + } + + walk_expr(self, expr); + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.cx.tcx.hir()) + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 19c46476263b..d105afe5931e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -520,6 +520,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &dereference::EXPLICIT_DEREF_METHODS, &derive::DERIVE_HASH_XOR_EQ, &derive::EXPL_IMPL_CLONE_ON_COPY, + &derive::UNSAFE_DERIVE_DESERIALIZE, &doc::DOC_MARKDOWN, &doc::MISSING_ERRORS_DOC, &doc::MISSING_SAFETY_DOC, @@ -1196,6 +1197,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IF_SAME_THEN_ELSE), LintId::of(&derive::DERIVE_HASH_XOR_EQ), + LintId::of(&derive::UNSAFE_DERIVE_DESERIALIZE), LintId::of(&doc::MISSING_SAFETY_DOC), LintId::of(&doc::NEEDLESS_DOCTEST_MAIN), LintId::of(&double_comparison::DOUBLE_COMPARISONS), @@ -1608,6 +1610,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IF_SAME_THEN_ELSE), LintId::of(&derive::DERIVE_HASH_XOR_EQ), + LintId::of(&derive::UNSAFE_DERIVE_DESERIALIZE), LintId::of(&drop_bounds::DROP_BOUNDS), LintId::of(&drop_forget_ref::DROP_COPY), LintId::of(&drop_forget_ref::DROP_REF), diff --git a/clippy_lints/src/utils/diagnostics.rs b/clippy_lints/src/utils/diagnostics.rs index 093ef3191088..24a1bdf1883f 100644 --- a/clippy_lints/src/utils/diagnostics.rs +++ b/clippy_lints/src/utils/diagnostics.rs @@ -49,7 +49,7 @@ pub fn span_lint(cx: &T, lint: &'static Lint, sp: impl Into, segments: &[&str]) -> bool { /// /// # Examples /// ```rust,ignore -/// match_qpath(path, &["std", "rt", "begin_unwind"]) +/// match_path_ast(path, &["std", "rt", "begin_unwind"]) /// ``` pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { path.segments diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index d93f8a1e5609..f85845be56dc 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -108,6 +108,7 @@ pub const RESULT_ERR: [&str; 4] = ["core", "result", "Result", "Err"]; pub const RESULT_OK: [&str; 4] = ["core", "result", "Result", "Ok"]; pub const RWLOCK_READ_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockReadGuard"]; pub const RWLOCK_WRITE_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockWriteGuard"]; +pub const SERDE_DESERIALIZE: [&str; 2] = ["_serde", "Deserialize"]; pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"]; pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "", "into_vec"]; pub const SLICE_ITER: [&str; 3] = ["core", "slice", "Iter"]; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 213d054e403d..c7c851a8032d 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2334,6 +2334,13 @@ pub static ref ALL_LINTS: Vec = vec![ deprecation: None, module: "literal_representation", }, + Lint { + name: "unsafe_derive_deserialize", + group: "correctness", + desc: "deriving `serde::Deserialize` on a type that has methods using `unsafe`", + deprecation: None, + module: "derive", + }, Lint { name: "unsafe_removed_from_name", group: "style", diff --git a/tests/ui/unsafe_derive_deserialize.rs b/tests/ui/unsafe_derive_deserialize.rs new file mode 100644 index 000000000000..7bee9c499e1f --- /dev/null +++ b/tests/ui/unsafe_derive_deserialize.rs @@ -0,0 +1,60 @@ +#![warn(clippy::unsafe_derive_deserialize)] +#![allow(unused, clippy::missing_safety_doc)] + +extern crate serde; + +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct A {} +impl A { + pub unsafe fn new(_a: i32, _b: i32) -> Self { + Self {} + } +} + +#[derive(Deserialize)] +pub struct B {} +impl B { + pub unsafe fn unsafe_method(&self) {} +} + +#[derive(Deserialize)] +pub struct C {} +impl C { + pub fn unsafe_block(&self) { + unsafe {} + } +} + +#[derive(Deserialize)] +pub struct D {} +impl D { + pub fn inner_unsafe_fn(&self) { + unsafe fn inner() {} + } +} + +// Does not derive `Deserialize`, should be ignored +pub struct E {} +impl E { + pub unsafe fn new(_a: i32, _b: i32) -> Self { + Self {} + } + + pub unsafe fn unsafe_method(&self) {} + + pub fn unsafe_block(&self) { + unsafe {} + } + + pub fn inner_unsafe_fn(&self) { + unsafe fn inner() {} + } +} + +// Does not have methods using `unsafe`, should be ignored +#[derive(Deserialize)] +pub struct F {} + +fn main() {} diff --git a/tests/ui/unsafe_derive_deserialize.stderr b/tests/ui/unsafe_derive_deserialize.stderr new file mode 100644 index 000000000000..1978bd95a670 --- /dev/null +++ b/tests/ui/unsafe_derive_deserialize.stderr @@ -0,0 +1,39 @@ +error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` + --> $DIR/unsafe_derive_deserialize.rs:8:10 + | +LL | #[derive(Deserialize)] + | ^^^^^^^^^^^ + | + = note: `-D clippy::unsafe-derive-deserialize` implied by `-D warnings` + = help: consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` + --> $DIR/unsafe_derive_deserialize.rs:16:10 + | +LL | #[derive(Deserialize)] + | ^^^^^^^^^^^ + | + = help: consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` + --> $DIR/unsafe_derive_deserialize.rs:22:10 + | +LL | #[derive(Deserialize)] + | ^^^^^^^^^^^ + | + = help: consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` + --> $DIR/unsafe_derive_deserialize.rs:30:10 + | +LL | #[derive(Deserialize)] + | ^^^^^^^^^^^ + | + = help: consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + From b7f85e8706b1cafa02868c853ed5c05550ef2ffe Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Mon, 20 Apr 2020 20:05:15 +0200 Subject: [PATCH 2/2] Apply suggestions from PR review * Move the lint to pedantic * Import used types instead of prefixing with `hir::` --- clippy_lints/src/derive.rs | 44 ++++++++++++++------------------------ clippy_lints/src/lib.rs | 3 +-- src/lintlist/mod.rs | 2 +- 3 files changed, 18 insertions(+), 31 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 2f7d30674e1f..16300db0974b 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -3,9 +3,11 @@ use crate::utils::{ is_automatically_derived, is_copy, match_path, span_lint_and_help, span_lint_and_note, span_lint_and_then, }; use if_chain::if_chain; -use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, NestedVisitorMap, Visitor}; +use rustc_hir::{ + BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, TraitRef, UnsafeSource, Unsafety, +}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_middle::ty::{self, Ty}; @@ -97,15 +99,15 @@ declare_clippy_lint! { /// } /// ``` pub UNSAFE_DERIVE_DESERIALIZE, - correctness, + pedantic, "deriving `serde::Deserialize` on a type that has methods using `unsafe`" } declare_lint_pass!(Derive => [EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ, UNSAFE_DERIVE_DESERIALIZE]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Derive { - fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'_>) { - if let hir::ItemKind::Impl { + fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) { + if let ItemKind::Impl { of_trait: Some(ref trait_ref), .. } = item.kind @@ -128,7 +130,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Derive { fn check_hash_peq<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, span: Span, - trait_ref: &hir::TraitRef<'_>, + trait_ref: &TraitRef<'_>, ty: Ty<'tcx>, hash_is_automatically_derived: bool, ) { @@ -175,12 +177,7 @@ fn check_hash_peq<'a, 'tcx>( } /// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint. -fn check_copy_clone<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - item: &hir::Item<'_>, - trait_ref: &hir::TraitRef<'_>, - ty: Ty<'tcx>, -) { +fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) { if match_path(&trait_ref.path, &paths::CLONE_TRAIT) { if !is_copy(cx, ty) { return; @@ -223,16 +220,16 @@ fn check_copy_clone<'a, 'tcx>( /// Implementation of the `UNSAFE_DERIVE_DESERIALIZE` lint. fn check_unsafe_derive_deserialize<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, - item: &hir::Item<'_>, - trait_ref: &hir::TraitRef<'_>, + item: &Item<'_>, + trait_ref: &TraitRef<'_>, ty: Ty<'tcx>, ) { - fn item_from_def_id<'tcx>(cx: &LateContext<'_, 'tcx>, def_id: DefId) -> &'tcx hir::Item<'tcx> { + fn item_from_def_id<'tcx>(cx: &LateContext<'_, 'tcx>, def_id: DefId) -> &'tcx Item<'tcx> { let hir_id = cx.tcx.hir().as_local_hir_id(def_id).unwrap(); cx.tcx.hir().expect_item(hir_id) } - fn has_unsafe<'tcx>(cx: &LateContext<'_, 'tcx>, item: &'tcx hir::Item<'_>) -> bool { + fn has_unsafe<'tcx>(cx: &LateContext<'_, 'tcx>, item: &'tcx Item<'_>) -> bool { let mut visitor = UnsafeVisitor { cx, has_unsafe: false }; walk_item(&mut visitor, item); visitor.has_unsafe @@ -267,21 +264,14 @@ struct UnsafeVisitor<'a, 'tcx> { impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { type Map = Map<'tcx>; - fn visit_fn( - &mut self, - kind: FnKind<'tcx>, - decl: &'tcx hir::FnDecl<'_>, - body_id: hir::BodyId, - span: Span, - id: hir::HirId, - ) { + fn visit_fn(&mut self, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body_id: BodyId, span: Span, id: HirId) { if self.has_unsafe { return; } if_chain! { if let Some(header) = kind.header(); - if let hir::Unsafety::Unsafe = header.unsafety; + if let Unsafety::Unsafe = header.unsafety; then { self.has_unsafe = true; } @@ -290,14 +280,12 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { walk_fn(self, kind, decl, body_id, span, id); } - fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { if self.has_unsafe { return; } - if let hir::ExprKind::Block(block, _) = expr.kind { - use hir::{BlockCheckMode, UnsafeSource}; - + if let ExprKind::Block(block, _) = expr.kind { match block.rules { BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) | BlockCheckMode::PushUnsafeBlock(UnsafeSource::UserProvided) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d105afe5931e..c04e0884b196 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1106,6 +1106,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&default_trait_access::DEFAULT_TRAIT_ACCESS), LintId::of(&dereference::EXPLICIT_DEREF_METHODS), LintId::of(&derive::EXPL_IMPL_CLONE_ON_COPY), + LintId::of(&derive::UNSAFE_DERIVE_DESERIALIZE), LintId::of(&doc::DOC_MARKDOWN), LintId::of(&doc::MISSING_ERRORS_DOC), LintId::of(&empty_enum::EMPTY_ENUM), @@ -1197,7 +1198,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IF_SAME_THEN_ELSE), LintId::of(&derive::DERIVE_HASH_XOR_EQ), - LintId::of(&derive::UNSAFE_DERIVE_DESERIALIZE), LintId::of(&doc::MISSING_SAFETY_DOC), LintId::of(&doc::NEEDLESS_DOCTEST_MAIN), LintId::of(&double_comparison::DOUBLE_COMPARISONS), @@ -1610,7 +1610,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IF_SAME_THEN_ELSE), LintId::of(&derive::DERIVE_HASH_XOR_EQ), - LintId::of(&derive::UNSAFE_DERIVE_DESERIALIZE), LintId::of(&drop_bounds::DROP_BOUNDS), LintId::of(&drop_forget_ref::DROP_COPY), LintId::of(&drop_forget_ref::DROP_REF), diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index c7c851a8032d..9b3f0d7182bf 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -2336,7 +2336,7 @@ pub static ref ALL_LINTS: Vec = vec![ }, Lint { name: "unsafe_derive_deserialize", - group: "correctness", + group: "pedantic", desc: "deriving `serde::Deserialize` on a type that has methods using `unsafe`", deprecation: None, module: "derive",