@@ -26,15 +26,7 @@ use rustc_index::Idx;
2626use rustc_middle:: ty:: Ty ;
2727
2828use crate :: constructor:: { Constructor , ConstructorSet } ;
29- #[ cfg( feature = "rustc" ) ]
30- use crate :: lints:: {
31- lint_nonexhaustive_missing_variants, lint_overlapping_range_endpoints, PatternColumn ,
32- } ;
3329use crate :: pat:: DeconstructedPat ;
34- #[ cfg( feature = "rustc" ) ]
35- use crate :: rustc:: RustcMatchCheckCtxt ;
36- #[ cfg( feature = "rustc" ) ]
37- use crate :: usefulness:: { compute_match_usefulness, ValidityConstraint } ;
3830
3931// It's not possible to only enable the `typed_arena` dependency when the `rustc` feature is off, so
4032// 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> {}
110102/// useful, and runs some lints.
111103#[ cfg( feature = "rustc" ) ]
112104pub fn analyze_match < ' p , ' tcx > (
113- tycx : & RustcMatchCheckCtxt < ' p , ' tcx > ,
105+ tycx : & rustc :: RustcMatchCheckCtxt < ' p , ' tcx > ,
114106 arms : & [ rustc:: MatchArm < ' p , ' tcx > ] ,
115107 scrut_ty : Ty < ' tcx > ,
116108) -> rustc:: UsefulnessReport < ' p , ' tcx > {
109+ use rustc_middle:: ty;
110+ use rustc_session:: lint;
111+
117112 // Arena to store the extra wildcards we construct during analysis.
118113 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 ) ;
120115 let cx = MatchCtxt { tycx, wildcard_arena } ;
121116
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) ;
123152
124- let pat_column = PatternColumn :: new ( arms) ;
153+ let pat_column = lints :: PatternColumn :: new ( arms) ;
125154
126155 // 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) ;
128157
129158 // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
130159 // `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
131160 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)
133162 }
134163
135164 report
0 commit comments