diff options
author | Dawer <[email protected]> | 2021-04-22 16:17:27 +0100 |
---|---|---|
committer | Dawer <[email protected]> | 2021-05-31 20:03:45 +0100 |
commit | c3c2893f302d087ff3c1ddd3a1d4e88c03c4356b (patch) | |
tree | dc24743a4482f625b287c697f3ef17bfbfb9097f /crates/hir_ty/src/diagnostics/expr.rs | |
parent | 7c1d8ca63510bb719fd91bbf38692e45b19c04d6 (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.rs | 70 |
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) { |