@@ -26,15 +26,7 @@ use rustc_index::Idx;
26
26
use rustc_middle:: ty:: Ty ;
27
27
28
28
use crate :: constructor:: { Constructor , ConstructorSet } ;
29
- #[ cfg( feature = "rustc" ) ]
30
- use crate :: lints:: {
31
- lint_nonexhaustive_missing_variants, lint_overlapping_range_endpoints, PatternColumn ,
32
- } ;
33
29
use crate :: pat:: DeconstructedPat ;
34
- #[ cfg( feature = "rustc" ) ]
35
- use crate :: rustc:: RustcMatchCheckCtxt ;
36
- #[ cfg( feature = "rustc" ) ]
37
- use crate :: usefulness:: { compute_match_usefulness, ValidityConstraint } ;
38
30
39
31
// It's not possible to only enable the `typed_arena` dependency when the `rustc` feature is off, so
40
32
// we use another feature instead. The crate won't compile if one of these isn't enabled.
@@ -110,26 +102,63 @@ impl<'p, Cx: TypeCx> Copy for MatchArm<'p, Cx> {}
110
102
/// useful, and runs some lints.
111
103
#[ cfg( feature = "rustc" ) ]
112
104
pub fn analyze_match < ' p , ' tcx > (
113
- tycx : & RustcMatchCheckCtxt < ' p , ' tcx > ,
105
+ tycx : & rustc :: RustcMatchCheckCtxt < ' p , ' tcx > ,
114
106
arms : & [ rustc:: MatchArm < ' p , ' tcx > ] ,
115
107
scrut_ty : Ty < ' tcx > ,
116
108
) -> rustc:: UsefulnessReport < ' p , ' tcx > {
109
+ use rustc_middle:: ty;
110
+ use rustc_session:: lint;
111
+
117
112
// Arena to store the extra wildcards we construct during analysis.
118
113
let wildcard_arena = tycx. pattern_arena ;
119
- let scrut_validity = ValidityConstraint :: from_bool ( tycx. known_valid_scrutinee ) ;
114
+ let scrut_validity = usefulness :: ValidityConstraint :: from_bool ( tycx. known_valid_scrutinee ) ;
120
115
let cx = MatchCtxt { tycx, wildcard_arena } ;
121
116
122
- let report = compute_match_usefulness ( cx, arms, scrut_ty, scrut_validity) ;
117
+ if !tycx. known_valid_scrutinee && arms. iter ( ) . all ( |arm| arm. has_guard ) {
118
+ let is_directly_empty = match scrut_ty. kind ( ) {
119
+ ty:: Adt ( def, ..) => {
120
+ def. is_enum ( )
121
+ && def. variants ( ) . is_empty ( )
122
+ && !tycx. is_foreign_non_exhaustive_enum ( scrut_ty)
123
+ }
124
+ ty:: Never => true ,
125
+ _ => false ,
126
+ } ;
127
+ if is_directly_empty {
128
+ if tycx. tcx . features ( ) . min_exhaustive_patterns {
129
+ tycx. tcx . emit_spanned_lint (
130
+ lint:: builtin:: EMPTY_MATCH_ON_UNSAFE_PLACE ,
131
+ tycx. match_lint_level ,
132
+ tycx. whole_match_span . unwrap_or ( tycx. scrut_span ) ,
133
+ errors:: EmptyMatchOnUnsafePlace {
134
+ scrut_span : tycx. scrut_span ,
135
+ suggestion : errors:: EmptyMatchOnUnsafePlaceWrapSuggestion {
136
+ scrut_start : tycx. scrut_span . shrink_to_lo ( ) ,
137
+ scrut_end : tycx. scrut_span . shrink_to_hi ( ) ,
138
+ } ,
139
+ } ,
140
+ ) ;
141
+ }
142
+
143
+ // For backwards compability we allow an empty match in this case.
144
+ return rustc:: UsefulnessReport {
145
+ arm_usefulness : Vec :: new ( ) ,
146
+ non_exhaustiveness_witnesses : Vec :: new ( ) ,
147
+ } ;
148
+ }
149
+ }
150
+
151
+ let report = usefulness:: compute_match_usefulness ( cx, arms, scrut_ty, scrut_validity) ;
123
152
124
- let pat_column = PatternColumn :: new ( arms) ;
153
+ let pat_column = lints :: PatternColumn :: new ( arms) ;
125
154
126
155
// Lint on ranges that overlap on their endpoints, which is likely a mistake.
127
- lint_overlapping_range_endpoints ( cx, & pat_column) ;
156
+ lints :: lint_overlapping_range_endpoints ( cx, & pat_column) ;
128
157
129
158
// Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
130
159
// `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
131
160
if tycx. refutable && report. non_exhaustiveness_witnesses . is_empty ( ) {
132
- lint_nonexhaustive_missing_variants ( cx, arms, & pat_column, scrut_ty)
161
+ lints :: lint_nonexhaustive_missing_variants ( cx, arms, & pat_column, scrut_ty)
133
162
}
134
163
135
164
report
0 commit comments