@@ -339,9 +339,60 @@ impl PatternFoldable for PatKind {
339
339
}
340
340
341
341
#[ 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
+
343
392
use crate :: diagnostics:: tests:: check_diagnostics;
344
393
394
+ pub ( crate ) use self :: report:: report_bail_out;
395
+
345
396
#[ test]
346
397
fn empty_tuple ( ) {
347
398
check_diagnostics (
@@ -589,14 +640,18 @@ enum Either2 { C, D }
589
640
fn main() {
590
641
match Either::A {
591
642
Either2::C => (),
643
+ // ^^^^^^^^^^ Internal: match check bailed out
592
644
Either2::D => (),
593
645
}
594
646
match (true, false) {
595
647
(true, false, true) => (),
648
+ // ^^^^^^^^^^^^^^^^^^^ Internal: match check bailed out
596
649
(true) => (),
597
650
}
598
651
match (true, false) { (true,) => {} }
652
+ // ^^^^^^^ Internal: match check bailed out
599
653
match (0) { () => () }
654
+ // ^^ Internal: match check bailed out
600
655
match Unresolved::Bar { Unresolved::Baz => () }
601
656
}
602
657
"# ,
@@ -609,7 +664,9 @@ fn main() {
609
664
r#"
610
665
fn main() {
611
666
match false { true | () => {} }
667
+ // ^^^^^^^^^ Internal: match check bailed out
612
668
match (false,) { (true | (),) => {} }
669
+ // ^^^^^^^^^^^^ Internal: match check bailed out
613
670
}
614
671
"# ,
615
672
) ;
@@ -642,10 +699,12 @@ enum Either { A, B }
642
699
fn main() {
643
700
match loop {} {
644
701
Either::A => (),
702
+ // ^^^^^^^^^ Internal: match check bailed out
645
703
Either::B => (),
646
704
}
647
705
match loop {} {
648
706
Either::A => (),
707
+ // ^^^^^^^^^ Internal: match check bailed out
649
708
}
650
709
match loop { break Foo::A } {
651
710
//^^^^^^^^^^^^^^^^^^^^^ Missing match arm
@@ -853,6 +912,11 @@ fn main() {
853
912
match Option::<Never>::None {
854
913
None => (),
855
914
Some(never) => match never {},
915
+ // ^^^^^^^^^^^ Internal: match check bailed out
916
+ }
917
+ match Option::<Never>::None {
918
+ //^^^^^^^^^^^^^^^^^^^^^ Missing match arm
919
+ Option::Some(_never) => {},
856
920
}
857
921
}
858
922
"# ,
@@ -1000,6 +1064,7 @@ fn main(v: S) {
1000
1064
match v { S{ a } => {} }
1001
1065
match v { S{ a: _x } => {} }
1002
1066
match v { S{ a: 'a' } => {} }
1067
+ //^^^^^^^^^^^ Internal: match check bailed out
1003
1068
match v { S{..} => {} }
1004
1069
match v { _ => {} }
1005
1070
match v { }
@@ -1045,6 +1110,7 @@ fn main() {
1045
1110
fn main() {
1046
1111
match 5 {
1047
1112
10 => (),
1113
+ // ^^ Internal: match check bailed out
1048
1114
11..20 => (),
1049
1115
}
1050
1116
}
0 commit comments