From 63d317c71a088bc20c6eee7d9ee71a7db44afde0 Mon Sep 17 00:00:00 2001 From: Dawer <7803845+iDawer@users.noreply.github.com> Date: Thu, 20 May 2021 17:58:18 +0500 Subject: Compute missing arms lazily. --- crates/ide_assists/src/handlers/fill_match_arms.rs | 47 +++++++++++----------- 1 file 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 @@ -use std::iter; +use std::iter::{self, Peekable}; use either::Either; use hir::{Adt, HasSource, ModuleDef, Semantics}; @@ -63,33 +63,33 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option< let module = ctx.sema.scope(expr.syntax()).module()?; - let missing_arms: Vec = if let Some(enum_def) = resolve_enum_def(&ctx.sema, &expr) { + let mut missing_pats: Peekable>> = if let Some(enum_def) = + resolve_enum_def(&ctx.sema, &expr) + { let variants = enum_def.variants(ctx.db()); - let mut variants = variants + let missing_pats = variants .into_iter() .filter_map(|variant| build_pat(ctx.db(), module, variant)) - .filter(|variant_pat| is_variant_missing(&top_lvl_pats, variant_pat)) - .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) - .map(|it| it.clone_for_update()) - .collect::>(); - if Some(enum_def) - == FamousDefs(&ctx.sema, Some(module.krate())) - .core_option_Option() - .map(|x| lift_enum(x)) + .filter(|variant_pat| is_variant_missing(&top_lvl_pats, variant_pat)); + + let missing_pats: Box> = if Some(enum_def) + == FamousDefs(&ctx.sema, Some(module.krate())).core_option_Option().map(lift_enum) { // Match `Some` variant first. cov_mark::hit!(option_order); - variants.reverse() - } - variants + Box::new(missing_pats.rev()) + } else { + Box::new(missing_pats) + }; + missing_pats.peekable() } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr) { // When calculating the match arms for a tuple of enums, we want // to create a match arm for each possible combination of enum // values. The `multi_cartesian_product` method transforms // Vec> into Vec<(EnumVariant, .., EnumVariant)> // where each tuple represents a proposed match arm. - enum_defs + let missing_pats = enum_defs .into_iter() .map(|enum_def| enum_def.variants(ctx.db())) .multi_cartesian_product() @@ -98,15 +98,13 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option< variants.into_iter().filter_map(|variant| build_pat(ctx.db(), module, variant)); ast::Pat::from(make::tuple_pat(patterns)) }) - .filter(|variant_pat| is_variant_missing(&top_lvl_pats, variant_pat)) - .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) - .map(|it| it.clone_for_update()) - .collect() + .filter(|variant_pat| is_variant_missing(&top_lvl_pats, variant_pat)); + (Box::new(missing_pats) as Box>).peekable() } else { return None; }; - if missing_arms.is_empty() { + if missing_pats.peek().is_none() { return None; } @@ -117,6 +115,9 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option< target, |builder| { let new_match_arm_list = match_arm_list.clone_for_update(); + let missing_arms = missing_pats + .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) + .map(|it| it.clone_for_update()); let catch_all_arm = new_match_arm_list .arms() @@ -167,13 +168,13 @@ fn does_pat_match_variant(pat: &Pat, var: &Pat) -> bool { } } -#[derive(Eq, PartialEq, Clone)] +#[derive(Eq, PartialEq, Clone, Copy)] enum ExtendedEnum { Bool, Enum(hir::Enum), } -#[derive(Eq, PartialEq, Clone)] +#[derive(Eq, PartialEq, Clone, Copy)] enum ExtendedVariant { True, False, @@ -185,7 +186,7 @@ fn lift_enum(e: hir::Enum) -> ExtendedEnum { } impl ExtendedEnum { - fn variants(&self, db: &RootDatabase) -> Vec { + fn variants(self, db: &RootDatabase) -> Vec { match self { ExtendedEnum::Enum(e) => { e.variants(db).into_iter().map(|x| ExtendedVariant::Variant(x)).collect::>() -- cgit v1.2.3