]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/replace_if_let_with_match.rs
Revert "Apply make_else_arm to general case"
[rust.git] / crates / ide_assists / src / handlers / replace_if_let_with_match.rs
1 use std::iter::{self, successors};
2
3 use either::Either;
4 use ide_db::{defs::NameClass, ty_filter::TryEnum, RootDatabase};
5 use syntax::{
6     ast::{
7         self,
8         edit::{AstNodeEdit, IndentLevel},
9         make, HasName,
10     },
11     AstNode, TextRange,
12 };
13
14 use crate::{
15     utils::{does_pat_match_variant, unwrap_trivial_block},
16     AssistContext, AssistId, AssistKind, Assists,
17 };
18
19 // Assist: replace_if_let_with_match
20 //
21 // Replaces a `if let` expression with a `match` expression.
22 //
23 // ```
24 // enum Action { Move { distance: u32 }, Stop }
25 //
26 // fn handle(action: Action) {
27 //     $0if let Action::Move { distance } = action {
28 //         foo(distance)
29 //     } else {
30 //         bar()
31 //     }
32 // }
33 // ```
34 // ->
35 // ```
36 // enum Action { Move { distance: u32 }, Stop }
37 //
38 // fn handle(action: Action) {
39 //     match action {
40 //         Action::Move { distance } => foo(distance),
41 //         _ => bar(),
42 //     }
43 // }
44 // ```
45 pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
46     let if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
47     let available_range = TextRange::new(
48         if_expr.syntax().text_range().start(),
49         if_expr.then_branch()?.syntax().text_range().start(),
50     );
51     let cursor_in_range = available_range.contains_range(ctx.frange.range);
52     if !cursor_in_range {
53         return None;
54     }
55     let mut else_block = None;
56     let if_exprs = successors(Some(if_expr.clone()), |expr| match expr.else_branch()? {
57         ast::ElseBranch::IfExpr(expr) => Some(expr),
58         ast::ElseBranch::Block(block) => {
59             else_block = Some(block);
60             None
61         }
62     });
63     let scrutinee_to_be_expr = if_expr.condition()?.expr()?;
64
65     let mut pat_seen = false;
66     let mut cond_bodies = Vec::new();
67     for if_expr in if_exprs {
68         let cond = if_expr.condition()?;
69         let expr = cond.expr()?;
70         let cond = match cond.pat() {
71             Some(pat) => {
72                 if scrutinee_to_be_expr.syntax().text() != expr.syntax().text() {
73                     // Only if all condition expressions are equal we can merge them into a match
74                     return None;
75                 }
76                 pat_seen = true;
77                 Either::Left(pat)
78             }
79             None => Either::Right(expr),
80         };
81         let body = if_expr.then_branch()?;
82         cond_bodies.push((cond, body));
83     }
84
85     if !pat_seen {
86         // Don't offer turning an if (chain) without patterns into a match
87         return None;
88     }
89
90     acc.add(
91         AssistId("replace_if_let_with_match", AssistKind::RefactorRewrite),
92         "Replace if let with match",
93         available_range,
94         move |edit| {
95             let match_expr = {
96                 let else_arm = make_else_arm(ctx, else_block, &cond_bodies);
97                 let make_match_arm = |(pat, body): (_, ast::BlockExpr)| {
98                     let body = body.reset_indent().indent(IndentLevel(1));
99                     match pat {
100                         Either::Left(pat) => {
101                             make::match_arm(iter::once(pat), None, unwrap_trivial_block(body))
102                         }
103                         Either::Right(expr) => make::match_arm(
104                             iter::once(make::wildcard_pat().into()),
105                             Some(expr),
106                             unwrap_trivial_block(body),
107                         ),
108                     }
109                 };
110                 let arms = cond_bodies.into_iter().map(make_match_arm).chain(iter::once(else_arm));
111                 let match_expr = make::expr_match(scrutinee_to_be_expr, make::match_arm_list(arms));
112                 match_expr.indent(IndentLevel::from_node(if_expr.syntax()))
113             };
114
115             let has_preceding_if_expr =
116                 if_expr.syntax().parent().map_or(false, |it| ast::IfExpr::can_cast(it.kind()));
117             let expr = if has_preceding_if_expr {
118                 // make sure we replace the `else if let ...` with a block so we don't end up with `else expr`
119                 make::block_expr(None, Some(match_expr)).into()
120             } else {
121                 match_expr
122             };
123             edit.replace_ast::<ast::Expr>(if_expr.into(), expr);
124         },
125     )
126 }
127
128 fn make_else_arm(
129     ctx: &AssistContext,
130     else_block: Option<ast::BlockExpr>,
131     conditionals: &[(Either<ast::Pat, ast::Expr>, ast::BlockExpr)],
132 ) -> ast::MatchArm {
133     if let Some(else_block) = else_block {
134         let pattern = if let [(Either::Left(pat), _)] = conditionals {
135             ctx.sema
136                 .type_of_pat(pat)
137                 .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty.adjusted()))
138                 .zip(Some(pat))
139         } else {
140             None
141         };
142         let pattern = match pattern {
143             Some((it, pat)) => {
144                 if does_pat_match_variant(pat, &it.sad_pattern()) {
145                     it.happy_pattern_wildcard()
146                 } else {
147                     it.sad_pattern()
148                 }
149             }
150             None => make::wildcard_pat().into(),
151         };
152         make::match_arm(iter::once(pattern), None, unwrap_trivial_block(else_block))
153     } else {
154         make::match_arm(iter::once(make::wildcard_pat().into()), None, make::expr_unit())
155     }
156 }
157
158 // Assist: replace_match_with_if_let
159 //
160 // Replaces a binary `match` with a wildcard pattern and no guards with an `if let` expression.
161 //
162 // ```
163 // enum Action { Move { distance: u32 }, Stop }
164 //
165 // fn handle(action: Action) {
166 //     $0match action {
167 //         Action::Move { distance } => foo(distance),
168 //         _ => bar(),
169 //     }
170 // }
171 // ```
172 // ->
173 // ```
174 // enum Action { Move { distance: u32 }, Stop }
175 //
176 // fn handle(action: Action) {
177 //     if let Action::Move { distance } = action {
178 //         foo(distance)
179 //     } else {
180 //         bar()
181 //     }
182 // }
183 // ```
184 pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
185     let match_expr: ast::MatchExpr = ctx.find_node_at_offset()?;
186
187     let mut arms = match_expr.match_arm_list()?.arms();
188     let (first_arm, second_arm) = (arms.next()?, arms.next()?);
189     if arms.next().is_some() || first_arm.guard().is_some() || second_arm.guard().is_some() {
190         return None;
191     }
192
193     let (if_let_pat, then_expr, else_expr) = pick_pattern_and_expr_order(
194         &ctx.sema,
195         first_arm.pat()?,
196         second_arm.pat()?,
197         first_arm.expr()?,
198         second_arm.expr()?,
199     )?;
200     let scrutinee = match_expr.expr()?;
201
202     let target = match_expr.syntax().text_range();
203     acc.add(
204         AssistId("replace_match_with_if_let", AssistKind::RefactorRewrite),
205         "Replace match with if let",
206         target,
207         move |edit| {
208             let condition = make::condition(scrutinee, Some(if_let_pat));
209             let then_block = match then_expr.reset_indent() {
210                 ast::Expr::BlockExpr(block) => block,
211                 expr => make::block_expr(iter::empty(), Some(expr)),
212             };
213             let else_expr = if is_empty_expr(&else_expr) { None } else { Some(else_expr) };
214             let if_let_expr = make::expr_if(
215                 condition,
216                 then_block,
217                 else_expr
218                     .map(|expr| match expr {
219                         ast::Expr::BlockExpr(block) => block,
220                         expr => (make::block_expr(iter::empty(), Some(expr))),
221                     })
222                     .map(ast::ElseBranch::Block),
223             )
224             .indent(IndentLevel::from_node(match_expr.syntax()));
225
226             edit.replace_ast::<ast::Expr>(match_expr.into(), if_let_expr);
227         },
228     )
229 }
230
231 /// Pick the pattern for the if let condition and return the expressions for the `then` body and `else` body in that order.
232 fn pick_pattern_and_expr_order(
233     sema: &hir::Semantics<RootDatabase>,
234     pat: ast::Pat,
235     pat2: ast::Pat,
236     expr: ast::Expr,
237     expr2: ast::Expr,
238 ) -> Option<(ast::Pat, ast::Expr, ast::Expr)> {
239     let res = match (pat, pat2) {
240         (ast::Pat::WildcardPat(_), _) => return None,
241         (pat, _) if is_empty_expr(&expr2) => (pat, expr, expr2),
242         (_, pat) if is_empty_expr(&expr) => (pat, expr2, expr),
243         (pat, pat2) => match (binds_name(sema, &pat), binds_name(sema, &pat2)) {
244             (true, true) => return None,
245             (true, false) => (pat, expr, expr2),
246             (false, true) => (pat2, expr2, expr),
247             _ if is_sad_pat(sema, &pat) => (pat2, expr2, expr),
248             (false, false) => (pat, expr, expr2),
249         },
250     };
251     Some(res)
252 }
253
254 fn is_empty_expr(expr: &ast::Expr) -> bool {
255     match expr {
256         ast::Expr::BlockExpr(expr) => match expr.stmt_list() {
257             Some(it) => it.statements().next().is_none() && it.tail_expr().is_none(),
258             None => true,
259         },
260         ast::Expr::TupleExpr(expr) => expr.fields().next().is_none(),
261         _ => false,
262     }
263 }
264
265 fn binds_name(sema: &hir::Semantics<RootDatabase>, pat: &ast::Pat) -> bool {
266     let binds_name_v = |pat| binds_name(sema, &pat);
267     match pat {
268         ast::Pat::IdentPat(pat) => !matches!(
269             pat.name().and_then(|name| NameClass::classify(sema, &name)),
270             Some(NameClass::ConstReference(_))
271         ),
272         ast::Pat::MacroPat(_) => true,
273         ast::Pat::OrPat(pat) => pat.pats().any(binds_name_v),
274         ast::Pat::SlicePat(pat) => pat.pats().any(binds_name_v),
275         ast::Pat::TuplePat(it) => it.fields().any(binds_name_v),
276         ast::Pat::TupleStructPat(it) => it.fields().any(binds_name_v),
277         ast::Pat::RecordPat(it) => it
278             .record_pat_field_list()
279             .map_or(false, |rpfl| rpfl.fields().flat_map(|rpf| rpf.pat()).any(binds_name_v)),
280         ast::Pat::RefPat(pat) => pat.pat().map_or(false, binds_name_v),
281         ast::Pat::BoxPat(pat) => pat.pat().map_or(false, binds_name_v),
282         ast::Pat::ParenPat(pat) => pat.pat().map_or(false, binds_name_v),
283         _ => false,
284     }
285 }
286
287 fn is_sad_pat(sema: &hir::Semantics<RootDatabase>, pat: &ast::Pat) -> bool {
288     sema.type_of_pat(pat)
289         .and_then(|ty| TryEnum::from_ty(sema, &ty.adjusted()))
290         .map_or(false, |it| does_pat_match_variant(pat, &it.sad_pattern()))
291 }
292
293 #[cfg(test)]
294 mod tests {
295     use super::*;
296
297     use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
298
299     #[test]
300     fn test_if_let_with_match_unapplicable_for_simple_ifs() {
301         check_assist_not_applicable(
302             replace_if_let_with_match,
303             r#"
304 fn main() {
305     if $0true {} else if false {} else {}
306 }
307 "#,
308         )
309     }
310
311     #[test]
312     fn test_if_let_with_match_no_else() {
313         check_assist(
314             replace_if_let_with_match,
315             r#"
316 impl VariantData {
317     pub fn foo(&self) {
318         if $0let VariantData::Struct(..) = *self {
319             self.foo();
320         }
321     }
322 }
323 "#,
324             r#"
325 impl VariantData {
326     pub fn foo(&self) {
327         match *self {
328             VariantData::Struct(..) => {
329                 self.foo();
330             }
331             _ => (),
332         }
333     }
334 }
335 "#,
336         )
337     }
338
339     #[test]
340     fn test_if_let_with_match_available_range_left() {
341         check_assist_not_applicable(
342             replace_if_let_with_match,
343             r#"
344 impl VariantData {
345     pub fn foo(&self) {
346         $0 if let VariantData::Struct(..) = *self {
347             self.foo();
348         }
349     }
350 }
351 "#,
352         )
353     }
354
355     #[test]
356     fn test_if_let_with_match_available_range_right() {
357         check_assist_not_applicable(
358             replace_if_let_with_match,
359             r#"
360 impl VariantData {
361     pub fn foo(&self) {
362         if let VariantData::Struct(..) = *self {$0
363             self.foo();
364         }
365     }
366 }
367 "#,
368         )
369     }
370
371     #[test]
372     fn test_if_let_with_match_basic() {
373         check_assist(
374             replace_if_let_with_match,
375             r#"
376 impl VariantData {
377     pub fn is_struct(&self) -> bool {
378         if $0let VariantData::Struct(..) = *self {
379             true
380         } else if let VariantData::Tuple(..) = *self {
381             false
382         } else if cond() {
383             true
384         } else {
385             bar(
386                 123
387             )
388         }
389     }
390 }
391 "#,
392             r#"
393 impl VariantData {
394     pub fn is_struct(&self) -> bool {
395         match *self {
396             VariantData::Struct(..) => true,
397             VariantData::Tuple(..) => false,
398             _ if cond() => true,
399             _ => {
400                     bar(
401                         123
402                     )
403                 }
404         }
405     }
406 }
407 "#,
408         )
409     }
410
411     #[test]
412     fn test_if_let_with_match_on_tail_if_let() {
413         check_assist(
414             replace_if_let_with_match,
415             r#"
416 impl VariantData {
417     pub fn is_struct(&self) -> bool {
418         if let VariantData::Struct(..) = *self {
419             true
420         } else if let$0 VariantData::Tuple(..) = *self {
421             false
422         } else {
423             false
424         }
425     }
426 }
427 "#,
428             r#"
429 impl VariantData {
430     pub fn is_struct(&self) -> bool {
431         if let VariantData::Struct(..) = *self {
432             true
433         } else {
434     match *self {
435             VariantData::Tuple(..) => false,
436             _ => false,
437         }
438 }
439     }
440 }
441 "#,
442         )
443     }
444
445     #[test]
446     fn special_case_option() {
447         check_assist(
448             replace_if_let_with_match,
449             r#"
450 //- minicore: option
451 fn foo(x: Option<i32>) {
452     $0if let Some(x) = x {
453         println!("{}", x)
454     } else {
455         println!("none")
456     }
457 }
458 "#,
459             r#"
460 fn foo(x: Option<i32>) {
461     match x {
462         Some(x) => println!("{}", x),
463         None => println!("none"),
464     }
465 }
466 "#,
467         );
468     }
469
470     #[test]
471     fn special_case_inverted_option() {
472         check_assist(
473             replace_if_let_with_match,
474             r#"
475 //- minicore: option
476 fn foo(x: Option<i32>) {
477     $0if let None = x {
478         println!("none")
479     } else {
480         println!("some")
481     }
482 }
483 "#,
484             r#"
485 fn foo(x: Option<i32>) {
486     match x {
487         None => println!("none"),
488         Some(_) => println!("some"),
489     }
490 }
491 "#,
492         );
493     }
494
495     #[test]
496     fn special_case_result() {
497         check_assist(
498             replace_if_let_with_match,
499             r#"
500 //- minicore: result
501 fn foo(x: Result<i32, ()>) {
502     $0if let Ok(x) = x {
503         println!("{}", x)
504     } else {
505         println!("none")
506     }
507 }
508 "#,
509             r#"
510 fn foo(x: Result<i32, ()>) {
511     match x {
512         Ok(x) => println!("{}", x),
513         Err(_) => println!("none"),
514     }
515 }
516 "#,
517         );
518     }
519
520     #[test]
521     fn special_case_inverted_result() {
522         check_assist(
523             replace_if_let_with_match,
524             r#"
525 //- minicore: result
526 fn foo(x: Result<i32, ()>) {
527     $0if let Err(x) = x {
528         println!("{}", x)
529     } else {
530         println!("ok")
531     }
532 }
533 "#,
534             r#"
535 fn foo(x: Result<i32, ()>) {
536     match x {
537         Err(x) => println!("{}", x),
538         Ok(_) => println!("ok"),
539     }
540 }
541 "#,
542         );
543     }
544
545     #[test]
546     fn nested_indent() {
547         check_assist(
548             replace_if_let_with_match,
549             r#"
550 fn main() {
551     if true {
552         $0if let Ok(rel_path) = path.strip_prefix(root_path) {
553             let rel_path = RelativePathBuf::from_path(rel_path).ok()?;
554             Some((*id, rel_path))
555         } else {
556             None
557         }
558     }
559 }
560 "#,
561             r#"
562 fn main() {
563     if true {
564         match path.strip_prefix(root_path) {
565             Ok(rel_path) => {
566                 let rel_path = RelativePathBuf::from_path(rel_path).ok()?;
567                 Some((*id, rel_path))
568             }
569             _ => None,
570         }
571     }
572 }
573 "#,
574         )
575     }
576
577     #[test]
578     fn test_replace_match_with_if_let_unwraps_simple_expressions() {
579         check_assist(
580             replace_match_with_if_let,
581             r#"
582 impl VariantData {
583     pub fn is_struct(&self) -> bool {
584         $0match *self {
585             VariantData::Struct(..) => true,
586             _ => false,
587         }
588     }
589 }           "#,
590             r#"
591 impl VariantData {
592     pub fn is_struct(&self) -> bool {
593         if let VariantData::Struct(..) = *self {
594             true
595         } else {
596             false
597         }
598     }
599 }           "#,
600         )
601     }
602
603     #[test]
604     fn test_replace_match_with_if_let_doesnt_unwrap_multiline_expressions() {
605         check_assist(
606             replace_match_with_if_let,
607             r#"
608 fn foo() {
609     $0match a {
610         VariantData::Struct(..) => {
611             bar(
612                 123
613             )
614         }
615         _ => false,
616     }
617 }           "#,
618             r#"
619 fn foo() {
620     if let VariantData::Struct(..) = a {
621         bar(
622             123
623         )
624     } else {
625         false
626     }
627 }           "#,
628         )
629     }
630
631     #[test]
632     fn replace_match_with_if_let_target() {
633         check_assist_target(
634             replace_match_with_if_let,
635             r#"
636 impl VariantData {
637     pub fn is_struct(&self) -> bool {
638         $0match *self {
639             VariantData::Struct(..) => true,
640             _ => false,
641         }
642     }
643 }           "#,
644             r#"match *self {
645             VariantData::Struct(..) => true,
646             _ => false,
647         }"#,
648         );
649     }
650
651     #[test]
652     fn special_case_option_match_to_if_let() {
653         check_assist(
654             replace_match_with_if_let,
655             r#"
656 //- minicore: option
657 fn foo(x: Option<i32>) {
658     $0match x {
659         Some(x) => println!("{}", x),
660         None => println!("none"),
661     }
662 }
663 "#,
664             r#"
665 fn foo(x: Option<i32>) {
666     if let Some(x) = x {
667         println!("{}", x)
668     } else {
669         println!("none")
670     }
671 }
672 "#,
673         );
674     }
675
676     #[test]
677     fn special_case_result_match_to_if_let() {
678         check_assist(
679             replace_match_with_if_let,
680             r#"
681 //- minicore: result
682 fn foo(x: Result<i32, ()>) {
683     $0match x {
684         Ok(x) => println!("{}", x),
685         Err(_) => println!("none"),
686     }
687 }
688 "#,
689             r#"
690 fn foo(x: Result<i32, ()>) {
691     if let Ok(x) = x {
692         println!("{}", x)
693     } else {
694         println!("none")
695     }
696 }
697 "#,
698         );
699     }
700
701     #[test]
702     fn nested_indent_match_to_if_let() {
703         check_assist(
704             replace_match_with_if_let,
705             r#"
706 fn main() {
707     if true {
708         $0match path.strip_prefix(root_path) {
709             Ok(rel_path) => {
710                 let rel_path = RelativePathBuf::from_path(rel_path).ok()?;
711                 Some((*id, rel_path))
712             }
713             _ => None,
714         }
715     }
716 }
717 "#,
718             r#"
719 fn main() {
720     if true {
721         if let Ok(rel_path) = path.strip_prefix(root_path) {
722             let rel_path = RelativePathBuf::from_path(rel_path).ok()?;
723             Some((*id, rel_path))
724         } else {
725             None
726         }
727     }
728 }
729 "#,
730         )
731     }
732
733     #[test]
734     fn replace_match_with_if_let_empty_wildcard_expr() {
735         check_assist(
736             replace_match_with_if_let,
737             r#"
738 fn main() {
739     $0match path.strip_prefix(root_path) {
740         Ok(rel_path) => println!("{}", rel_path),
741         _ => (),
742     }
743 }
744 "#,
745             r#"
746 fn main() {
747     if let Ok(rel_path) = path.strip_prefix(root_path) {
748         println!("{}", rel_path)
749     }
750 }
751 "#,
752         )
753     }
754
755     #[test]
756     fn replace_match_with_if_let_number_body() {
757         check_assist(
758             replace_match_with_if_let,
759             r#"
760 fn main() {
761     $0match Ok(()) {
762         Ok(()) => {},
763         Err(_) => 0,
764     }
765 }
766 "#,
767             r#"
768 fn main() {
769     if let Err(_) = Ok(()) {
770         0
771     }
772 }
773 "#,
774         )
775     }
776
777     #[test]
778     fn replace_match_with_if_let_exhaustive() {
779         check_assist(
780             replace_match_with_if_let,
781             r#"
782 fn print_source(def_source: ModuleSource) {
783     match def_so$0urce {
784         ModuleSource::SourceFile(..) => { println!("source file"); }
785         ModuleSource::Module(..) => { println!("module"); }
786     }
787 }
788 "#,
789             r#"
790 fn print_source(def_source: ModuleSource) {
791     if let ModuleSource::SourceFile(..) = def_source { println!("source file"); } else { println!("module"); }
792 }
793 "#,
794         )
795     }
796
797     #[test]
798     fn replace_match_with_if_let_prefer_name_bind() {
799         check_assist(
800             replace_match_with_if_let,
801             r#"
802 fn foo() {
803     match $0Foo(0) {
804         Foo(_) => (),
805         Bar(bar) => println!("bar {}", bar),
806     }
807 }
808 "#,
809             r#"
810 fn foo() {
811     if let Bar(bar) = Foo(0) {
812         println!("bar {}", bar)
813     }
814 }
815 "#,
816         );
817         check_assist(
818             replace_match_with_if_let,
819             r#"
820 fn foo() {
821     match $0Foo(0) {
822         Bar(bar) => println!("bar {}", bar),
823         Foo(_) => (),
824     }
825 }
826 "#,
827             r#"
828 fn foo() {
829     if let Bar(bar) = Foo(0) {
830         println!("bar {}", bar)
831     }
832 }
833 "#,
834         );
835     }
836
837     #[test]
838     fn replace_match_with_if_let_prefer_nonempty_body() {
839         check_assist(
840             replace_match_with_if_let,
841             r#"
842 fn foo() {
843     match $0Ok(0) {
844         Ok(value) => {},
845         Err(err) => eprintln!("{}", err),
846     }
847 }
848 "#,
849             r#"
850 fn foo() {
851     if let Err(err) = Ok(0) {
852         eprintln!("{}", err)
853     }
854 }
855 "#,
856         );
857         check_assist(
858             replace_match_with_if_let,
859             r#"
860 fn foo() {
861     match $0Ok(0) {
862         Err(err) => eprintln!("{}", err),
863         Ok(value) => {},
864     }
865 }
866 "#,
867             r#"
868 fn foo() {
869     if let Err(err) = Ok(0) {
870         eprintln!("{}", err)
871     }
872 }
873 "#,
874         );
875     }
876
877     #[test]
878     fn replace_match_with_if_let_rejects_double_name_bindings() {
879         check_assist_not_applicable(
880             replace_match_with_if_let,
881             r#"
882 fn foo() {
883     match $0Foo(0) {
884         Foo(foo) => println!("bar {}", foo),
885         Bar(bar) => println!("bar {}", bar),
886     }
887 }
888 "#,
889         );
890     }
891
892     #[test]
893     fn nested_type() {
894         check_assist(
895             replace_if_let_with_match,
896             r#"
897 //- minicore: result
898 fn foo(x: Result<i32, ()>) {
899     let bar: Result<_, ()> = Ok(Some(1));
900     $0if let Ok(Some(_)) = bar {
901         ()
902     } else {
903         ()
904     }
905 }
906 "#,
907             r#"
908 fn foo(x: Result<i32, ()>) {
909     let bar: Result<_, ()> = Ok(Some(1));
910     match bar {
911         Ok(Some(_)) => (),
912         _ => (),
913     }
914 "#,
915         );
916     }
917 }