Skip to content

Commit f46a42f

Browse files
committed
Better tests: check if match checking bails out.
1 parent e84efc4 commit f46a42f

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

crates/hir_ty/src/diagnostics/expr.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
346346
// fit the match expression, we skip this diagnostic. Skipping the entire
347347
// diagnostic rather than just not including this match arm is preferred
348348
// to avoid the chance of false positives.
349+
#[cfg(test)]
350+
match_check::tests::report_bail_out(db, self.owner, arm.pat, self.sink);
349351
return;
350352
}
351353

crates/hir_ty/src/diagnostics/match_check.rs

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,60 @@ impl PatternFoldable for PatKind {
339339
}
340340

341341
#[cfg(test)]
342-
mod tests {
342+
pub(super) mod tests {
343+
mod report {
344+
use std::any::Any;
345+
346+
use hir_def::{expr::PatId, DefWithBodyId};
347+
use hir_expand::{HirFileId, InFile};
348+
use syntax::SyntaxNodePtr;
349+
350+
use crate::{
351+
db::HirDatabase,
352+
diagnostics_sink::{Diagnostic, DiagnosticCode, DiagnosticSink},
353+
};
354+
355+
/// In tests, match check bails out loudly.
356+
/// This helps to catch incorrect tests that pass due to false negatives.
357+
pub(crate) fn report_bail_out(
358+
db: &dyn HirDatabase,
359+
def: DefWithBodyId,
360+
pat: PatId,
361+
sink: &mut DiagnosticSink,
362+
) {
363+
let (_, source_map) = db.body_with_source_map(def);
364+
if let Ok(source_ptr) = source_map.pat_syntax(pat) {
365+
let pat_syntax_ptr = source_ptr.value.either(Into::into, Into::into);
366+
sink.push(BailedOut { file: source_ptr.file_id, pat_syntax_ptr });
367+
}
368+
}
369+
370+
#[derive(Debug)]
371+
struct BailedOut {
372+
file: HirFileId,
373+
pat_syntax_ptr: SyntaxNodePtr,
374+
}
375+
376+
impl Diagnostic for BailedOut {
377+
fn code(&self) -> DiagnosticCode {
378+
DiagnosticCode("internal:match-check-bailed-out")
379+
}
380+
fn message(&self) -> String {
381+
format!("Internal: match check bailed out")
382+
}
383+
fn display_source(&self) -> InFile<SyntaxNodePtr> {
384+
InFile { file_id: self.file, value: self.pat_syntax_ptr.clone() }
385+
}
386+
fn as_any(&self) -> &(dyn Any + Send + 'static) {
387+
self
388+
}
389+
}
390+
}
391+
343392
use crate::diagnostics::tests::check_diagnostics;
344393

394+
pub(crate) use self::report::report_bail_out;
395+
345396
#[test]
346397
fn empty_tuple() {
347398
check_diagnostics(
@@ -589,14 +640,18 @@ enum Either2 { C, D }
589640
fn main() {
590641
match Either::A {
591642
Either2::C => (),
643+
// ^^^^^^^^^^ Internal: match check bailed out
592644
Either2::D => (),
593645
}
594646
match (true, false) {
595647
(true, false, true) => (),
648+
// ^^^^^^^^^^^^^^^^^^^ Internal: match check bailed out
596649
(true) => (),
597650
}
598651
match (true, false) { (true,) => {} }
652+
// ^^^^^^^ Internal: match check bailed out
599653
match (0) { () => () }
654+
// ^^ Internal: match check bailed out
600655
match Unresolved::Bar { Unresolved::Baz => () }
601656
}
602657
"#,
@@ -609,7 +664,9 @@ fn main() {
609664
r#"
610665
fn main() {
611666
match false { true | () => {} }
667+
// ^^^^^^^^^ Internal: match check bailed out
612668
match (false,) { (true | (),) => {} }
669+
// ^^^^^^^^^^^^ Internal: match check bailed out
613670
}
614671
"#,
615672
);
@@ -642,10 +699,12 @@ enum Either { A, B }
642699
fn main() {
643700
match loop {} {
644701
Either::A => (),
702+
// ^^^^^^^^^ Internal: match check bailed out
645703
Either::B => (),
646704
}
647705
match loop {} {
648706
Either::A => (),
707+
// ^^^^^^^^^ Internal: match check bailed out
649708
}
650709
match loop { break Foo::A } {
651710
//^^^^^^^^^^^^^^^^^^^^^ Missing match arm
@@ -853,6 +912,11 @@ fn main() {
853912
match Option::<Never>::None {
854913
None => (),
855914
Some(never) => match never {},
915+
// ^^^^^^^^^^^ Internal: match check bailed out
916+
}
917+
match Option::<Never>::None {
918+
//^^^^^^^^^^^^^^^^^^^^^ Missing match arm
919+
Option::Some(_never) => {},
856920
}
857921
}
858922
"#,
@@ -1000,6 +1064,7 @@ fn main(v: S) {
10001064
match v { S{ a } => {} }
10011065
match v { S{ a: _x } => {} }
10021066
match v { S{ a: 'a' } => {} }
1067+
//^^^^^^^^^^^ Internal: match check bailed out
10031068
match v { S{..} => {} }
10041069
match v { _ => {} }
10051070
match v { }
@@ -1045,6 +1110,7 @@ fn main() {
10451110
fn main() {
10461111
match 5 {
10471112
10 => (),
1113+
// ^^ Internal: match check bailed out
10481114
11..20 => (),
10491115
}
10501116
}

0 commit comments

Comments
 (0)