aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ide_assists/src/handlers/fill_match_arms.rs47
1 files changed, 24 insertions, 23 deletions
diff --git a/crates/ide_assists/src/handlers/fill_match_arms.rs b/crates/ide_assists/src/handlers/fill_match_arms.rs
index 58b001050..12ea17d7a 100644
--- a/crates/ide_assists/src/handlers/fill_match_arms.rs
+++ b/crates/ide_assists/src/handlers/fill_match_arms.rs
@@ -1,4 +1,4 @@
1use std::iter; 1use std::iter::{self, Peekable};
2 2
3use either::Either; 3use either::Either;
4use hir::{Adt, HasSource, ModuleDef, Semantics}; 4use hir::{Adt, HasSource, ModuleDef, Semantics};
@@ -63,33 +63,33 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
63 63
64 let module = ctx.sema.scope(expr.syntax()).module()?; 64 let module = ctx.sema.scope(expr.syntax()).module()?;
65 65
66 let missing_arms: Vec<MatchArm> = if let Some(enum_def) = resolve_enum_def(&ctx.sema, &expr) { 66 let mut missing_pats: Peekable<Box<dyn Iterator<Item = ast::Pat>>> = if let Some(enum_def) =
67 resolve_enum_def(&ctx.sema, &expr)
68 {
67 let variants = enum_def.variants(ctx.db()); 69 let variants = enum_def.variants(ctx.db());
68 70
69 let mut variants = variants 71 let missing_pats = variants
70 .into_iter() 72 .into_iter()
71 .filter_map(|variant| build_pat(ctx.db(), module, variant)) 73 .filter_map(|variant| build_pat(ctx.db(), module, variant))
72 .filter(|variant_pat| is_variant_missing(&top_lvl_pats, variant_pat)) 74 .filter(|variant_pat| is_variant_missing(&top_lvl_pats, variant_pat));
73 .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) 75
74 .map(|it| it.clone_for_update()) 76 let missing_pats: Box<dyn Iterator<Item = _>> = if Some(enum_def)
75 .collect::<Vec<_>>(); 77 == FamousDefs(&ctx.sema, Some(module.krate())).core_option_Option().map(lift_enum)
76 if Some(enum_def)
77 == FamousDefs(&ctx.sema, Some(module.krate()))
78 .core_option_Option()
79 .map(|x| lift_enum(x))
80 { 78 {
81 // Match `Some` variant first. 79 // Match `Some` variant first.
82 cov_mark::hit!(option_order); 80 cov_mark::hit!(option_order);
83 variants.reverse() 81 Box::new(missing_pats.rev())
84 } 82 } else {
85 variants 83 Box::new(missing_pats)
84 };
85 missing_pats.peekable()
86 } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr) { 86 } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr) {
87 // When calculating the match arms for a tuple of enums, we want 87 // When calculating the match arms for a tuple of enums, we want
88 // to create a match arm for each possible combination of enum 88 // to create a match arm for each possible combination of enum
89 // values. The `multi_cartesian_product` method transforms 89 // values. The `multi_cartesian_product` method transforms
90 // Vec<Vec<EnumVariant>> into Vec<(EnumVariant, .., EnumVariant)> 90 // Vec<Vec<EnumVariant>> into Vec<(EnumVariant, .., EnumVariant)>
91 // where each tuple represents a proposed match arm. 91 // where each tuple represents a proposed match arm.
92 enum_defs 92 let missing_pats = enum_defs
93 .into_iter() 93 .into_iter()
94 .map(|enum_def| enum_def.variants(ctx.db())) 94 .map(|enum_def| enum_def.variants(ctx.db()))
95 .multi_cartesian_product() 95 .multi_cartesian_product()
@@ -98,15 +98,13 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
98 variants.into_iter().filter_map(|variant| build_pat(ctx.db(), module, variant)); 98 variants.into_iter().filter_map(|variant| build_pat(ctx.db(), module, variant));
99 ast::Pat::from(make::tuple_pat(patterns)) 99 ast::Pat::from(make::tuple_pat(patterns))
100 }) 100 })
101 .filter(|variant_pat| is_variant_missing(&top_lvl_pats, variant_pat)) 101 .filter(|variant_pat| is_variant_missing(&top_lvl_pats, variant_pat));
102 .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) 102 (Box::new(missing_pats) as Box<dyn Iterator<Item = _>>).peekable()
103 .map(|it| it.clone_for_update())
104 .collect()
105 } else { 103 } else {
106 return None; 104 return None;
107 }; 105 };
108 106
109 if missing_arms.is_empty() { 107 if missing_pats.peek().is_none() {
110 return None; 108 return None;
111 } 109 }
112 110
@@ -117,6 +115,9 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
117 target, 115 target,
118 |builder| { 116 |builder| {
119 let new_match_arm_list = match_arm_list.clone_for_update(); 117 let new_match_arm_list = match_arm_list.clone_for_update();
118 let missing_arms = missing_pats
119 .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block()))
120 .map(|it| it.clone_for_update());
120 121
121 let catch_all_arm = new_match_arm_list 122 let catch_all_arm = new_match_arm_list
122 .arms() 123 .arms()
@@ -167,13 +168,13 @@ fn does_pat_match_variant(pat: &Pat, var: &Pat) -> bool {
167 } 168 }
168} 169}
169 170
170#[derive(Eq, PartialEq, Clone)] 171#[derive(Eq, PartialEq, Clone, Copy)]
171enum ExtendedEnum { 172enum ExtendedEnum {
172 Bool, 173 Bool,
173 Enum(hir::Enum), 174 Enum(hir::Enum),
174} 175}
175 176
176#[derive(Eq, PartialEq, Clone)] 177#[derive(Eq, PartialEq, Clone, Copy)]
177enum ExtendedVariant { 178enum ExtendedVariant {
178 True, 179 True,
179 False, 180 False,
@@ -185,7 +186,7 @@ fn lift_enum(e: hir::Enum) -> ExtendedEnum {
185} 186}
186 187
187impl ExtendedEnum { 188impl ExtendedEnum {
188 fn variants(&self, db: &RootDatabase) -> Vec<ExtendedVariant> { 189 fn variants(self, db: &RootDatabase) -> Vec<ExtendedVariant> {
189 match self { 190 match self {
190 ExtendedEnum::Enum(e) => { 191 ExtendedEnum::Enum(e) => {
191 e.variants(db).into_iter().map(|x| ExtendedVariant::Variant(x)).collect::<Vec<_>>() 192 e.variants(db).into_iter().map(|x| ExtendedVariant::Variant(x)).collect::<Vec<_>>()