From 570eff655208b5f7d28d2e0a587ee514b91b4a42 Mon Sep 17 00:00:00 2001 From: Dawer <7803845+iDawer@users.noreply.github.com> Date: Thu, 20 May 2021 23:50:27 +0500 Subject: fix: `fill_match_arms` hangs on a tuple of large enums --- crates/ide_assists/src/handlers/fill_match_arms.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/crates/ide_assists/src/handlers/fill_match_arms.rs b/crates/ide_assists/src/handlers/fill_match_arms.rs index 12ea17d7a..3532759bf 100644 --- a/crates/ide_assists/src/handlers/fill_match_arms.rs +++ b/crates/ide_assists/src/handlers/fill_match_arms.rs @@ -84,14 +84,26 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option< }; missing_pats.peekable() } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr) { + let mut n_arms = 1; + let variants_of_enums: Vec> = enum_defs + .into_iter() + .map(|enum_def| enum_def.variants(ctx.db())) + .inspect(|variants| n_arms *= variants.len()) + .collect(); + // 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. - let missing_pats = enum_defs + + // A number of arms grows very fast on even a small tuple of large enums. + // We skip the assist beyond an arbitrary threshold. + if n_arms > 256 { + return None; + } + let missing_pats = variants_of_enums .into_iter() - .map(|enum_def| enum_def.variants(ctx.db())) .multi_cartesian_product() .map(|variants| { let patterns = -- cgit v1.2.3