1 use crate::utils
::{last_path_segment, snippet, span_lint_and_sugg}
;
2 use rustc_hir
::{GenericArg, Mutability, Ty, TyKind}
;
3 use rustc_lint
::{LateContext, LateLintPass}
;
4 use rustc_session
::{declare_lint_pass, declare_tool_lint}
;
5 use rustc_span
::symbol
::sym
;
7 use if_chain
::if_chain
;
8 use rustc_errors
::Applicability
;
10 declare_clippy_lint
! {
11 /// **What it does:** Checks for usage of `&Option<&T>`.
13 /// **Why is this bad?** Since `&` is Copy, it's useless to have a
14 /// reference on `Option<&T>`.
16 /// **Known problems:** It may be irrelevant to use this lint on
17 /// public API code as it will make a breaking change to apply it.
22 /// let x: &Option<&u32> = &Some(&0u32);
26 /// let x: Option<&u32> = Some(&0u32);
30 "use `Option<&T>` instead of `&Option<&T>`"
33 declare_lint_pass
!(RefOptionRef
=> [REF_OPTION_REF
]);
35 impl<'tcx
> LateLintPass
<'tcx
> for RefOptionRef
{
36 fn check_ty(&mut self, cx
: &LateContext
<'tcx
>, ty
: &'tcx Ty
<'tcx
>) {
38 if let TyKind
::Rptr(_
, ref mut_ty
) = ty
.kind
;
39 if mut_ty
.mutbl
== Mutability
::Not
;
40 if let TyKind
::Path(ref qpath
) = &mut_ty
.ty
.kind
;
41 let last
= last_path_segment(qpath
);
42 if let Some(res
) = last
.res
;
43 if let Some(def_id
) = res
.opt_def_id();
45 if cx
.tcx
.is_diagnostic_item(sym
::option_type
, def_id
);
46 if let Some(ref params
) = last_path_segment(qpath
).args
;
47 if !params
.parenthesized
;
48 if let Some(inner_ty
) = params
.args
.iter().find_map(|arg
| match arg
{
49 GenericArg
::Type(inner_ty
) => Some(inner_ty
),
52 if let TyKind
::Rptr(_
, _
) = inner_ty
.kind
;
59 "since `&` implements the `Copy` trait, `&Option<&T>` can be simplified to `Option<&T>`",
61 format
!("Option<{}>", &snippet(cx
, inner_ty
.span
, "..")),
62 Applicability
::MaybeIncorrect
,