Skip to content

Commit 213dbf7

Browse files
committed
clippy_lint: Add 'ref_option_ref'
1 parent afbac89 commit 213dbf7

File tree

6 files changed

+93
-0
lines changed

6 files changed

+93
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,6 +1917,7 @@ Released 2018-09-13
19171917
[`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate
19181918
[`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes
19191919
[`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref
1920+
[`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref
19201921
[`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro
19211922
[`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once
19221923
[`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts

clippy_lints/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ mod redundant_closure_call;
293293
mod redundant_field_names;
294294
mod redundant_pub_crate;
295295
mod redundant_static_lifetimes;
296+
mod ref_option_ref;
296297
mod reference;
297298
mod regex;
298299
mod repeat_once;
@@ -803,6 +804,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
803804
&redundant_field_names::REDUNDANT_FIELD_NAMES,
804805
&redundant_pub_crate::REDUNDANT_PUB_CRATE,
805806
&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES,
807+
&ref_option_ref::REF_OPTION_REF,
806808
&reference::DEREF_ADDROF,
807809
&reference::REF_IN_DEREF,
808810
&regex::INVALID_REGEX,
@@ -1024,6 +1026,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10241026
&sess.target,
10251027
);
10261028
store.register_late_pass(move || box pass_by_ref_or_value);
1029+
store.register_late_pass(|| box ref_option_ref::RefOptionRef);
10271030
store.register_late_pass(|| box try_err::TryErr);
10281031
store.register_late_pass(|| box use_self::UseSelf);
10291032
store.register_late_pass(|| box bytecount::ByteCount);
@@ -1493,6 +1496,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
14931496
LintId::of(&redundant_closure_call::REDUNDANT_CLOSURE_CALL),
14941497
LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES),
14951498
LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
1499+
LintId::of(&ref_option_ref::REF_OPTION_REF),
14961500
LintId::of(&reference::DEREF_ADDROF),
14971501
LintId::of(&reference::REF_IN_DEREF),
14981502
LintId::of(&regex::INVALID_REGEX),
@@ -1648,6 +1652,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
16481652
LintId::of(&ranges::MANUAL_RANGE_CONTAINS),
16491653
LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES),
16501654
LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
1655+
LintId::of(&ref_option_ref::REF_OPTION_REF),
16511656
LintId::of(&regex::TRIVIAL_REGEX),
16521657
LintId::of(&returns::LET_AND_RETURN),
16531658
LintId::of(&returns::NEEDLESS_RETURN),

clippy_lints/src/ref_option_ref.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use crate::utils::{last_path_segment, match_def_path, paths, snippet, span_lint_and_sugg};
2+
use rustc_hir::{GenericArg, Local, Mutability, TyKind};
3+
use rustc_lint::{LateContext, LateLintPass};
4+
use rustc_session::{declare_lint_pass, declare_tool_lint};
5+
6+
use if_chain::if_chain;
7+
use rustc_errors::Applicability;
8+
9+
declare_clippy_lint! {
10+
/// **What it does:** Checks for usage of `&Option<&T>`.
11+
///
12+
/// **Why is this bad?** Since `&` is Copy, it's useless to have a
13+
/// reference on `Option<&T>`.
14+
///
15+
/// **Known problems:** None.
16+
///
17+
/// **Example:**
18+
///
19+
/// ```rust,ignore
20+
/// // example code where clippy issues a warning
21+
/// let x: &Option<&u32> = &Some(&0u32);
22+
/// ```
23+
/// Use instead:
24+
/// ```rust,ignore
25+
/// // example code which does not raise clippy warning
26+
/// let x: Option<&u32> = Some(&0u32);
27+
/// ```
28+
pub REF_OPTION_REF,
29+
style,
30+
"use `Option<&T>` instead of `&Option<&T>`"
31+
}
32+
33+
declare_lint_pass!(RefOptionRef => [REF_OPTION_REF]);
34+
35+
impl<'tcx> LateLintPass<'tcx> for RefOptionRef {
36+
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
37+
if_chain! {
38+
if let Some(ref ty) = local.ty;
39+
if let TyKind::Rptr(_, ref mut_ty) = ty.kind;
40+
if mut_ty.mutbl == Mutability::Not;
41+
if let TyKind::Path(ref qpath) = &mut_ty.ty.kind ;
42+
if let Some(def_id) = cx.typeck_results().qpath_res(qpath, local.hir_id).opt_def_id();
43+
if match_def_path(cx, def_id, &paths::OPTION);
44+
if let Some(ref params) = last_path_segment(qpath).args ;
45+
if !params.parenthesized;
46+
if let Some(inner_ty) = params.args.iter().find_map(|arg| match arg {
47+
GenericArg::Type(inner_ty) => Some(inner_ty),
48+
_ => None,
49+
});
50+
if let TyKind::Rptr(_, _) = inner_ty.kind;
51+
52+
then {
53+
span_lint_and_sugg(
54+
cx,
55+
REF_OPTION_REF,
56+
ty.span,
57+
"since & implements Copy trait, &Option<&T> can be simplifyied into Option<&T>",
58+
"try",
59+
format!("Option<{}>", &snippet(cx, inner_ty.span, "..")),
60+
Applicability::MachineApplicable,
61+
);
62+
}
63+
}
64+
}
65+
}

src/lintlist/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,13 @@ vec![
20132013
deprecation: None,
20142014
module: "reference",
20152015
},
2016+
Lint {
2017+
name: "ref_option_ref",
2018+
group: "style",
2019+
desc: "use `Option<&T>` instead of `&Option<&T>`",
2020+
deprecation: None,
2021+
module: "ref_option_ref",
2022+
},
20162023
Lint {
20172024
name: "repeat_once",
20182025
group: "complexity",

tests/ui/ref_option_ref.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#![warn(clippy::ref_option_ref)]
2+
3+
fn main() {
4+
let x: &Option<&u32> = &None;
5+
}

tests/ui/ref_option_ref.stderr

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: since & implements Copy trait, &Option<&T> can be simplifyied into Option<&T>
2+
--> $DIR/ref_option_ref.rs:4:12
3+
|
4+
LL | let x: &Option<&u32> = &None;
5+
| ^^^^^^^^^^^^^ help: try: `Option<&u32>`
6+
|
7+
= note: `-D clippy::ref-option-ref` implied by `-D warnings`
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)