aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/diagnostics/expr.rs
diff options
context:
space:
mode:
authorDawer <[email protected]>2021-04-22 16:17:27 +0100
committerDawer <[email protected]>2021-05-31 20:03:45 +0100
commitc3c2893f302d087ff3c1ddd3a1d4e88c03c4356b (patch)
treedc24743a4482f625b287c697f3ef17bfbfb9097f /crates/hir_ty/src/diagnostics/expr.rs
parent7c1d8ca63510bb719fd91bbf38692e45b19c04d6 (diff)
Update match checking.
fn is_useful , more skeletons Specify a lifetime on pattern references impl PatStack fill impl Matrix PatStack::pop_head_constructor Index-based approach struct PatCtxt fields construction fn Fields::wildcards split wildcard fn Constructor::is_covered_by_any(..) fn Matrix::specialize_constructor(..) impl Usefulness Initial work on witness construction Reorganize files Replace match checking diagnostic Handle types of expanded patterns unit match checking go brrr
Diffstat (limited to 'crates/hir_ty/src/diagnostics/expr.rs')
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs70
1 files changed, 69 insertions, 1 deletions
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index 86f82e3fa..ea70a5f9f 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -62,7 +62,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
62 62
63 match expr { 63 match expr {
64 Expr::Match { expr, arms } => { 64 Expr::Match { expr, arms } => {
65 self.validate_match(id, *expr, arms, db, self.infer.clone()); 65 self.validate_match2(id, *expr, arms, db, self.infer.clone());
66 } 66 }
67 Expr::Call { .. } | Expr::MethodCall { .. } => { 67 Expr::Call { .. } | Expr::MethodCall { .. } => {
68 self.validate_call(db, id, expr); 68 self.validate_call(db, id, expr);
@@ -277,6 +277,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
277 } 277 }
278 } 278 }
279 279
280 #[allow(dead_code)]
280 fn validate_match( 281 fn validate_match(
281 &mut self, 282 &mut self,
282 id: ExprId, 283 id: ExprId,
@@ -358,6 +359,73 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
358 } 359 }
359 } 360 }
360 361
362 fn validate_match2(
363 &mut self,
364 id: ExprId,
365 match_expr: ExprId,
366 arms: &[MatchArm],
367 db: &dyn HirDatabase,
368 infer: Arc<InferenceResult>,
369 ) {
370 use crate::diagnostics::pattern::usefulness;
371 use hir_def::HasModule;
372
373 let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) =
374 db.body_with_source_map(self.owner);
375
376 let match_expr_ty = if infer.type_of_expr[match_expr].is_unknown() {
377 return;
378 } else {
379 &infer.type_of_expr[match_expr]
380 };
381 eprintln!("ExprValidator::validate_match2({:?})", match_expr_ty.kind(&Interner));
382
383 let pattern_arena = usefulness::PatternArena::clone_from(&body.pats);
384 let cx = usefulness::MatchCheckCtx {
385 krate: self.owner.module(db.upcast()).krate(),
386 match_expr,
387 body,
388 infer: &infer,
389 db,
390 pattern_arena: &pattern_arena,
391 };
392
393 let m_arms: Vec<_> = arms
394 .iter()
395 .map(|arm| usefulness::MatchArm { pat: arm.pat, has_guard: arm.guard.is_some() })
396 .collect();
397
398 let report = usefulness::compute_match_usefulness(&cx, &m_arms);
399
400 // TODO Report unreacheble arms
401 // let mut catchall = None;
402 // for (arm_index, (arm, is_useful)) in report.arm_usefulness.iter().enumerate() {
403 // match is_useful{
404 // Unreachable => {
405 // }
406 // Reachable(_) => {}
407 // }
408 // }
409
410 let witnesses = report.non_exhaustiveness_witnesses;
411 if !witnesses.is_empty() {
412 if let Ok(source_ptr) = source_map.expr_syntax(id) {
413 let root = source_ptr.file_syntax(db.upcast());
414 if let ast::Expr::MatchExpr(match_expr) = &source_ptr.value.to_node(&root) {
415 if let (Some(match_expr), Some(arms)) =
416 (match_expr.expr(), match_expr.match_arm_list())
417 {
418 self.sink.push(MissingMatchArms {
419 file: source_ptr.file_id,
420 match_expr: AstPtr::new(&match_expr),
421 arms: AstPtr::new(&arms),
422 })
423 }
424 }
425 }
426 }
427 }
428
361 fn validate_results_in_tail_expr(&mut self, body_id: ExprId, id: ExprId, db: &dyn HirDatabase) { 429 fn validate_results_in_tail_expr(&mut self, body_id: ExprId, id: ExprId, db: &dyn HirDatabase) {
362 // the mismatch will be on the whole block currently 430 // the mismatch will be on the whole block currently
363 let mismatch = match self.infer.type_mismatch_for_expr(body_id) { 431 let mismatch = match self.infer.type_mismatch_for_expr(body_id) {