From 99516bbd67a0018c3c0bf94cb895896857d4263c Mon Sep 17 00:00:00 2001 From: Dawer <7803845+iDawer@users.noreply.github.com> Date: Tue, 1 Jun 2021 17:21:00 +0500 Subject: minor: Avoid eprintln on panic --- crates/hir_ty/src/diagnostics/expr.rs | 23 ++++++++++++---------- .../src/diagnostics/match_check/usefulness.rs | 5 ++--- 2 files changed, 15 insertions(+), 13 deletions(-) (limited to 'crates') diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index 3efbce773..a2a4d61db 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs @@ -357,17 +357,20 @@ impl<'a, 'b> ExprValidator<'a, 'b> { infer: &infer, db, pattern_arena: &pattern_arena, - eprint_panic_context: &|| { + panic_context: &|| { use syntax::AstNode; - if let Ok(scrutinee_sptr) = source_map.expr_syntax(match_expr) { - let root = scrutinee_sptr.file_syntax(db.upcast()); - if let Some(match_ast) = scrutinee_sptr.value.to_node(&root).syntax().parent() { - eprintln!( - "Match checking is about to panic on this expression:\n{}", - match_ast.to_string(), - ); - } - } + let match_expr_text = source_map + .expr_syntax(match_expr) + .ok() + .and_then(|scrutinee_sptr| { + let root = scrutinee_sptr.file_syntax(db.upcast()); + scrutinee_sptr.value.to_node(&root).syntax().parent() + }) + .map(|node| node.to_string()); + format!( + "expression:\n{}", + match_expr_text.as_deref().unwrap_or("") + ) }, }; let report = compute_match_usefulness(&cx, &m_arms); diff --git a/crates/hir_ty/src/diagnostics/match_check/usefulness.rs b/crates/hir_ty/src/diagnostics/match_check/usefulness.rs index 83b094a89..bd76a606c 100644 --- a/crates/hir_ty/src/diagnostics/match_check/usefulness.rs +++ b/crates/hir_ty/src/diagnostics/match_check/usefulness.rs @@ -295,7 +295,7 @@ pub(crate) struct MatchCheckCtx<'a> { pub(crate) db: &'a dyn HirDatabase, /// Lowered patterns from arms plus generated by the check. pub(crate) pattern_arena: &'a RefCell, - pub(crate) eprint_panic_context: &'a dyn Fn(), + pub(crate) panic_context: &'a dyn Fn() -> String, } impl<'a> MatchCheckCtx<'a> { @@ -331,8 +331,7 @@ impl<'a> MatchCheckCtx<'a> { #[track_caller] pub(super) fn bug(&self, info: &str) -> ! { - (self.eprint_panic_context)(); - panic!("bug: {}", info); + panic!("bug: {}\n{}", info, (self.panic_context)()); } } -- cgit v1.2.3 From 0a8c30a96fe09047da07a8e2980baa47a334a3d7 Mon Sep 17 00:00:00 2001 From: Dawer <7803845+iDawer@users.noreply.github.com> Date: Wed, 2 Jun 2021 01:29:07 +0500 Subject: internal: implement pattern adjustments. --- crates/hir_ty/src/diagnostics/match_check.rs | 28 ++++++++++++++++++++++++++-- crates/hir_ty/src/infer.rs | 2 ++ crates/hir_ty/src/infer/pat.rs | 7 +++++++ 3 files changed, 35 insertions(+), 2 deletions(-) (limited to 'crates') diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index a9a99f57a..c8e1b23de 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs @@ -100,10 +100,19 @@ impl<'a> PatCtxt<'a> { } pub(crate) fn lower_pattern(&mut self, pat: hir_def::expr::PatId) -> Pat { - // FIXME: implement pattern adjustments (implicit pattern dereference; "RFC 2005-match-ergonomics") + // XXX(iDawer): Collecting pattern adjustments feels imprecise to me. + // When lowering of & and box patterns are implemented this should be tested + // in a manner of `match_ergonomics_issue_9095` test. + // Pattern adjustment is part of RFC 2005-match-ergonomics. // More info https://github.com/rust-lang/rust/issues/42640#issuecomment-313535089 let unadjusted_pat = self.lower_pattern_unadjusted(pat); - unadjusted_pat + self.infer.pat_adjustments.get(&pat).map(|it| &**it).unwrap_or_default().iter().rev().fold( + unadjusted_pat, + |subpattern, ref_ty| Pat { + ty: ref_ty.clone(), + kind: Box::new(PatKind::Deref { subpattern }), + }, + ) } fn lower_pattern_unadjusted(&mut self, pat: hir_def::expr::PatId) -> Pat { @@ -1236,6 +1245,21 @@ fn main(f: Foo) { ); } + #[test] + fn match_ergonomics_issue_9095() { + check_diagnostics( + r#" +enum Foo { A(T) } +fn main() { + match &Foo::A(true) { + _ => {} + Foo::A(_) => {} + } +} +"#, + ); + } + mod false_negatives { //! The implementation of match checking here is a work in progress. As we roll this out, we //! prefer false negatives to false positives (ideally there would be no false positives). This diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 7a4268819..0e9f777da 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -150,6 +150,8 @@ pub struct InferenceResult { type_mismatches: FxHashMap, /// Interned Unknown to return references to. standard_types: InternedStandardTypes, + /// Stores the types which were implicitly dereferenced in pattern binding modes. + pub pat_adjustments: FxHashMap>, } impl InferenceResult { diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index 83e0a7a9e..a21f44d6a 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs @@ -101,7 +101,9 @@ impl<'a> InferenceContext<'a> { let mut expected = self.resolve_ty_shallow(expected); if is_non_ref_pat(&body, pat) { + let mut pat_adjustments = Vec::new(); while let Some((inner, _lifetime, mutability)) = expected.as_reference() { + pat_adjustments.push(expected.clone()); expected = self.resolve_ty_shallow(inner); default_bm = match default_bm { BindingMode::Move => BindingMode::Ref(mutability), @@ -109,6 +111,11 @@ impl<'a> InferenceContext<'a> { BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability), } } + + if !pat_adjustments.is_empty() { + pat_adjustments.shrink_to_fit(); + self.result.pat_adjustments.insert(pat, pat_adjustments); + } } else if let Pat::Ref { .. } = &body[pat] { cov_mark::hit!(match_ergonomics_ref); // When you encounter a `&pat` pattern, reset to Move. -- cgit v1.2.3