1+ use clippy_config:: Conf ;
12use clippy_utils:: diagnostics:: span_lint_hir_and_then;
3+ use clippy_utils:: msrvs:: Msrv ;
24use clippy_utils:: ty:: get_type_diagnostic_name;
35use clippy_utils:: usage:: is_potentially_local_place;
4- use clippy_utils:: { higher, path_to_local, sym} ;
6+ use clippy_utils:: { can_use_if_let_chains , higher, path_to_local, sym} ;
57use rustc_errors:: Applicability ;
68use rustc_hir:: intravisit:: { FnKind , Visitor , walk_expr, walk_fn} ;
79use rustc_hir:: { BinOpKind , Body , Expr , ExprKind , FnDecl , HirId , Node , UnOp } ;
@@ -10,7 +12,7 @@ use rustc_lint::{LateContext, LateLintPass};
1012use rustc_middle:: hir:: nested_filter;
1113use rustc_middle:: mir:: FakeReadCause ;
1214use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
13- use rustc_session:: declare_lint_pass ;
15+ use rustc_session:: impl_lint_pass ;
1416use rustc_span:: def_id:: LocalDefId ;
1517use rustc_span:: { Span , Symbol } ;
1618
@@ -72,10 +74,21 @@ declare_clippy_lint! {
7274 "checks for calls of `unwrap[_err]()` that will always fail"
7375}
7476
77+ pub ( crate ) struct Unwrap {
78+ msrv : Msrv ,
79+ }
80+
81+ impl Unwrap {
82+ pub fn new ( conf : & ' static Conf ) -> Self {
83+ Self { msrv : conf. msrv }
84+ }
85+ }
86+
7587/// Visitor that keeps track of which variables are unwrappable.
76- struct UnwrappableVariablesVisitor < ' a , ' tcx > {
88+ struct UnwrappableVariablesVisitor < ' a , ' tcx , ' unwrap > {
7789 unwrappables : Vec < UnwrapInfo < ' tcx > > ,
7890 cx : & ' a LateContext < ' tcx > ,
91+ unwrap : & ' unwrap Unwrap ,
7992}
8093
8194/// What kind of unwrappable this is.
@@ -231,7 +244,7 @@ impl<'tcx> Delegate<'tcx> for MutationVisitor<'tcx> {
231244 fn fake_read ( & mut self , _: & PlaceWithHirId < ' tcx > , _: FakeReadCause , _: HirId ) { }
232245}
233246
234- impl < ' tcx > UnwrappableVariablesVisitor < ' _ , ' tcx > {
247+ impl < ' tcx > UnwrappableVariablesVisitor < ' _ , ' tcx , ' _ > {
235248 fn visit_branch (
236249 & mut self ,
237250 if_expr : & ' tcx Expr < ' _ > ,
@@ -282,7 +295,7 @@ fn consume_option_as_ref<'tcx>(expr: &'tcx Expr<'tcx>) -> (&'tcx Expr<'tcx>, Opt
282295 }
283296}
284297
285- impl < ' tcx > Visitor < ' tcx > for UnwrappableVariablesVisitor < ' _ , ' tcx > {
298+ impl < ' tcx > Visitor < ' tcx > for UnwrappableVariablesVisitor < ' _ , ' tcx , ' _ > {
286299 type NestedFilter = nested_filter:: OnlyBodies ;
287300
288301 fn visit_expr ( & mut self , expr : & ' tcx Expr < ' _ > ) {
@@ -353,7 +366,11 @@ impl<'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'_, 'tcx> {
353366 ) ;
354367 } else {
355368 diag. span_label ( unwrappable. check . span , "the check is happening here" ) ;
356- diag. help ( "try using `if let` or `match`" ) ;
369+ if can_use_if_let_chains ( self . cx , self . unwrap . msrv ) {
370+ diag. help ( "try using `if let` or `match`" ) ;
371+ } else {
372+ diag. help ( "try using `match`" ) ;
373+ }
357374 }
358375 } ,
359376 ) ;
@@ -379,7 +396,7 @@ impl<'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'_, 'tcx> {
379396 }
380397}
381398
382- declare_lint_pass ! ( Unwrap => [ PANICKING_UNWRAP , UNNECESSARY_UNWRAP ] ) ;
399+ impl_lint_pass ! ( Unwrap => [ PANICKING_UNWRAP , UNNECESSARY_UNWRAP ] ) ;
383400
384401impl < ' tcx > LateLintPass < ' tcx > for Unwrap {
385402 fn check_fn (
@@ -398,6 +415,7 @@ impl<'tcx> LateLintPass<'tcx> for Unwrap {
398415 let mut v = UnwrappableVariablesVisitor {
399416 unwrappables : Vec :: new ( ) ,
400417 cx,
418+ unwrap : self ,
401419 } ;
402420
403421 walk_fn ( & mut v, kind, decl, body. id ( ) , fn_id) ;
0 commit comments