1
1
use super :: deconstruct_pat:: { Constructor , DeconstructedPat } ;
2
2
use super :: usefulness:: {
3
- compute_match_usefulness, MatchArm , MatchCheckCtxt , Reachability , UsefulnessReport ,
3
+ compute_match_usefulness, MatchArm , Reachability , UsefulnessCtxt , UsefulnessReport ,
4
4
} ;
5
- use super :: { deconstructed_to_pat, pat_to_deconstructed, PatCtxt , PatternError } ;
5
+ use super :: { deconstructed_to_pat, pat_to_deconstructed, MatchCheckCtxt , PatCtxt , PatternError } ;
6
6
7
7
use rustc_arena:: TypedArena ;
8
8
use rustc_ast:: Mutability ;
@@ -51,7 +51,7 @@ struct MatchVisitor<'a, 'p, 'tcx> {
51
51
tcx : TyCtxt < ' tcx > ,
52
52
typeck_results : & ' a ty:: TypeckResults < ' tcx > ,
53
53
param_env : ty:: ParamEnv < ' tcx > ,
54
- pattern_arena : & ' p TypedArena < DeconstructedPat < ' p , ' tcx > > ,
54
+ pattern_arena : & ' p TypedArena < DeconstructedPat < ' p , MatchCheckCtxt < ' tcx > > > ,
55
55
}
56
56
57
57
impl < ' tcx > Visitor < ' tcx > for MatchVisitor < ' _ , ' _ , ' tcx > {
@@ -128,10 +128,10 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
128
128
129
129
fn lower_pattern (
130
130
& self ,
131
- cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
131
+ cx : & UsefulnessCtxt < ' p , MatchCheckCtxt < ' tcx > > ,
132
132
pat : & ' tcx hir:: Pat < ' tcx > ,
133
133
have_errors : & mut bool ,
134
- ) -> & ' p DeconstructedPat < ' p , ' tcx > {
134
+ ) -> & ' p DeconstructedPat < ' p , MatchCheckCtxt < ' tcx > > {
135
135
let mut patcx = PatCtxt :: new ( self . tcx , self . param_env , self . typeck_results ) ;
136
136
patcx. include_lint_checks ( ) ;
137
137
let pattern = patcx. lower_pattern ( pat) ;
@@ -143,13 +143,13 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
143
143
pattern
144
144
}
145
145
146
- fn new_cx ( & self , hir_id : HirId ) -> MatchCheckCtxt < ' p , ' tcx > {
147
- MatchCheckCtxt {
146
+ fn new_cx ( & self , hir_id : HirId ) -> UsefulnessCtxt < ' p , MatchCheckCtxt < ' tcx > > {
147
+ let cx = MatchCheckCtxt {
148
148
tcx : self . tcx ,
149
149
param_env : self . param_env ,
150
150
module : self . tcx . parent_module ( hir_id) . to_def_id ( ) ,
151
- pattern_arena : & self . pattern_arena ,
152
- }
151
+ } ;
152
+ UsefulnessCtxt { cx , pattern_arena : & self . pattern_arena }
153
153
}
154
154
155
155
fn check_let ( & mut self , pat : & ' tcx hir:: Pat < ' tcx > , expr : & hir:: Expr < ' _ > , span : Span ) {
@@ -165,15 +165,16 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
165
165
arms : & ' tcx [ hir:: Arm < ' tcx > ] ,
166
166
source : hir:: MatchSource ,
167
167
) {
168
- let mut cx = self . new_cx ( scrut. hir_id ) ;
168
+ let ucx = self . new_cx ( scrut. hir_id ) ;
169
+ let cx = & ucx. cx ;
169
170
170
171
for arm in arms {
171
172
// Check the arm for some things unrelated to exhaustiveness.
172
173
self . check_patterns ( & arm. pat , Refutable ) ;
173
174
if let Some ( hir:: Guard :: IfLet ( ref pat, _) ) = arm. guard {
174
175
self . check_patterns ( pat, Refutable ) ;
175
- let tpat = self . lower_pattern ( & mut cx , pat, & mut false ) ;
176
- check_let_reachability ( & mut cx , pat. hir_id , tpat, tpat. span ( ) ) ;
176
+ let tpat = self . lower_pattern ( & ucx , pat, & mut false ) ;
177
+ check_let_reachability ( & ucx , pat. hir_id , tpat, tpat. span ( ) ) ;
177
178
}
178
179
}
179
180
@@ -182,7 +183,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
182
183
let arms: Vec < _ > = arms
183
184
. iter ( )
184
185
. map ( |hir:: Arm { pat, guard, .. } | MatchArm {
185
- pat : self . lower_pattern ( & mut cx , pat, & mut have_errors) ,
186
+ pat : self . lower_pattern ( & ucx , pat, & mut have_errors) ,
186
187
hir_id : pat. hir_id ,
187
188
has_guard : guard. is_some ( ) ,
188
189
} )
@@ -194,7 +195,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
194
195
}
195
196
196
197
let scrut_ty = self . typeck_results . expr_ty_adjusted ( scrut) ;
197
- let report = compute_match_usefulness ( & cx , & arms, scrut. hir_id , scrut_ty) ;
198
+ let report = compute_match_usefulness ( & ucx , & arms, scrut. hir_id , scrut_ty) ;
198
199
199
200
match source {
200
201
hir:: MatchSource :: ForLoopDesugar | hir:: MatchSource :: Normal => {
@@ -215,12 +216,13 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
215
216
}
216
217
217
218
fn check_irrefutable ( & self , pat : & ' tcx Pat < ' tcx > , origin : & str , sp : Option < Span > ) {
218
- let mut cx = self . new_cx ( pat. hir_id ) ;
219
+ let ucx = self . new_cx ( pat. hir_id ) ;
220
+ let cx = & ucx. cx ;
219
221
220
- let pattern = self . lower_pattern ( & mut cx , pat, & mut false ) ;
222
+ let pattern = self . lower_pattern ( & ucx , pat, & mut false ) ;
221
223
let pattern_ty = pattern. ty ( ) ;
222
224
let arms = vec ! [ MatchArm { pat: pattern, hir_id: pat. hir_id, has_guard: false } ] ;
223
- let report = compute_match_usefulness ( & cx , & arms, pat. hir_id , pattern_ty) ;
225
+ let report = compute_match_usefulness ( & ucx , & arms, pat. hir_id , pattern_ty) ;
224
226
report_exhaustiveness_lints ( & cx, & report) ;
225
227
226
228
// Note: we ignore whether the pattern is unreachable (i.e. whether the type is empty). We
@@ -359,7 +361,7 @@ fn check_for_bindings_named_same_as_variants(
359
361
}
360
362
361
363
/// Checks for common cases of "catchall" patterns that may not be intended as such.
362
- fn pat_is_catchall ( pat : & DeconstructedPat < ' _ , ' _ > ) -> bool {
364
+ fn pat_is_catchall ( pat : & DeconstructedPat < ' _ , MatchCheckCtxt < ' _ > > ) -> bool {
363
365
use Constructor :: * ;
364
366
match pat. ctor ( ) {
365
367
Wildcard => true ,
@@ -440,13 +442,14 @@ fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) {
440
442
}
441
443
442
444
fn check_let_reachability < ' p , ' tcx > (
443
- cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
445
+ ucx : & UsefulnessCtxt < ' p , MatchCheckCtxt < ' tcx > > ,
444
446
pat_id : HirId ,
445
- pat : & ' p DeconstructedPat < ' p , ' tcx > ,
447
+ pat : & ' p DeconstructedPat < ' p , MatchCheckCtxt < ' tcx > > ,
446
448
span : Span ,
447
449
) {
450
+ let cx = & ucx. cx ;
448
451
let arms = [ MatchArm { pat, hir_id : pat_id, has_guard : false } ] ;
449
- let report = compute_match_usefulness ( & cx , & arms, pat_id, pat. ty ( ) ) ;
452
+ let report = compute_match_usefulness ( & ucx , & arms, pat_id, pat. ty ( ) ) ;
450
453
report_exhaustiveness_lints ( & cx, & report) ;
451
454
452
455
// Report if the pattern is unreachable, which can only occur when the type is uninhabited.
@@ -460,8 +463,8 @@ fn check_let_reachability<'p, 'tcx>(
460
463
461
464
/// Report unreachable arms, if any.
462
465
fn report_arm_reachability < ' p , ' tcx > (
463
- cx : & MatchCheckCtxt < ' p , ' tcx > ,
464
- report : & UsefulnessReport < ' p , ' tcx > ,
466
+ cx : & MatchCheckCtxt < ' tcx > ,
467
+ report : & UsefulnessReport < ' p , MatchCheckCtxt < ' tcx > > ,
465
468
) {
466
469
let mut catchall = None ;
467
470
for ( arm, reachability) in report. arm_usefulness . iter ( ) {
@@ -479,8 +482,8 @@ fn report_arm_reachability<'p, 'tcx>(
479
482
480
483
/// Report various things detected during exhaustiveness checking.
481
484
fn report_exhaustiveness_lints < ' p , ' tcx > (
482
- cx : & MatchCheckCtxt < ' p , ' tcx > ,
483
- report : & UsefulnessReport < ' p , ' tcx > ,
485
+ cx : & MatchCheckCtxt < ' tcx > ,
486
+ report : & UsefulnessReport < ' p , MatchCheckCtxt < ' tcx > > ,
484
487
) {
485
488
if !report. unreachable_subpatterns . is_empty ( ) {
486
489
let mut unreachables = report. unreachable_subpatterns . clone ( ) ;
@@ -502,11 +505,11 @@ fn report_exhaustiveness_lints<'p, 'tcx>(
502
505
///
503
506
/// NB: The partner lint for structs lives in `compiler/rustc_typeck/src/check/pat.rs`.
504
507
pub ( super ) fn lint_non_exhaustive_omitted_patterns < ' p , ' tcx > (
505
- cx : & MatchCheckCtxt < ' p , ' tcx > ,
508
+ cx : & MatchCheckCtxt < ' tcx > ,
506
509
scrut_ty : Ty < ' tcx > ,
507
510
span : Span ,
508
511
hir_id : HirId ,
509
- witnesses : & [ DeconstructedPat < ' p , ' tcx > ] ,
512
+ witnesses : & [ DeconstructedPat < ' p , MatchCheckCtxt < ' tcx > > ] ,
510
513
) {
511
514
let joined_patterns = joined_uncovered_patterns ( cx, & witnesses) ;
512
515
cx. tcx . struct_span_lint_hir ( NON_EXHAUSTIVE_OMITTED_PATTERNS , hir_id, span, |build| {
@@ -525,10 +528,10 @@ pub(super) fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
525
528
526
529
/// Lint on likely incorrect range patterns (#63987)
527
530
pub ( super ) fn lint_overlapping_range_endpoints < ' p , ' tcx > (
528
- cx : & MatchCheckCtxt < ' p , ' tcx > ,
531
+ cx : & MatchCheckCtxt < ' tcx > ,
529
532
span : Span ,
530
533
hir_id : HirId ,
531
- overlaps : & [ DeconstructedPat < ' p , ' tcx > ] ,
534
+ overlaps : & [ DeconstructedPat < ' p , MatchCheckCtxt < ' tcx > > ] ,
532
535
) {
533
536
if !overlaps. is_empty ( ) {
534
537
cx. tcx . struct_span_lint_hir ( OVERLAPPING_RANGE_ENDPOINTS , hir_id, span, |lint| {
@@ -548,10 +551,10 @@ pub(super) fn lint_overlapping_range_endpoints<'p, 'tcx>(
548
551
549
552
/// Report that a match is not exhaustive.
550
553
fn non_exhaustive_match < ' p , ' tcx > (
551
- cx : & MatchCheckCtxt < ' p , ' tcx > ,
554
+ cx : & MatchCheckCtxt < ' tcx > ,
552
555
scrut_ty : Ty < ' tcx > ,
553
556
sp : Span ,
554
- witnesses : Vec < DeconstructedPat < ' p , ' tcx > > ,
557
+ witnesses : Vec < DeconstructedPat < ' p , MatchCheckCtxt < ' tcx > > > ,
555
558
is_empty_match : bool ,
556
559
) {
557
560
let non_empty_enum = match scrut_ty. kind ( ) {
@@ -619,8 +622,8 @@ fn non_exhaustive_match<'p, 'tcx>(
619
622
}
620
623
621
624
crate fn joined_uncovered_patterns < ' p , ' tcx > (
622
- cx : & MatchCheckCtxt < ' p , ' tcx > ,
623
- witnesses : & [ DeconstructedPat < ' p , ' tcx > ] ,
625
+ cx : & MatchCheckCtxt < ' tcx > ,
626
+ witnesses : & [ DeconstructedPat < ' p , MatchCheckCtxt < ' tcx > > ] ,
624
627
) -> String {
625
628
const LIMIT : usize = 3 ;
626
629
let pat_to_str = |pat| deconstructed_to_pat ( cx, pat) . to_string ( ) ;
@@ -640,18 +643,18 @@ crate fn joined_uncovered_patterns<'p, 'tcx>(
640
643
}
641
644
642
645
crate fn pattern_not_covered_label (
643
- witnesses : & [ DeconstructedPat < ' _ , ' _ > ] ,
646
+ witnesses : & [ DeconstructedPat < ' _ , MatchCheckCtxt < ' _ > > ] ,
644
647
joined_patterns : & str ,
645
648
) -> String {
646
649
format ! ( "pattern{} {} not covered" , rustc_errors:: pluralize!( witnesses. len( ) ) , joined_patterns)
647
650
}
648
651
649
652
/// Point at the definition of non-covered `enum` variants.
650
653
fn adt_defined_here < ' p , ' tcx > (
651
- cx : & MatchCheckCtxt < ' p , ' tcx > ,
654
+ cx : & MatchCheckCtxt < ' tcx > ,
652
655
err : & mut DiagnosticBuilder < ' _ > ,
653
656
ty : Ty < ' tcx > ,
654
- witnesses : & [ DeconstructedPat < ' p , ' tcx > ] ,
657
+ witnesses : & [ DeconstructedPat < ' p , MatchCheckCtxt < ' tcx > > ] ,
655
658
) {
656
659
let ty = ty. peel_refs ( ) ;
657
660
if let ty:: Adt ( def, _) = ty. kind ( ) {
@@ -668,10 +671,13 @@ fn adt_defined_here<'p, 'tcx>(
668
671
}
669
672
670
673
fn maybe_point_at_variant < ' a , ' p : ' a , ' tcx : ' a > (
671
- cx : & MatchCheckCtxt < ' p , ' tcx > ,
674
+ cx : & MatchCheckCtxt < ' tcx > ,
672
675
def : & AdtDef ,
673
- patterns : impl Iterator < Item = & ' a DeconstructedPat < ' p , ' tcx > > ,
674
- ) -> Vec < Span > {
676
+ patterns : impl Iterator < Item = & ' a DeconstructedPat < ' p , MatchCheckCtxt < ' tcx > > > ,
677
+ ) -> Vec < Span >
678
+ where
679
+ MatchCheckCtxt < ' tcx > : ' p ,
680
+ {
675
681
use Constructor :: * ;
676
682
let mut covered = vec ! [ ] ;
677
683
for pattern in patterns {
0 commit comments