aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/diagnostics/expr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/diagnostics/expr.rs')
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs77
1 files changed, 48 insertions, 29 deletions
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index 929c4a9cc..e4e9ab5c0 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -379,32 +379,58 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
379 let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) = 379 let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) =
380 db.body_with_source_map(self.owner); 380 db.body_with_source_map(self.owner);
381 381
382 let _match_expr_ty = if infer.type_of_expr[match_expr].is_unknown() { 382 let match_expr_ty = if infer.type_of_expr[match_expr].is_unknown() {
383 return; 383 return;
384 } else { 384 } else {
385 &infer.type_of_expr[match_expr] 385 &infer.type_of_expr[match_expr]
386 }; 386 };
387 // eprintln!("ExprValidator::validate_match2({:?})", _match_expr_ty.kind(&Interner));
388 387
389 let pattern_arena = RefCell::new(PatternArena::new()); 388 let pattern_arena = RefCell::new(PatternArena::new());
390 389
391 let mut have_errors = false; 390 let mut m_arms = Vec::new();
392 let m_arms: Vec<_> = arms 391 let mut has_lowering_errors = false;
393 .iter() 392 for arm in arms {
394 .map(|arm| usefulness::MatchArm { 393 if let Some(pat_ty) = infer.type_of_pat.get(arm.pat) {
395 pat: self.lower_pattern( 394 // We only include patterns whose type matches the type
396 arm.pat, 395 // of the match expression. If we had a InvalidMatchArmPattern
397 &mut pattern_arena.borrow_mut(), 396 // diagnostic or similar we could raise that in an else
398 db, 397 // block here.
399 &body, 398 //
400 &mut have_errors, 399 // When comparing the types, we also have to consider that rustc
401 ), 400 // will automatically de-reference the match expression type if
402 has_guard: arm.guard.is_some(), 401 // necessary.
403 }) 402 //
404 .collect(); 403 // FIXME we should use the type checker for this.
405 404 if pat_ty == match_expr_ty
406 // Bail out early if lowering failed. 405 || match_expr_ty
407 if have_errors { 406 .as_reference()
407 .map(|(match_expr_ty, ..)| match_expr_ty == pat_ty)
408 .unwrap_or(false)
409 {
410 // If we had a NotUsefulMatchArm diagnostic, we could
411 // check the usefulness of each pattern as we added it
412 // to the matrix here.
413 let m_arm = usefulness::MatchArm {
414 pat: self.lower_pattern(
415 arm.pat,
416 &mut pattern_arena.borrow_mut(),
417 db,
418 &body,
419 &mut has_lowering_errors,
420 ),
421 has_guard: arm.guard.is_some(),
422 };
423 m_arms.push(m_arm);
424 if !has_lowering_errors {
425 continue;
426 }
427 }
428 }
429
430 // If we can't resolve the type of a pattern, or the pattern type doesn't
431 // fit the match expression, we skip this diagnostic. Skipping the entire
432 // diagnostic rather than just not including this match arm is preferred
433 // to avoid the chance of false positives.
408 return; 434 return;
409 } 435 }
410 436
@@ -418,18 +444,11 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
418 }; 444 };
419 let report = usefulness::compute_match_usefulness(&cx, &m_arms); 445 let report = usefulness::compute_match_usefulness(&cx, &m_arms);
420 446
421 // TODO Report unreacheble arms 447 // FIXME Report unreacheble arms
422 // let mut catchall = None; 448 // https://github.com/rust-lang/rust/blob/25c15cdbe/compiler/rustc_mir_build/src/thir/pattern/check_match.rs#L200-L201
423 // for (arm_index, (arm, is_useful)) in report.arm_usefulness.iter().enumerate() {
424 // match is_useful{
425 // Unreachable => {
426 // }
427 // Reachable(_) => {}
428 // }
429 // }
430 449
431 let witnesses = report.non_exhaustiveness_witnesses; 450 let witnesses = report.non_exhaustiveness_witnesses;
432 eprintln!("compute_match_usefulness(..) -> {:?}", &witnesses); 451 // eprintln!("compute_match_usefulness(..) -> {:?}", &witnesses);
433 if !witnesses.is_empty() { 452 if !witnesses.is_empty() {
434 if let Ok(source_ptr) = source_map.expr_syntax(id) { 453 if let Ok(source_ptr) = source_map.expr_syntax(id) {
435 let root = source_ptr.file_syntax(db.upcast()); 454 let root = source_ptr.file_syntax(db.upcast());