diff options
| author | Nadrieril <nadrieril+git@gmail.com> | 2024-03-17 16:38:01 +0100 |
|---|---|---|
| committer | Nadrieril <nadrieril+git@gmail.com> | 2024-03-18 21:21:52 +0100 |
| commit | 040f37a99d430395b0d9ace6ea468f895f50fc16 (patch) | |
| tree | ac3f04aecf530153be352cf1f5874dd14cd5935d | |
| parent | e67adf40c98c95bb25a27a66c5b3f20a8094b296 (diff) | |
| download | rust-040f37a99d430395b0d9ace6ea468f895f50fc16.tar.gz rust-040f37a99d430395b0d9ace6ea468f895f50fc16.zip | |
Avoid hanging on complex matches
| -rw-r--r-- | crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs | 5 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/missing_match_arms.rs | 23 |
2 files changed, 26 insertions, 2 deletions
diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index dfe082cb560..f45beb4c92b 100644 --- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -67,7 +67,9 @@ impl<'p> MatchCheckCtx<'p> { ) -> Result<UsefulnessReport<'p, Self>, ()> { // FIXME: Determine place validity correctly. For now, err on the safe side. let place_validity = PlaceValidity::MaybeInvalid; - compute_match_usefulness(self, arms, scrut_ty, place_validity, None) + // Measured to take ~100ms on modern hardware. + let complexity_limit = Some(500000); + compute_match_usefulness(self, arms, scrut_ty, place_validity, complexity_limit) } fn is_uninhabited(&self, ty: &Ty) -> bool { @@ -476,7 +478,6 @@ impl<'p> PatCx for MatchCheckCtx<'p> { } fn complexity_exceeded(&self) -> Result<(), Self::Error> { - // FIXME(Nadrieril): make use of the complexity counter. Err(()) } } diff --git a/crates/ide-diagnostics/src/handlers/missing_match_arms.rs b/crates/ide-diagnostics/src/handlers/missing_match_arms.rs index 67daa172b27..c03bb3aeb53 100644 --- a/crates/ide-diagnostics/src/handlers/missing_match_arms.rs +++ b/crates/ide-diagnostics/src/handlers/missing_match_arms.rs @@ -1004,6 +1004,29 @@ fn f() { ); } + #[test] + fn exponential_match() { + // Constructs a match where match checking takes exponential time. Ensures we bail early. + use std::fmt::Write; + let struct_arity = 30; + let mut code = String::new(); + write!(code, "struct BigStruct {{").unwrap(); + for i in 0..struct_arity { + write!(code, " field{i}: bool,").unwrap(); + } + write!(code, "}}").unwrap(); + write!(code, "fn big_match(s: BigStruct) {{").unwrap(); + write!(code, " match s {{").unwrap(); + for i in 0..struct_arity { + write!(code, " BigStruct {{ field{i}: true, ..}} => {{}},").unwrap(); + write!(code, " BigStruct {{ field{i}: false, ..}} => {{}},").unwrap(); + } + write!(code, " _ => {{}},").unwrap(); + write!(code, " }}").unwrap(); + write!(code, "}}").unwrap(); + check_diagnostics_no_bails(&code); + } + mod rust_unstable { use super::*; |
